diff options
Diffstat (limited to 'graphics/VectorRendererSpec.cpp')
-rw-r--r-- | graphics/VectorRendererSpec.cpp | 170 |
1 files changed, 125 insertions, 45 deletions
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 1bd07af237..b5dc129e3c 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -224,17 +224,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 +235,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 +335,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; } } @@ -413,20 +491,6 @@ blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { (((int)(idst & _alphaMask) * alpha) >> 8)))); } -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) + ((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; - - return output; -} - /******************************************************************** ******************************************************************** * Primitive shapes drawing - Public API calls - VectorRendererSpec * @@ -816,6 +880,8 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: } else { BE_RESET(); + precalcGradient(long_h); + PixelType color1, color2; color1 = color2 = color; @@ -825,22 +891,32 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: 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; + } else { + colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color); + colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color); - *(ptr_tr + (y) - (px)) = color1; - *(ptr_tr + (x) - (py)) = color2; - *(ptr_tl - (x) - (py)) = color2; - *(ptr_tl - (y) - (px)) = color1; + *(ptr_tr + (y) - (px)) = color; + *(ptr_tr + (x) - (py)) = color; + *(ptr_tl - (x) - (py)) = color; + *(ptr_tl - (y) - (px)) = color; + } } 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; } } @@ -1326,6 +1402,8 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto PixelType color1, color2, color3, color4; if (fill_m == kFillGradient) { + precalcGradient(long_h); + while (x++ < y) { BE_ALGORITHM(); @@ -1334,11 +1412,11 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto 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); } @@ -1359,9 +1437,11 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto 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; } } |