aboutsummaryrefslogtreecommitdiff
path: root/graphics/VectorRendererSpec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/VectorRendererSpec.cpp')
-rw-r--r--graphics/VectorRendererSpec.cpp693
1 files changed, 482 insertions, 211 deletions
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 588e17b6cb..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,35 +87,63 @@ 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() \
if (error_term >= 0) { \
@@ -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 {
@@ -447,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) {
@@ -473,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) +
@@ -486,9 +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 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);
+ }
+}
+
+template<typename PixelType>
+inline void VectorRendererSpec<PixelType>::
+darkenFill(PixelType *ptr, PixelType *end) {
+ PixelType mask = (PixelType)((3 << _format.rShift) | (3 << _format.gShift) | (3 << _format.bShift));
+
+ 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;
+ }
+ }
}
/********************************************************************
@@ -665,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>
@@ -719,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));
@@ -839,17 +925,10 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer:
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_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);
}
}
@@ -880,6 +959,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;
@@ -889,22 +970,26 @@ 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;
+ 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;
}
}
@@ -998,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;
}
}
@@ -1347,49 +1433,30 @@ 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);
+ // TODO: Split this up into border, bevel and interior functions
- 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;
-
- BE_RESET();
- r--;
-
- while (x++ < y) {
- BE_ALGORITHM();
- BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
+ 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);
- 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);
- }
- }
- }
+ int real_radius = r;
+ int short_h = h - (2 * r) + 2;
+ int long_h = h;
- 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();
@@ -1398,11 +1465,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);
}
@@ -1410,11 +1477,11 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto
while (x++ < y) {
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);
@@ -1423,9 +1490,56 @@ 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, 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;
}
}
@@ -1567,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;
- }
-}
-
-
/******************************************************************************/
@@ -1687,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);
@@ -1720,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();
- 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++) {
+ Base::precalcGradient(long_h);
+
+ while (x > y++) {
WU_ALGORITHM();
- colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color);
- colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color);
+ if (fill_m == Base::kFillGradient) {
+ color1 = Base::calcGradient(real_radius - x, long_h);
+ color2 = Base::calcGradient(real_radius - y, long_h);
- colorFill<PixelType>(ptr_bl - x + py, ptr_br + x + py, color);
- colorFill<PixelType>(ptr_bl - y + px, ptr_br + y + px, color);
+ Base::gradientFill(ptr_tl - x - py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, real_radius - y);
- WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1);
+ // 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
+
+ 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);
+
+ int sw = 0, sp = 0;
+ int short_h = h - 2 * r;
+ int hp = h * pitch;
+
+ 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 **/