From 9d3eb2ebd7311a4ed3c69b7bc4637dee6dbfe530 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Fri, 9 Dec 2011 13:27:49 +0000 Subject: GUI: Refactor gradient calculation into separate method --- graphics/VectorRendererSpec.cpp | 160 +++++++++++++++++++++------------------- graphics/VectorRendererSpec.h | 6 ++ 2 files changed, 92 insertions(+), 74 deletions(-) (limited to 'graphics') diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index e1f2ffee8a..9e4119d356 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -223,6 +223,22 @@ VectorRenderer *createRenderer(int mode) { return 0; } +template +VectorRendererSpec:: +VectorRendererSpec(PixelFormat format) : + _format(format), + _redMask((0xFF >> format.rLoss) << format.rShift), + _greenMask((0xFF >> format.gLoss) << format.gShift), + _blueMask((0xFF >> format.bLoss) << format.bShift), + _alphaMask((0xFF >> format.aLoss) << format.aShift) { + + _bitmapAlphaColor = _format.RGBToColor(255, 0, 255); +} + +/**************************** + * Gradient-related methods * + ****************************/ + template void VectorRendererSpec:: setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) { @@ -235,15 +251,75 @@ setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) { } template -VectorRendererSpec:: -VectorRendererSpec(PixelFormat format) : - _format(format), - _redMask((0xFF >> format.rLoss) << format.rShift), - _greenMask((0xFF >> format.gLoss) << format.gShift), - _blueMask((0xFF >> format.bLoss) << format.bShift), - _alphaMask((0xFF >> format.aLoss) << format.aShift) { +inline PixelType VectorRendererSpec:: +calcGradient(uint32 pos, uint32 max) { + PixelType output = 0; + pos = (MIN(pos * Base::_gradientFactor, max) << 12) / max; - _bitmapAlphaColor = _format.RGBToColor(255, 0, 255); + 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 +void VectorRendererSpec:: +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 +void VectorRendererSpec:: +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(ptr, ptr + width, _gradCache[curGrad]); + } else if (grad == 3 && ox) { + colorFill(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 @@ -252,7 +328,6 @@ fillSurface() { byte *ptr = (byte *)_activeSurface->getBasePtr(0, 0); int h = _activeSurface->h; - int w = _activeSurface->w; int pitch = _activeSurface->pitch; if (Base::_fillMode == kFillBackground) { @@ -260,60 +335,11 @@ fillSurface() { } else if (Base::_fillMode == kFillForeground) { colorFill((PixelType *)ptr, (PixelType *)(ptr + pitch * h), _fgColor); } else if (Base::_fillMode == kFillGradient) { - Common::Array gradCache; - Common::Array gradIndexes; - PixelType prevcolor = 0, color; - int numColors = 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); - numColors++; - } - } + precalcGradient(h); - int curGrad = -1; for (int i = 0; i < h; i++) { - PixelType *ptr1 = (PixelType *)ptr; - - bool ox = (i & 1 == 1); - int stripSize; + gradientFill((PixelType *)ptr, _activeSurface->w, 0, i); - if (i == gradIndexes[curGrad + 1]) { - curGrad++; - - stripSize = gradIndexes[curGrad + 1] - gradIndexes[curGrad]; - } - - int grad = (((i - 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, (PixelType *)(ptr + pitch), gradCache[curGrad]); - } else if (grad == 3 && ox) { - colorFill((PixelType *)ptr, (PixelType *)(ptr + pitch), gradCache[curGrad + 1]); - } else { - for (int j = 0; j < w; j++, ptr1++) { - bool oy = (j & 1 == 1); - - if ((ox && oy) || - ((grad == 2 || grad == 3) && ox && !oy) || - (grad == 3 && oy)) - *ptr1 = gradCache[curGrad + 1]; - else - *ptr1 = gradCache[curGrad]; - } - } ptr += pitch; } } @@ -465,20 +491,6 @@ blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { (((int)(idst & _alphaMask) * alpha) >> 8)))); } -template -inline PixelType VectorRendererSpec:: -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; -} - /******************************************************************** ******************************************************************** * Primitive shapes drawing - Public API calls - VectorRendererSpec * diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h index b0a0624aee..fe64f9774d 100644 --- a/graphics/VectorRendererSpec.h +++ b/graphics/VectorRendererSpec.h @@ -185,6 +185,9 @@ protected: */ inline PixelType calcGradient(uint32 pos, uint32 max); + void precalcGradient(int h); + void gradientFill(PixelType *first, int width, int x, int y); + /** * Fills several pixels in a row with a given color and the specified alpha blending. * @@ -210,6 +213,9 @@ protected: int _gradientBytes[3]; /**< Color bytes of the active gradient, used to speed up calculation */ + Common::Array _gradCache; + Common::Array _gradIndexes; + PixelType _bevelColor; PixelType _bitmapAlphaColor; }; -- cgit v1.2.3