diff options
| author | Willem Jan Palenstijn | 2013-04-18 23:35:23 +0200 |
|---|---|---|
| committer | Willem Jan Palenstijn | 2013-05-08 20:40:58 +0200 |
| commit | 9c2341678ef4984bf92b3878295250faf980b066 (patch) | |
| tree | 2fb4805e05e16b9924e80c9947e6bad723b28c4b /graphics/VectorRendererSpec.cpp | |
| parent | 8172d679df5148a4a32f46074b20cb6caf91844f (diff) | |
| parent | a5f4ff36ffc386d48f2da49387a9655ce9295a4d (diff) | |
| download | scummvm-rg350-9c2341678ef4984bf92b3878295250faf980b066.tar.gz scummvm-rg350-9c2341678ef4984bf92b3878295250faf980b066.tar.bz2 scummvm-rg350-9c2341678ef4984bf92b3878295250faf980b066.zip | |
Merge branch 'master'
Diffstat (limited to 'graphics/VectorRendererSpec.cpp')
| -rw-r--r-- | graphics/VectorRendererSpec.cpp | 1194 |
1 files changed, 836 insertions, 358 deletions
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index a2cb693b78..7817725664 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -77,7 +77,7 @@ inline frac_t fp_sqroot(uint32 x) { HELPER MACROS for Bresenham's circle drawing algorithm Note the proper spelling on this header. */ -#define __BE_ALGORITHM() { \ +#define BE_ALGORITHM() do { \ if (f >= 0) { \ y--; \ ddF_y += 2; \ @@ -87,37 +87,65 @@ inline frac_t fp_sqroot(uint32 x) { px += pitch; \ ddF_x += 2; \ f += ddF_x + 1; \ -} +} while(0) -#define __BE_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py) { \ +#define BE_DRAWCIRCLE_TOP(ptr1,ptr2,x,y,px,py) do { \ *(ptr1 + (y) - (px)) = color; \ *(ptr1 + (x) - (py)) = color; \ *(ptr2 - (x) - (py)) = color; \ *(ptr2 - (y) - (px)) = color; \ +} while (0) + +#define BE_DRAWCIRCLE_BOTTOM(ptr3,ptr4,x,y,px,py) do { \ *(ptr3 - (y) + (px)) = color; \ *(ptr3 - (x) + (py)) = color; \ *(ptr4 + (x) + (py)) = color; \ *(ptr4 + (y) + (px)) = color; \ -} +} while (0) + +#define BE_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py) do { \ + BE_DRAWCIRCLE_TOP(ptr1,ptr2,x,y,px,py); \ + BE_DRAWCIRCLE_BOTTOM(ptr3,ptr4,x,y,px,py); \ +} while (0) + +#define BE_DRAWCIRCLE_BCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py) do { \ + *(ptr1 + (y) - (px)) = color1; \ + *(ptr1 + (x) - (py)) = color1; \ + *(ptr2 - (x) - (py)) = color1; \ + *(ptr2 - (y) - (px)) = color1; \ + *(ptr3 - (y) + (px)) = color1; \ + *(ptr3 - (x) + (py)) = color1; \ + *(ptr4 + (x) + (py)) = color2; \ + *(ptr4 + (y) + (px)) = color2; \ +} while (0) -#define __BE_DRAWCIRCLE_XCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py) { \ +#define BE_DRAWCIRCLE_XCOLOR_TOP(ptr1,ptr2,x,y,px,py) do { \ *(ptr1 + (y) - (px)) = color1; \ *(ptr1 + (x) - (py)) = color2; \ *(ptr2 - (x) - (py)) = color2; \ *(ptr2 - (y) - (px)) = color1; \ +} while (0) + +#define BE_DRAWCIRCLE_XCOLOR_BOTTOM(ptr3,ptr4,x,y,px,py) do { \ *(ptr3 - (y) + (px)) = color3; \ *(ptr3 - (x) + (py)) = color4; \ *(ptr4 + (x) + (py)) = color4; \ *(ptr4 + (y) + (px)) = color3; \ -} +} while (0) + +#define BE_DRAWCIRCLE_XCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py) do { \ + BE_DRAWCIRCLE_XCOLOR_TOP(ptr1,ptr2,x,y,px,py); \ + BE_DRAWCIRCLE_XCOLOR_BOTTOM(ptr3,ptr4,x,y,px,py); \ +} while (0) + -#define __BE_RESET() { \ +#define BE_RESET() do { \ f = 1 - r; \ ddF_x = 0; ddF_y = -2 * r; \ x = 0; y = r; px = 0; py = pitch * r; \ -} +} while (0) -#define __TRIANGLE_MAINX() \ +#define TRIANGLE_MAINX() \ if (error_term >= 0) { \ ptr_right += pitch; \ ptr_left += pitch; \ @@ -128,7 +156,7 @@ inline frac_t fp_sqroot(uint32 x) { ptr_right++; \ ptr_left--; -#define __TRIANGLE_MAINY() \ +#define TRIANGLE_MAINY() \ if (error_term >= 0) { \ ptr_right++; \ ptr_left--; \ @@ -140,19 +168,63 @@ inline frac_t fp_sqroot(uint32 x) { ptr_left += pitch; /** HELPER MACROS for WU's circle drawing algorithm **/ -#define __WU_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a) { \ +#define WU_DRAWCIRCLE_TOP(ptr1,ptr2,x,y,px,py,a) do { \ this->blendPixelPtr(ptr1 + (y) - (px), color, a); \ this->blendPixelPtr(ptr1 + (x) - (py), color, a); \ this->blendPixelPtr(ptr2 - (x) - (py), color, a); \ this->blendPixelPtr(ptr2 - (y) - (px), color, a); \ +} while (0) + +#define WU_DRAWCIRCLE_BOTTOM(ptr3,ptr4,x,y,px,py,a) do { \ this->blendPixelPtr(ptr3 - (y) + (px), color, a); \ this->blendPixelPtr(ptr3 - (x) + (py), color, a); \ this->blendPixelPtr(ptr4 + (x) + (py), color, a); \ this->blendPixelPtr(ptr4 + (y) + (px), color, a); \ -} +} while (0) + +#define WU_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a) do { \ + WU_DRAWCIRCLE_TOP(ptr1,ptr2,x,y,px,py,a); \ + WU_DRAWCIRCLE_BOTTOM(ptr3,ptr4,x,y,px,py,a); \ +} while (0) + + +// Color depending on y +// Note: this is only for the outer pixels +#define WU_DRAWCIRCLE_XCOLOR_TOP(ptr1,ptr2,x,y,px,py,a,func) do { \ + this->func(ptr1 + (y) - (px), color1, a); \ + this->func(ptr1 + (x) - (py), color2, a); \ + this->func(ptr2 - (x) - (py), color2, a); \ + this->func(ptr2 - (y) - (px), color1, a); \ +} while (0) + +#define WU_DRAWCIRCLE_XCOLOR_BOTTOM(ptr3,ptr4,x,y,px,py,a,func) do { \ + this->func(ptr3 - (y) + (px), color3, a); \ + this->func(ptr3 - (x) + (py), color4, a); \ + this->func(ptr4 + (x) + (py), color4, a); \ + this->func(ptr4 + (y) + (px), color3, a); \ +} while (0) + +#define WU_DRAWCIRCLE_XCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a,func) do { \ + WU_DRAWCIRCLE_XCOLOR_TOP(ptr1,ptr2,x,y,px,py,a,func); \ + WU_DRAWCIRCLE_XCOLOR_BOTTOM(ptr3,ptr4,x,y,px,py,a,func); \ +} while (0) + +// Color depending on corner (tl,tr,bl: color1, br: color2) +// Note: this is only for the outer pixels +#define WU_DRAWCIRCLE_BCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a) do { \ + this->blendPixelPtr(ptr1 + (y) - (px), color1, a); \ + this->blendPixelPtr(ptr1 + (x) - (py), color1, a); \ + this->blendPixelPtr(ptr2 - (x) - (py), color1, a); \ + this->blendPixelPtr(ptr2 - (y) - (px), color1, a); \ + this->blendPixelPtr(ptr3 - (y) + (px), color1, a); \ + this->blendPixelPtr(ptr3 - (x) + (py), color1, a); \ + this->blendPixelPtr(ptr4 + (x) + (py), color2, a); \ + this->blendPixelPtr(ptr4 + (y) + (px), color2, a); \ +} while (0) + // optimized Wu's algorithm -#define __WU_ALGORITHM() { \ +#define WU_ALGORITHM() do { \ oldT = T; \ T = fp_sqroot(rsq - y*y) ^ 0xFFFF; \ py += pitch; \ @@ -160,8 +232,8 @@ inline frac_t fp_sqroot(uint32 x) { x--; px -= pitch; \ } \ a2 = (T >> 8); \ - a1 = ~a2 >> 4; \ -} + a1 = ~a2; \ +} while (0) namespace Graphics { @@ -169,7 +241,7 @@ namespace Graphics { /** * Fills several pixels in a row with a given color. * - * This is a replacement function for Common::set_to, using an unrolled + * This is a replacement function for Common::fill, using an unrolled * loop to maximize performance on most architectures. * This function may (and should) be overloaded in any child renderers * for portable platforms with platform-specific assembly code. @@ -224,17 +296,6 @@ VectorRenderer *createRenderer(int mode) { } template<typename PixelType> -void VectorRendererSpec<PixelType>:: -setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) { - _gradientEnd = _format.RGBToColor(r2, g2, b2); - _gradientStart = _format.RGBToColor(r1, g1, b1); - - Base::_gradientBytes[0] = (_gradientEnd & _redMask) - (_gradientStart & _redMask); - Base::_gradientBytes[1] = (_gradientEnd & _greenMask) - (_gradientStart & _greenMask); - Base::_gradientBytes[2] = (_gradientEnd & _blueMask) - (_gradientStart & _blueMask); -} - -template<typename PixelType> VectorRendererSpec<PixelType>:: VectorRendererSpec(PixelFormat format) : _format(format), @@ -246,6 +307,93 @@ VectorRendererSpec(PixelFormat format) : _bitmapAlphaColor = _format.RGBToColor(255, 0, 255); } +/**************************** + * Gradient-related methods * + ****************************/ + +template<typename PixelType> +void VectorRendererSpec<PixelType>:: +setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) { + _gradientEnd = _format.RGBToColor(r2, g2, b2); + _gradientStart = _format.RGBToColor(r1, g1, b1); + + _gradientBytes[0] = (_gradientEnd & _redMask) - (_gradientStart & _redMask); + _gradientBytes[1] = (_gradientEnd & _greenMask) - (_gradientStart & _greenMask); + _gradientBytes[2] = (_gradientEnd & _blueMask) - (_gradientStart & _blueMask); +} + +template<typename PixelType> +inline PixelType VectorRendererSpec<PixelType>:: +calcGradient(uint32 pos, uint32 max) { + PixelType output = 0; + pos = (MIN(pos * Base::_gradientFactor, max) << 12) / max; + + output |= ((_gradientStart & _redMask) + ((_gradientBytes[0] * pos) >> 12)) & _redMask; + output |= ((_gradientStart & _greenMask) + ((_gradientBytes[1] * pos) >> 12)) & _greenMask; + output |= ((_gradientStart & _blueMask) + ((_gradientBytes[2] * pos) >> 12)) & _blueMask; + output |= _alphaMask; + + return output; +} + +template<typename PixelType> +void VectorRendererSpec<PixelType>:: +precalcGradient(int h) { + PixelType prevcolor = 0, color; + + _gradCache.resize(0); + _gradIndexes.resize(0); + + for (int i = 0; i < h + 2; i++) { + color = calcGradient(i, h); + if (color != prevcolor || i == 0 || i > h - 1) { + prevcolor = color; + _gradCache.push_back(color); + _gradIndexes.push_back(i); + } + } +} + +template<typename PixelType> +void VectorRendererSpec<PixelType>:: +gradientFill(PixelType *ptr, int width, int x, int y) { + bool ox = ((y & 1) == 1); + int stripSize; + int curGrad = 0; + + while (_gradIndexes[curGrad + 1] <= y) + curGrad++; + + stripSize = _gradIndexes[curGrad + 1] - _gradIndexes[curGrad]; + + int grad = (((y - _gradIndexes[curGrad]) % stripSize) << 2) / stripSize; + + // Dithering: + // +--+ +--+ +--+ +--+ + // | | | | | *| | *| + // | | | *| |* | |**| + // +--+ +--+ +--+ +--+ + // 0 1 2 3 + if (grad == 0 || + _gradCache[curGrad] == _gradCache[curGrad + 1] || // no color change + stripSize < 2) { // the stip is small + colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad]); + } else if (grad == 3 && ox) { + colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad + 1]); + } else { + for (int j = x; j < x + width; j++, ptr++) { + bool oy = ((j & 1) == 1); + + if ((ox && oy) || + ((grad == 2 || grad == 3) && ox && !oy) || + (grad == 3 && oy)) + *ptr = _gradCache[curGrad + 1]; + else + *ptr = _gradCache[curGrad]; + } + } +} + template<typename PixelType> void VectorRendererSpec<PixelType>:: fillSurface() { @@ -259,9 +407,11 @@ fillSurface() { } else if (Base::_fillMode == kFillForeground) { colorFill<PixelType>((PixelType *)ptr, (PixelType *)(ptr + pitch * h), _fgColor); } else if (Base::_fillMode == kFillGradient) { - int i = h; - while (i--) { - colorFill<PixelType>((PixelType *)ptr, (PixelType *)(ptr + pitch), calcGradient(h - i, h)); + precalcGradient(h); + + for (int i = 0; i < h; i++) { + gradientFill((PixelType *)ptr, _activeSurface->w, 0, i); + ptr += pitch; } } @@ -369,18 +519,10 @@ applyScreenShading(GUI::ThemeEngine::ShadingStyle shadingStyle) { if (shadingStyle == GUI::ThemeEngine::kShadingDim) { - int n = (pixels + 7) >> 3; - switch (pixels % 8) { - case 0: do { - *ptr = (*ptr & colorMask) >> 1; ++ptr; - case 7: *ptr = (*ptr & colorMask) >> 1; ++ptr; - case 6: *ptr = (*ptr & colorMask) >> 1; ++ptr; - case 5: *ptr = (*ptr & colorMask) >> 1; ++ptr; - case 4: *ptr = (*ptr & colorMask) >> 1; ++ptr; - case 3: *ptr = (*ptr & colorMask) >> 1; ++ptr; - case 2: *ptr = (*ptr & colorMask) >> 1; ++ptr; - case 1: *ptr = (*ptr & colorMask) >> 1; ++ptr; - } while (--n > 0); + // TODO: Check how this interacts with kFeatureOverlaySupportsAlpha + for (int i = 0; i < pixels; ++i) { + *ptr = ((*ptr & colorMask) >> 1) | _alphaMask; + ++ptr; } } else if (shadingStyle == GUI::ThemeEngine::kShadingLuminance) { @@ -395,8 +537,8 @@ applyScreenShading(GUI::ThemeEngine::ShadingStyle shadingStyle) { template<typename PixelType> inline void VectorRendererSpec<PixelType>:: blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { - register int idst = *ptr; - register int isrc = color; + int idst = *ptr; + int isrc = color; *ptr = (PixelType)( (_redMask & ((idst & _redMask) + @@ -408,23 +550,53 @@ blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { (_blueMask & ((idst & _blueMask) + ((int)(((int)(isrc & _blueMask) - (int)(idst & _blueMask)) * alpha) >> 8))) | - (_alphaMask & ((idst & _alphaMask) + - ((alpha >> _format.aLoss) << _format.aShift) - - (((int)(idst & _alphaMask) * alpha) >> 8)))); + (idst & _alphaMask)); } template<typename PixelType> -inline PixelType VectorRendererSpec<PixelType>:: -calcGradient(uint32 pos, uint32 max) { - PixelType output = 0; - pos = (MIN(pos * Base::_gradientFactor, max) << 12) / max; +inline void VectorRendererSpec<PixelType>:: +blendPixelDestAlphaPtr(PixelType *ptr, PixelType color, uint8 alpha) { + int idst = *ptr; + // This function is only used for corner pixels in rounded rectangles, so + // the performance hit of this if shouldn't be too high. + // We're also ignoring the cases where dst has intermediate alpha. + if ((idst & _alphaMask) == 0) { + // set color and alpha channels + *ptr = (PixelType)(color & (_redMask | _greenMask | _blueMask)) | + ((alpha >> _format.aLoss) << _format.aShift); + } else { + // blend color with background + blendPixelPtr(ptr, color, alpha); + } +} - output |= ((_gradientStart & _redMask) + ((Base::_gradientBytes[0] * pos) >> 12)) & _redMask; - output |= ((_gradientStart & _greenMask) + ((Base::_gradientBytes[1] * pos) >> 12)) & _greenMask; - output |= ((_gradientStart & _blueMask) + ((Base::_gradientBytes[2] * pos) >> 12)) & _blueMask; - output |= _alphaMask; +template<typename PixelType> +inline void VectorRendererSpec<PixelType>:: +darkenFill(PixelType *ptr, PixelType *end) { + PixelType mask = (PixelType)((3 << _format.rShift) | (3 << _format.gShift) | (3 << _format.bShift)); - return output; + if (!g_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha)) { + // !kFeatureOverlaySupportsAlpha (but might have alpha bits) + + while (ptr != end) { + *ptr = ((*ptr & ~mask) >> 2) | _alphaMask; + ++ptr; + } + } else { + // kFeatureOverlaySupportsAlpha + // assuming at least 3 alpha bits + + mask |= 3 << _format.aShift; + PixelType addA = (PixelType)(255 >> _format.aLoss) << _format.aShift; + addA -= (addA >> 2); + + while (ptr != end) { + // Darken the colour, and increase the alpha + // (0% -> 75%, 100% -> 100%) + *ptr = (PixelType)(((*ptr & ~mask) >> 2) + addA); + ++ptr; + } + } } /******************************************************************** @@ -601,42 +773,16 @@ drawRoundedSquare(int x, int y, int r, int w, int h) { if ((r * 2) > w || (r * 2) > h) r = MIN(w /2, h / 2); + if (r <= 0) + return; + if (Base::_fillMode != kFillDisabled && Base::_shadowOffset && x + w + Base::_shadowOffset + 1 < Base::_activeSurface->w && y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h) { drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset); } - switch (Base::_fillMode) { - case kFillDisabled: - if (Base::_strokeWidth) - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillDisabled); - break; - - case kFillForeground: - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillForeground); - break; - - case kFillBackground: - VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, _bgColor, kFillBackground); - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillDisabled); - break; - - case kFillGradient: - if (Base::_strokeWidth > 1) { - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillForeground); - VectorRendererSpec::drawRoundedSquareAlg(x + Base::_strokeWidth/2, y + Base::_strokeWidth/2, - r - Base::_strokeWidth/2, w - Base::_strokeWidth, h - Base::_strokeWidth, 0, kFillGradient); - } else { - VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, 0, kFillGradient); - if (Base::_strokeWidth) - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kFillDisabled); - } - break; - } - - if (Base::_bevel) - drawRoundedSquareFakeBevel(x, y, r, w, h, Base::_bevel); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, Base::_fillMode); } template<typename PixelType> @@ -655,10 +801,14 @@ drawTab(int x, int y, int r, int w, int h) { switch (Base::_fillMode) { case kFillDisabled: + // FIXME: Implement this return; case kFillGradient: case kFillBackground: + // FIXME: This is broken for the AA renderer. + // See the rounded rect alg for how to fix it. (The border should + // be drawn before the interior, both inside drawTabAlg.) drawTabAlg(x, y, w, h, r, (Base::_fillMode == kFillBackground) ? _bgColor : _fgColor, Base::_fillMode); if (Base::_strokeWidth) drawTabAlg(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF)); @@ -693,25 +843,49 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) { if (Base::_dynamicData != 0) orient = (TriangleOrientation)Base::_dynamicData; - int newW = w / 2; - if (newW % 2) newW++; + if (w == h) { + int newW = w; - switch (orient) { + switch (orient) { case kTriangleUp: case kTriangleDown: - drawTriangleFast(x + (newW / 2), y + (h / 2) - (newW / 2), newW, (orient == kTriangleDown), color, Base::_fillMode); + //drawTriangleFast(x, y, newW, (orient == kTriangleDown), color, Base::_fillMode); + drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode); break; case kTriangleLeft: case kTriangleRight: case kTriangleAuto: break; - } + } + + if (Base::_strokeWidth > 0) + if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) { + //drawTriangleFast(x, y, newW, (orient == kTriangleDown), _fgColor, kFillDisabled); + drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode); + } + } else { + int newW = w; + int newH = h; + + switch (orient) { + case kTriangleUp: + case kTriangleDown: + drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), color, Base::_fillMode); + break; + + case kTriangleLeft: + case kTriangleRight: + case kTriangleAuto: + break; + } - if (Base::_strokeWidth > 0) - if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) { - drawTriangleFast(x + (newW / 2), y + (h / 2) - (newW / 2), newW, (orient == kTriangleDown), _fgColor, kFillDisabled); + if (Base::_strokeWidth > 0) { + if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) { + drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), _fgColor, kFillDisabled); + } } + } } @@ -746,22 +920,15 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: colorFill<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); sp += pitch; - __BE_RESET(); + BE_RESET(); r--; while (x++ < y) { - __BE_ALGORITHM(); - *(ptr_tr + (y) - (px)) = color; - *(ptr_tr + (x) - (py)) = color; - *(ptr_tl - (x) - (py)) = color; - *(ptr_tl - (y) - (px)) = color; + BE_ALGORITHM(); + BE_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px, py); - if (Base::_strokeWidth > 1) { - *(ptr_tr + (y) - (px - pitch)) = color; - *(ptr_tr + (x) - (py)) = color; - *(ptr_tl - (x) - (py)) = color; - *(ptr_tl - (y) - (px - pitch)) = color; - } + if (Base::_strokeWidth > 1) + BE_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px - pitch, py); } } @@ -790,33 +957,39 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: } } } else { - __BE_RESET(); + BE_RESET(); + + precalcGradient(long_h); PixelType color1, color2; color1 = color2 = color; while (x++ < y) { - __BE_ALGORITHM(); + BE_ALGORITHM(); if (fill_m == kFillGradient) { color1 = calcGradient(real_radius - x, long_h); color2 = calcGradient(real_radius - y, long_h); - } - colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color2); - colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color1); + gradientFill(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y); + gradientFill(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x); - *(ptr_tr + (y) - (px)) = color1; - *(ptr_tr + (x) - (py)) = color2; - *(ptr_tl - (x) - (py)) = color2; - *(ptr_tl - (y) - (px)) = color1; + BE_DRAWCIRCLE_XCOLOR_TOP(ptr_tr, ptr_tl, x, y, px, py); + } else { + colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color); + colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color); + + BE_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px, py); + } } ptr_fill += pitch * r; while (short_h--) { - if (fill_m == kFillGradient) - color = calcGradient(real_radius++, long_h); - colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color); + if (fill_m == kFillGradient) { + gradientFill(ptr_fill, w + 1, x1, real_radius++); + } else { + colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color); + } ptr_fill += pitch; } } @@ -910,8 +1083,9 @@ drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, P PixelType *ptr_fill = (PixelType *)_activeSurface->getBasePtr(x, y); if (fill) { + assert((_bgColor & ~_alphaMask) == 0); // only support black while (height--) { - blendFill(ptr_fill, ptr_fill + w, _bgColor, 200); + darkenFill(ptr_fill, ptr_fill + w); ptr_fill += pitch; } } @@ -1005,130 +1179,249 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { } /** VERTICAL TRIANGLE DRAWING ALGORITHM **/ +/** + FIXED POINT ARITHMETIC +**/ + +#define FIXED_POINT 1 + +#if FIXED_POINT +#define ipart(x) ((x) & ~0xFF) +// This is not really correct since gradient is not percentage, but [0..255] +#define rfpart(x) ((0x100 - ((x) & 0xFF)) * 100 >> 8) +//#define rfpart(x) (0x100 - ((x) & 0xFF)) +#else +#define ipart(x) ((int)x) +#define round(x) (ipart(x + 0.5)) +#define fpart(x) (x - ipart(x)) +#define rfpart(x) (int)((1 - fpart(x)) * 100) +#endif + template<typename PixelType> void VectorRendererSpec<PixelType>:: drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) { - int dx = w >> 1, dy = h, gradient_h = 0; int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; - PixelType *ptr_right = 0, *ptr_left = 0; - - if (inverted) { - ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1); - ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + w, y1); - } else { - ptr_right = ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + dx, y1); + int gradient_h = 0; + if (!inverted) { + pitch = -pitch; + y1 += h; } + + PixelType *ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1); + PixelType *floor = ptr_right - 1; + PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + w, y1); + + int x2 = x1 + w / 2; + int y2 = y1 + h; + +#if FIXED_POINT + int dx = (x2 - x1) << 8; + int dy = (y2 - y1) << 8; + + if (abs(dx) > abs(dy)) { +#else + double dx = (double)x2 - (double)x1; + double dy = (double)y2 - (double)y1; - if (dx > dy) { - int ddy = dy * 2; - int dysub = ddy - (dx * 2); - int error_term = ddy - dx; + if (fabs(dx) > fabs(dy)) { +#endif + while (floor++ != ptr_left) + blendPixelPtr(floor, color, 50); + +#if FIXED_POINT + int gradient = (dy << 8) / dx; + int intery = (y1 << 8) + gradient; +#else + double gradient = dy / dx; + double intery = y1 + gradient; +#endif - switch (fill_m) { - case kFillDisabled: - while (dx--) { - __TRIANGLE_MAINX(); - *ptr_right = color; - *ptr_left = color; + for (int x = x1 + 1; x < x2; x++) { +#if FIXED_POINT + if (intery + gradient > ipart(intery) + 0x100) { +#else + if (intery + gradient > ipart(intery) + 1) { +#endif + ptr_right++; + ptr_left--; } - colorFill<PixelType>(ptr_left, ptr_right, color); - break; - case kFillForeground: - case kFillBackground: - while (dx--) { - __TRIANGLE_MAINX(); - if (inverted) colorFill<PixelType>(ptr_right, ptr_left, color); - else colorFill<PixelType>(ptr_left, ptr_right, color); + ptr_left += pitch; + ptr_right += pitch; + + intery += gradient; + + switch (fill_m) { + case kFillDisabled: + *ptr_left = *ptr_right = color; + break; + case kFillForeground: + case kFillBackground: + colorFill<PixelType>(ptr_right + 1, ptr_left, color); + blendPixelPtr(ptr_right, color, rfpart(intery)); + blendPixelPtr(ptr_left, color, rfpart(intery)); + break; + case kFillGradient: + colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h)); + blendPixelPtr(ptr_right, color, rfpart(intery)); + blendPixelPtr(ptr_left, color, rfpart(intery)); + break; } - break; + } + + return; + } + +#if FIXED_POINT + if (abs(dx) < abs(dy)) { +#else + if (fabs(dx) < fabs(dy)) { +#endif + ptr_left--; + while (floor++ != ptr_left) + blendPixelPtr(floor, color, 50); + +#if FIXED_POINT + int gradient = (dx << 8) / (dy + 0x100); + int interx = (x1 << 8) + gradient; +#else + double gradient = dx / (dy+1); + double interx = x1 + gradient; +#endif - case kFillGradient: - while (dx--) { - __TRIANGLE_MAINX(); - if (inverted) colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h)); - else colorFill<PixelType>(ptr_left, ptr_right, calcGradient(gradient_h++, h)); + for (int y = y1 + 1; y < y2; y++) { +#if FIXED_POINT + if (interx + gradient > ipart(interx) + 0x100) { +#else + if (interx + gradient > ipart(interx) + 1) { +#endif + ptr_right++; + ptr_left--; + } + + ptr_left += pitch; + ptr_right += pitch; + + interx += gradient; + + switch (fill_m) { + case kFillDisabled: + *ptr_left = *ptr_right = color; + break; + case kFillForeground: + case kFillBackground: + colorFill<PixelType>(ptr_right + 1, ptr_left, color); + blendPixelPtr(ptr_right, color, rfpart(interx)); + blendPixelPtr(ptr_left, color, rfpart(interx)); + break; + case kFillGradient: + colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h)); + blendPixelPtr(ptr_right, color, rfpart(interx)); + blendPixelPtr(ptr_left, color, rfpart(interx)); + break; } - break; } - } else { - int ddx = dx * 2; - int dxsub = ddx - (dy * 2); - int error_term = ddx - dy; + + return; + } + + ptr_left--; + + while (floor++ != ptr_left) + blendPixelPtr(floor, color, 50); + +#if FIXED_POINT + int gradient = (dx / dy) << 8; + int interx = (x1 << 8) + gradient; +#else + double gradient = dx / dy; + double interx = x1 + gradient; +#endif + + for (int y = y1 + 1; y < y2; y++) { + ptr_right++; + ptr_left--; + + ptr_left += pitch; + ptr_right += pitch; + interx += gradient; + switch (fill_m) { case kFillDisabled: - while (dy--) { - __TRIANGLE_MAINY(); - *ptr_right = color; - *ptr_left = color; - } - colorFill<PixelType>(ptr_left, ptr_right, color); + *ptr_left = *ptr_right = color; break; - case kFillForeground: case kFillBackground: - while (dy--) { - __TRIANGLE_MAINY(); - if (inverted) colorFill<PixelType>(ptr_right, ptr_left, color); - else colorFill<PixelType>(ptr_left, ptr_right, color); - } + colorFill<PixelType>(ptr_right + 1, ptr_left, color); + blendPixelPtr(ptr_right, color, rfpart(interx)); + blendPixelPtr(ptr_left, color, rfpart(interx)); break; case kFillGradient: - while (dy--) { - __TRIANGLE_MAINY(); - if (inverted) colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h)); - else colorFill<PixelType>(ptr_left, ptr_right, calcGradient(gradient_h++, h)); - } + colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h)); + blendPixelPtr(ptr_right, color, rfpart(interx)); + blendPixelPtr(ptr_left, color, rfpart(interx)); break; } } + } - /** VERTICAL TRIANGLE DRAWING - FAST VERSION FOR SQUARED TRIANGLES */ template<typename PixelType> void VectorRendererSpec<PixelType>:: drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) { int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; - int hstep = 0, dy = size; - bool grad = (fill_m == kFillGradient); - - PixelType *ptr_right = 0, *ptr_left = 0; - - if (x1 + size > Base::_activeSurface->w || x1 < 0 || - y1 + size > Base::_activeSurface->h || y1 < 0) - return; - - if (inverted) { - ptr_left = (PixelType *)_activeSurface->getBasePtr(x1, y1); - ptr_right = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1); - } else { - ptr_left = (PixelType *)_activeSurface->getBasePtr(x1, y1 + size); - ptr_right = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1 + size); + + if (!inverted) { pitch = -pitch; + y1 += size; } - - if (fill_m == kFillDisabled) { - while (ptr_left < ptr_right) { - *ptr_left = color; - *ptr_right = color; - ptr_left += pitch; - ptr_right += pitch; - if (hstep++ % 2) { - ptr_left++; - ptr_right--; - } + + int gradient_h = 0; + PixelType *ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1); + PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + size, y1); + int x2 = x1 + size / 2; + int y2 = y1 + size; + int deltaX = abs(x2 - x1); + int deltaY = abs(y2 - y1); + int signX = x1 < x2 ? 1 : -1; + int signY = y1 < y2 ? 1 : -1; + int error = deltaX - deltaY; + + colorFill<PixelType>(ptr_right, ptr_left, color); + + while (1) { + switch (fill_m) { + case kFillDisabled: + *ptr_left = *ptr_right = color; + break; + case kFillForeground: + case kFillBackground: + colorFill<PixelType>(ptr_right, ptr_left, color); + break; + case kFillGradient: + colorFill<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, size)); + break; } - } else { - while (ptr_left < ptr_right) { - colorFill<PixelType>(ptr_left, ptr_right, grad ? calcGradient(dy--, size) : color); - ptr_left += pitch; + + if (x1 == x2 && y1 == y2) + break; + + int error2 = error * 2; + + if (error2 > -deltaY) { + error -= deltaY; + x1 += signX; + ptr_right += signX; + ptr_left += -signX; + } + + if (error2 < deltaX) { + error += deltaX; + y1 += signY; ptr_right += pitch; - if (hstep++ % 2) { - ptr_left++; - ptr_right--; - } + ptr_left += pitch; } } } @@ -1140,85 +1433,113 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto int f, ddF_x, ddF_y; int x, y, px, py; int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; - int sw = 0, sp = 0, hp = h * pitch; - PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); - PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); - PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); - PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); - PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - - int real_radius = r; - int short_h = h - (2 * r) + 2; - int long_h = h; - - if (fill_m == kFillDisabled) { - while (sw++ < Base::_strokeWidth) { - colorFill<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); - colorFill<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); - sp += pitch; + // TODO: Split this up into border, bevel and interior functions - __BE_RESET(); - r--; + if (fill_m != kFillDisabled) { + PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); + PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - while (x++ < y) { - __BE_ALGORITHM(); - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + int real_radius = r; + int short_h = h - (2 * r) + 2; + int long_h = h; - if (Base::_strokeWidth > 1) { - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py); - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py); - } - } - } + BE_RESET(); - ptr_fill += pitch * real_radius; - while (short_h--) { - colorFill<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color); - colorFill<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); - ptr_fill += pitch; - } - } else { - __BE_RESET(); - PixelType color1, color2, color3, color4; + PixelType color1 = color; + if (fill_m == kFillBackground) + color1 = _bgColor; if (fill_m == kFillGradient) { + PixelType color2, color3, color4; + precalcGradient(long_h); + while (x++ < y) { - __BE_ALGORITHM(); + BE_ALGORITHM(); color1 = calcGradient(real_radius - x, long_h); color2 = calcGradient(real_radius - y, long_h); color3 = calcGradient(long_h - r + x, long_h); color4 = calcGradient(long_h - r + y, long_h); - colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color2); - colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color1); + gradientFill(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y); + gradientFill(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x); - colorFill<PixelType>(ptr_bl - x + py, ptr_br + x + py, color4); - colorFill<PixelType>(ptr_bl - y + px, ptr_br + y + px, color3); + gradientFill(ptr_bl - x + py, w - 2 * r + 2 * x, x1 + r - x - y, long_h - r + y); + gradientFill(ptr_bl - y + px, w - 2 * r + 2 * y, x1 + r - y - x, long_h - r + x); - __BE_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + BE_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); } } else { while (x++ < y) { - __BE_ALGORITHM(); + BE_ALGORITHM(); - colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color); - colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color); + colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color1); + colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color1); - colorFill<PixelType>(ptr_bl - x + py, ptr_br + x + py, color); - colorFill<PixelType>(ptr_bl - y + px, ptr_br + y + px, color); + colorFill<PixelType>(ptr_bl - x + py, ptr_br + x + py, color1); + colorFill<PixelType>(ptr_bl - y + px, ptr_br + y + px, color1); // do not remove - messes up the drawing at lower resolutions - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); } } ptr_fill += pitch * r; while (short_h--) { - if (fill_m == kFillGradient) - color = calcGradient(real_radius++, long_h); - colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color); + if (fill_m == kFillGradient) { + gradientFill(ptr_fill, w + 1, x1, real_radius++); + } else { + colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color1); + } + ptr_fill += pitch; + } + } + + + if (Base::_strokeWidth) { + int sw = 0, sp = 0, hp = h * pitch; + + PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); + PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + + int real_radius = r; + int short_h = h - (2 * r) + 2; + + // TODO: A gradient effect on the bevel + PixelType color1, color2; + color1 = Base::_bevel ? _bevelColor : color; + color2 = color; + + while (sw++ < Base::_strokeWidth) { + colorFill<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1); + colorFill<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2); + sp += pitch; + + BE_RESET(); + r--; + + while (x++ < y) { + BE_ALGORITHM(); + BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + + if (Base::_strokeWidth > 1) { + BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py); + BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py); + } + } + } + + ptr_fill += pitch * real_radius; + while (short_h--) { + colorFill<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color1); + colorFill<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2); ptr_fill += pitch; } } @@ -1235,7 +1556,7 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode f if (fill_m == kFillDisabled) { while (sw++ < Base::_strokeWidth) { - __BE_RESET(); + BE_RESET(); r--; *(ptr + y) = color; @@ -1244,21 +1565,21 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode f *(ptr - py) = color; while (x++ < y) { - __BE_ALGORITHM(); - __BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py); + BE_ALGORITHM(); + BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py); if (Base::_strokeWidth > 1) { - __BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x - 1, y, px, py); - __BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px - pitch, py); + BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x - 1, y, px, py); + BE_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px - pitch, py); } } } } else { colorFill<PixelType>(ptr - r, ptr + r, color); - __BE_RESET(); + BE_RESET(); while (x++ < y) { - __BE_ALGORITHM(); + BE_ALGORITHM(); colorFill<PixelType>(ptr - x + py, ptr + x + py, color); colorFill<PixelType>(ptr - x - py, ptr + x - py, color); colorFill<PixelType>(ptr - y + px, ptr + y + px, color); @@ -1330,7 +1651,7 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { int short_h = h - (2 * r) + 1; - __BE_RESET(); + BE_RESET(); // HACK: As we are drawing circles exploting 8-axis symmetry, // there are 4 pixels on each circle which are drawn twice. @@ -1339,7 +1660,7 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { uint32 hb = 0; while (x++ < y) { - __BE_ALGORITHM(); + BE_ALGORITHM(); if (((1 << x) & hb) == 0) { blendFill(ptr_tr - px - r, ptr_tr + y - px, 0, alpha); @@ -1360,64 +1681,6 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { } } -template<typename PixelType> -void VectorRendererSpec<PixelType>:: -drawRoundedSquareFakeBevel(int x1, int y1, int r, int w, int h, int amount) { - int x, y; - const int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; - int px, py; - int sw = 0, sp = 0; - - uint32 rsq = r*r; - frac_t T = 0, oldT; - uint8 a1, a2; - - PixelType color = _bevelColor; //_format.RGBToColor(63, 60, 17); - - PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); - PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); - PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); - PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - - int short_h = h - 2 * r; - - while (sw++ < amount) { - colorFill<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); - sp += pitch; - - x = r - (sw - 1); - y = 0; - T = 0; - px = pitch * x; - py = 0; - - while (x > y++) { - __WU_ALGORITHM(); - - blendPixelPtr(ptr_tr + (y) - (px - pitch), color, a2); - blendPixelPtr(ptr_tr + (x - 1) - (py), color, a2); - blendPixelPtr(ptr_tl - (x - 1) - (py), color, a2); - blendPixelPtr(ptr_tl - (y) - (px - pitch), color, a2); - blendPixelPtr(ptr_bl - (y) + (px - pitch), color, a2); - blendPixelPtr(ptr_bl - (x - 1) + (py), color, a2); - - blendPixelPtr(ptr_tr + (y) - (px), color, a1); - blendPixelPtr(ptr_tr + (x) - (py), color, a1); - blendPixelPtr(ptr_tl - (x) - (py), color, a1); - blendPixelPtr(ptr_tl - (y) - (px), color, a1); - blendPixelPtr(ptr_bl - (y) + (px), color, a1); - blendPixelPtr(ptr_bl - (x) + (py), color, a1); - } - } - - ptr_fill += pitch * r; - while (short_h-- >= 0) { - colorFill<PixelType>(ptr_fill, ptr_fill + amount, color); - ptr_fill += pitch; - } -} - - /******************************************************************************/ @@ -1480,28 +1743,26 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { Base::putPixel(x2, y2, color); } -/** ROUNDED SQUARES **/ +/** TAB ALGORITHM */ template<typename PixelType> void VectorRendererAA<PixelType>:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { - int x, y; - const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel; - int px, py; - int sw = 0, sp = 0, hp = h * pitch; +drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) { + int x, y, px, py; + int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel; + int sw = 0, sp = 0, hp = 0; - uint32 rsq = r*r; frac_t T = 0, oldT; uint8 a1, a2; + uint32 rsq = r*r; PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); - PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); - PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - int short_h = h - 2 * r; + int real_radius = r; - if (fill_m == VectorRenderer::kFillDisabled) { + if (fill_m == Base::kFillDisabled) { + color = 0; while (sw++ < Base::_strokeWidth) { colorFill<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); colorFill<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); @@ -1513,48 +1774,265 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto px = pitch * x; py = 0; + while (x > y++) { - __WU_ALGORITHM(); + WU_ALGORITHM(); - if (sw != 1 && sw != Base::_strokeWidth) - a2 = a1 = 255; + // sw == 1: outside, sw = _strokeWidth: inside + if (sw != Base::_strokeWidth) + a2 = 255; - __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, (x - 1), y, (px - pitch), py, a2); - __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); + // inner arc + WU_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px, py, a2); + + if (sw == 1) // outer arc + WU_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px - pitch, py, a1); } } - ptr_fill += pitch * r; - while (short_h-- >= 0) { + int short_h = h - r + 2; + + ptr_fill += pitch * real_radius; + while (short_h--) { colorFill<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color); colorFill<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color); ptr_fill += pitch; } + + if (baseLeft) { + sw = 0; + ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1 + h + 1); + while (sw++ < Base::_strokeWidth) { + colorFill<PixelType>(ptr_fill - baseLeft, ptr_fill, color); + ptr_fill += pitch; + } + } + + if (baseRight) { + sw = 0; + ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w, y1 + h + 1); + while (sw++ < Base::_strokeWidth) { + colorFill<PixelType>(ptr_fill, ptr_fill + baseRight, color); + ptr_fill += pitch; + } + } } else { - x = r; + PixelType color1, color2; + color1 = color2 = color; + + int long_h = h; + int short_h = h - real_radius + 2; + x = real_radius; y = 0; T = 0; px = pitch * x; py = 0; - while (x > 1 + y++) { - __WU_ALGORITHM(); + Base::precalcGradient(long_h); + + while (x > y++) { + WU_ALGORITHM(); + + if (fill_m == Base::kFillGradient) { + color1 = Base::calcGradient(real_radius - x, long_h); + color2 = Base::calcGradient(real_radius - y, long_h); + + Base::gradientFill(ptr_tl - x - py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, real_radius - y); + + // Only fill each horizontal line once (or we destroy + // the gradient effect at the edges) + if (T < oldT || y == 1) + Base::gradientFill(ptr_tl - y - px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, real_radius - x); + + WU_DRAWCIRCLE_XCOLOR_TOP(ptr_tr, ptr_tl, x, y, px, py, a1, Base::blendPixelPtr); + } else { + colorFill<PixelType>(ptr_tl - x - py + 1, ptr_tr + x - py, color); + if (T < oldT || y == 1) + colorFill<PixelType>(ptr_tl - y - px + 1, ptr_tr + y - px, color); + + WU_DRAWCIRCLE_TOP(ptr_tr, ptr_tl, x, y, px, py, a1); + } + } + + ptr_fill += pitch * r; + while (short_h--) { + if (fill_m == Base::kFillGradient) { + Base::gradientFill(ptr_fill, w + 1, x1, real_radius++); + } else { + colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color); + } + ptr_fill += pitch; + } + } +} + + +/** ROUNDED SQUARES **/ +template<typename PixelType> +void VectorRendererAA<PixelType>:: +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { + int x, y; + const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel; + int px, py; + + uint32 rsq = r*r; + frac_t T = 0, oldT; + uint8 a1, a2; + + // TODO: Split this up into border, bevel and interior functions - colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color); - colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color); + if (Base::_strokeWidth) { + PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); + PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - colorFill<PixelType>(ptr_bl - x + py, ptr_br + x + py, color); - colorFill<PixelType>(ptr_bl - y + px, ptr_br + y + px, color); + int sw = 0, sp = 0; + int short_h = h - 2 * r; + int hp = h * pitch; - __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); + int strokeWidth = Base::_strokeWidth; + // If we're going to fill the inside, draw a slightly thicker border + // so we can blend the inside on top of it. + if (fill_m != Base::kFillDisabled) strokeWidth++; + + // TODO: A gradient effect on the bevel + PixelType color1, color2; + color1 = Base::_bevel ? Base::_bevelColor : color; + color2 = color; + + + while (sw++ < strokeWidth) { + colorFill<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1); + colorFill<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2); + sp += pitch; + + x = r - (sw - 1); + y = 0; + T = 0; + px = pitch * x; + py = 0; + + while (x > y++) { + WU_ALGORITHM(); + + // sw == 1: outside, sw = _strokeWidth: inside + // We always draw the outer edge AAed, but the inner edge + // only when the inside isn't filled + if (sw != strokeWidth || fill_m != Base::kFillDisabled) + a2 = 255; + + // inner arc + WU_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, (x - 1), y, (px - pitch), py, a2); + + if (sw == 1) // outer arc + WU_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); + } } ptr_fill += pitch * r; while (short_h-- >= 0) { - colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color); + colorFill<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color1); + colorFill<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2); ptr_fill += pitch; } } + + r -= Base::_strokeWidth; + x1 += Base::_strokeWidth; + y1 += Base::_strokeWidth; + w -= 2*Base::_strokeWidth; + h -= 2*Base::_strokeWidth; + rsq = r*r; + + if (w <= 0 || h <= 0) + return; // Only border is visible + + if (fill_m != Base::kFillDisabled) { + if (fill_m == Base::kFillBackground) + color = Base::_bgColor; + + PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r); + PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); + PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); + PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); + PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + + int short_h = h - 2 * r; + x = r; + y = 0; + T = 0; + px = pitch * x; + py = 0; + + if (fill_m == Base::kFillGradient) { + + Base::precalcGradient(h); + + PixelType color1, color2, color3, color4; + while (x > y++) { + WU_ALGORITHM(); + + color1 = Base::calcGradient(r - x, h); + color2 = Base::calcGradient(r - y, h); + color3 = Base::calcGradient(h - r + x, h); + color4 = Base::calcGradient(h - r + y, h); + + Base::gradientFill(ptr_tl - x - py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, r - y); + + // Only fill each horizontal line once (or we destroy + // the gradient effect at the edges) + if (T < oldT || y == 1) + Base::gradientFill(ptr_tl - y - px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, r - x); + + Base::gradientFill(ptr_bl - x + py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, h - r + y); + + // Only fill each horizontal line once (or we destroy + // the gradient effect at the edges) + if (T < oldT || y == 1) + Base::gradientFill(ptr_bl - y + px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, h - r + x); + + // This shape is used for dialog backgrounds. + // If we're drawing on top of an empty overlay background, + // and the overlay supports alpha, we have to do AA by + // setting the dest alpha channel, instead of blending with + // dest color channels. + if (!g_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha)) + WU_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1, blendPixelPtr); + else + WU_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1, blendPixelDestAlphaPtr); + } + + ptr_fill += pitch * r; + while (short_h-- >= 0) { + Base::gradientFill(ptr_fill, w + 1, x1, r++); + ptr_fill += pitch; + } + + } else { + + while (x > 1 + y++) { + WU_ALGORITHM(); + + colorFill<PixelType>(ptr_tl - x - py + 1, ptr_tr + x - py, color); + if (T < oldT || y == 1) + colorFill<PixelType>(ptr_tl - y - px + 1, ptr_tr + y - px, color); + + colorFill<PixelType>(ptr_bl - x + py + 1, ptr_br + x + py, color); + if (T < oldT || y == 1) + colorFill<PixelType>(ptr_bl - y + px + 1, ptr_br + y + px, color); + + WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); + } + + ptr_fill += pitch * r; + while (short_h-- >= 0) { + colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color); + ptr_fill += pitch; + } + } + } } /** CIRCLES **/ @@ -1585,13 +2063,13 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode f *(ptr - px) = (PixelType)color; while (x > y++) { - __WU_ALGORITHM(); + WU_ALGORITHM(); if (sw != 1 && sw != Base::_strokeWidth) a2 = a1 = 255; - __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, (x - 1), y, (px - pitch), py, a2); - __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1); + WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, (x - 1), y, (px - pitch), py, a2); + WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1); } } } else { @@ -1603,14 +2081,14 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode f py = 0; while (x > y++) { - __WU_ALGORITHM(); + WU_ALGORITHM(); colorFill<PixelType>(ptr - x + py, ptr + x + py, color); colorFill<PixelType>(ptr - x - py, ptr + x - py, color); colorFill<PixelType>(ptr - y + px, ptr + y + px, color); colorFill<PixelType>(ptr - y - px, ptr + y - px, color); - __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1); + WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1); } } } |
