aboutsummaryrefslogtreecommitdiff
path: root/graphics/VectorRendererSpec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/VectorRendererSpec.cpp')
-rw-r--r--graphics/VectorRendererSpec.cpp170
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;
}
}