diff options
-rw-r--r-- | graphics/VectorRendererSpec.cpp | 193 | ||||
-rw-r--r-- | graphics/VectorRendererSpec.h | 4 |
2 files changed, 175 insertions, 22 deletions
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 5220beec5c..cd012f5f31 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -89,17 +89,25 @@ inline frac_t fp_sqroot(uint32 x) { f += ddF_x + 1; \ } while(0) -#define BE_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py) do { \ +#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; \ @@ -111,17 +119,26 @@ inline frac_t fp_sqroot(uint32 x) { *(ptr4 + (y) + (px)) = color2; \ } while (0) -#define BE_DRAWCIRCLE_XCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py) do { \ +#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() do { \ f = 1 - r; \ ddF_x = 0; ddF_y = -2 * r; \ @@ -151,30 +168,47 @@ 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) do { \ +#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(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a,func) do { \ +#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 { \ @@ -767,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)); @@ -887,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); } } @@ -943,18 +974,12 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: 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); - *(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); } } @@ -1718,6 +1743,130 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { Base::putPixel(x2, y2, color); } +/** TAB ALGORITHM */ +template<typename PixelType> +void VectorRendererAA<PixelType>:: +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; + + 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_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); + + int real_radius = r; + + 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); + 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 + if (sw != Base::_strokeWidth) + a2 = 255; + + // 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); + } + } + + 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 { + 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; + + 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); + + 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) + 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) { + 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>:: diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h index d8fc82a6f1..4ed80cb55f 100644 --- a/graphics/VectorRendererSpec.h +++ b/graphics/VectorRendererSpec.h @@ -297,6 +297,10 @@ protected: // VectorRenderer::applyConvolutionMatrix(VectorRenderer::kConvolutionHardBlur, // Common::Rect(x, y, x + w + blur * 2, y + h + blur * 2)); } + + virtual void drawTabAlg(int x, int y, int w, int h, int r, + PixelType color, VectorRenderer::FillMode fill_m, + int baseLeft = 0, int baseRight = 0); }; #endif |