diff options
-rw-r--r-- | graphics/VectorRenderer.cpp | 293 | ||||
-rw-r--r-- | graphics/VectorRenderer.h | 182 |
2 files changed, 283 insertions, 192 deletions
diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 67a60bbde1..d840b5d35a 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -62,10 +62,11 @@ void vector_renderer_test(OSystem *_system) { vr->setFgColor(255, 255, 255); vr->fillSurface(); - vr->setFgColor(255, 0, 0 ); - vr->setBgColor(25, 25, 175 ); - vr->setFillMode( VectorRenderer::kBackgroundFill ); - vr->shadowEnable( 5, 5 ); + vr->setFgColor(255, 0, 0); + vr->setBgColor(25, 25, 175); + vr->setFillMode(VectorRenderer::kBackgroundFill); + vr->setStrokeWidth(3); + vr->shadowEnable(1, 1); vr->drawLine(25, 25, 125, 300); vr->drawCircle(250, 250, 100); @@ -87,7 +88,86 @@ void vector_renderer_test(OSystem *_system) { template<typename PixelType, typename PixelFormat> void VectorRendererSpec<PixelType, PixelFormat>:: +drawCircle(int x, int y, int r) { + if (Base::_fillMode != kNoFill && Base::_shadows) { + drawCircleAlg(x + Base::_shadowXOffset + 1, y + Base::_shadowYOffset + 1, r, 0, true); + } + + switch(Base::_fillMode) { + case kNoFill: + drawCircleAlg(x, y, r, _fgColor, false); + break; + + case kForegroundFill: + drawCircleAlg(x, y, r, _fgColor, true); + break; + + case kBackgroundFill: + VectorRendererSpec::drawCircleAlg(x, y, r - 1, _bgColor, true); + drawCircleAlg(x, y, r, _fgColor, false); + break; + + case kGradientFill: + break; + } +} + +template<typename PixelType, typename PixelFormat> +void VectorRendererSpec<PixelType, PixelFormat>:: +drawSquare(int x, int y, int w, int h) { + if (Base::_fillMode != kNoFill && Base::_shadows) { + drawSquareAlg(x + Base::_shadowXOffset + 1, y + Base::_shadowYOffset + 1, w, h, 0, true); + } + + switch(Base::_fillMode) { + case kNoFill: + drawSquareAlg(x, y, w, h, _fgColor, false); + break; + + case kForegroundFill: + drawSquareAlg(x, y, w, h, _fgColor, true); + break; + + case kBackgroundFill: + drawSquareAlg(x, y, w, h, _bgColor, true); + drawSquareAlg(x, y, w, h, _fgColor, false); + break; + + case kGradientFill: + break; + } +} + +template<typename PixelType, typename PixelFormat> +void VectorRendererSpec<PixelType, PixelFormat>:: +drawRoundedSquare(int x, int y, int r, int w, int h) { + if (Base::_fillMode != kNoFill && Base::_shadows) { + drawRoundedSquareAlg(x + Base::_shadowXOffset + 1, y + Base::_shadowYOffset + 1, r, w, h, 0, true); + } + + switch(Base::_fillMode) { + case kNoFill: + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); + break; + + case kForegroundFill: + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, true); + break; + + case kBackgroundFill: + VectorRendererSpec::drawRoundedSquareAlg(x + 1, y + 1, r, w - 1, h - 1, _bgColor, true); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); + break; + + case kGradientFill: + break; + } +} + +template<typename PixelType, typename PixelFormat> +void VectorRendererSpec<PixelType, PixelFormat>:: drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill) { + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); int pitch = Base::surfacePitch(); @@ -97,12 +177,17 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill) { ptr += pitch; } } else { - Common::set_to(ptr, ptr + w, color); - Common::set_to(ptr + pitch * h, ptr + w + pitch * h, color); + int sw = _strokeWidth, sp = 0, hp = pitch * (h - 1); + + while(sw--) { + Common::set_to(ptr + sp, ptr + w + sp, color); + Common::set_to(ptr + hp - sp, ptr + w + hp - sp, color); + sp += pitch; + } while (h--) { - *ptr = color; - *(ptr + w) = color; + Common::set_to(ptr, ptr + _strokeWidth, color); + Common::set_to(ptr + w - _strokeWidth, ptr + w, color); ptr += pitch; } } @@ -159,6 +244,11 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { template<typename PixelType, typename PixelFormat> void VectorRendererAA<PixelType, PixelFormat>:: blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { + if (alpha == 255) { + *ptr = color; + return; + } + register int idst = *ptr; register int isrc = color; @@ -283,7 +373,7 @@ inline uint32 fp_sqroot(uint32 x) { remHI = (remHI << 2) | (remLO >> 30); remLO <<= 2; root <<= 1; - testDIV = (root << 1 ) + 1; + testDIV = (root << 1) + 1; if (remHI >= testDIV) { remHI -= testDIV; @@ -343,12 +433,35 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { } } +#define __WU_DRAWCIRCLE(ptr1,ptr2,ptr3,ptr4,x,y,px,py,a) { \ + blendPixelPtr(ptr1 + (y) - (px), color, a); \ + blendPixelPtr(ptr1 + (x) - (py), color, a); \ + blendPixelPtr(ptr2 - (x) - (py), color, a); \ + blendPixelPtr(ptr2 - (y) - (px), color, a); \ + blendPixelPtr(ptr3 - (y) + (px), color, a); \ + blendPixelPtr(ptr3 - (x) + (py), color, a); \ + blendPixelPtr(ptr4 + (x) + (py), color, a); \ + blendPixelPtr(ptr4 + (y) + (px), color, a); \ +} + +#define __WU_ALGORITHM() { \ + oldT = T; \ + T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; \ + py += p; \ + if (T < oldT) { \ + x--; px -= p; \ + } \ + a2 = (T >> 8); \ + a1 = ~a2; \ +} + template<typename PixelType, typename PixelFormat> void VectorRendererAA<PixelType, PixelFormat>:: drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill) { - int x = r; - int y = 0; + int x, y; int p = Base::surfacePitch(), px, py; + int sw = 0, sp = 0, hp = h * p; + uint32 rsq = (r * r) << 16; uint32 T = 0, oldT; uint8 a1, a2; @@ -359,137 +472,105 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - Common::set_to(ptr_fill + r, ptr_fill + w - r + 1, color); - Common::set_to(ptr_fill + r + h*p, ptr_fill + w - r + 1 + h*p, color); - - h -= 2*r; - ptr_fill += p*r; - - if (!fill) { - while (h-- >= 0) { - *(ptr_fill) = (PixelType)color; - *(ptr_fill + w) = (PixelType)color; - ptr_fill += p; - } - } else { - while (h-- >= 0) { - Common::set_to(ptr_fill, ptr_fill + w + 1, color); - ptr_fill += p; - } - } + int short_h = h - 2 * r; - px = p * x; - py = 0; + if (fill == false) { + while (sw++ < Base::_strokeWidth) { + Common::set_to(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color); + Common::set_to(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color); + sp += p; - while (x > y++) - { - oldT = T; - T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; + x = r - (sw - 1); y = 0; T = 0; + px = p * x; py = 0; + + while (x > y++) { + __WU_ALGORITHM(); - py += p; + if (sw != 1 && sw != Base::_strokeWidth) + a2 = a1 = 255; - if (T < oldT) { - x--; - px -= p; + __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, (x - 1), y, (px - p), py, a2); + __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); + } } - a2 = (T >> 8); - a1 = ~a2; + ptr_fill += p * r; + while (short_h-- >= 0) { + Common::set_to(ptr_fill, ptr_fill + _strokeWidth, color); + Common::set_to(ptr_fill + w - _strokeWidth + 1, ptr_fill + w + 1, color); + ptr_fill += p; + } + } else { + x = r; y = 0; T = 0; + px = p * x; py = 0; + + while (x > y++) { + __WU_ALGORITHM(); - if (fill) { Common::set_to(ptr_tl - x - py, ptr_tr + x - py, color); Common::set_to(ptr_tl - y - px, ptr_tr + y - px, color); Common::set_to(ptr_bl - x + py, ptr_br + x + py, color); Common::set_to(ptr_bl - y + px, ptr_br + y + px, color); - } else { - blendPixelPtr(ptr_tr + y - (px-p), color, a2); - blendPixelPtr(ptr_tr + x - 1 - py, color, a2); - blendPixelPtr(ptr_tl - x + 1 - py, color, a2); - blendPixelPtr(ptr_tl - y - (px-p), color, a2); - - blendPixelPtr(ptr_bl - y + (px-p), color, a2); - blendPixelPtr(ptr_bl - x + 1 + py, color, a2); - - blendPixelPtr(ptr_br + x - 1 + py, color, a2); - blendPixelPtr(ptr_br + y + (px-p), 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); + __WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); + } - blendPixelPtr(ptr_br + x + py, color, a1); - blendPixelPtr(ptr_br + y + px, color, a1); + ptr_fill += p * r; + while (short_h-- >= 0) { + Common::set_to(ptr_fill, ptr_fill + w + 1, color); + ptr_fill += p; + } } } template<typename PixelType, typename PixelFormat> void VectorRendererAA<PixelType, PixelFormat>:: drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { - int x = r; - int y = 0; - int p = Base::surfacePitch(), px = 0, py = 0; + int x, y, sw = 0; + int p = Base::surfacePitch(), px, py; + uint32 rsq = (r * r) << 16; uint32 T = 0, oldT; uint8 a1, a2; PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - px = p * x; - py = p * y; - *(ptr + x) = (PixelType)color; - *(ptr - x) = (PixelType)color; - *(ptr + px) = (PixelType)color; - *(ptr - px) = (PixelType)color; - - if (fill) Common::set_to(ptr - x, ptr + x, color); + if (fill == false) { + while (sw++ < Base::_strokeWidth) { + x = r - (sw - 1); y = 0; T = 0; + px = p * x; py = 0; - while (x > y++) - { - oldT = T; - T = fp_sqroot(rsq - ((y * y) << 16)) ^ 0xFFFF; + *(ptr + x) = (PixelType)color; + *(ptr - x) = (PixelType)color; + *(ptr + px) = (PixelType)color; + *(ptr - px) = (PixelType)color; - py += p; + while (x > y++) { + __WU_ALGORITHM(); - if (T < oldT) { - x--; - px -= p; + if (sw != 1 && sw != Base::_strokeWidth) + a2 = a1 = 255; + + __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, (x - 1), y, (px - p), py, a2); + __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1); + } } + } else { + Common::set_to(ptr - r, ptr + r + 1, color); + x = r; y = 0; T = 0; + px = p * x; py = 0; - a2 = (T >> 8); - a1 = ~a2; + while (x > y++) { + __WU_ALGORITHM(); - if (fill) { Common::set_to(ptr - x + py, ptr + x + py, color); Common::set_to(ptr - x - py, ptr + x - py, color); Common::set_to(ptr - y + px, ptr + y + px, color); Common::set_to(ptr - y - px, ptr + y - px, color); - } else { - blendPixelPtr(ptr + x - 1 + py, color, a2); - blendPixelPtr(ptr + y - (px-p), color, a2); - blendPixelPtr(ptr - x + 1 - py, color, a2); - blendPixelPtr(ptr - y - (px-p), color, a2); - blendPixelPtr(ptr - y + (px-p), color, a2); - blendPixelPtr(ptr - x + 1 + py, color, a2); - blendPixelPtr(ptr + y + (px-p), color, a2); - blendPixelPtr(ptr + x - 1 - py, color, a2); - } - - blendPixelPtr(ptr + x + py, color, a1); - blendPixelPtr(ptr + y - px, color, a1); - blendPixelPtr(ptr - x - py, color, a1); - blendPixelPtr(ptr - y - px, color, a1); - blendPixelPtr(ptr - y + px, color, a1); - blendPixelPtr(ptr - x + py, color, a1); - blendPixelPtr(ptr + y + px, color, a1); - blendPixelPtr(ptr + x - py, color, a1); + + __WU_DRAWCIRCLE(ptr, ptr, ptr, ptr, x, y, px, py, a1); + } } } diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index bc96299fc2..1cf7337c84 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -53,7 +53,7 @@ void vector_renderer_test(OSystem *_system); class VectorRenderer { public: - VectorRenderer() : _shadows(false), _fillMode(kNoFill), _activeSurface(NULL) {} + VectorRenderer() : _shadows(false), _fillMode(kNoFill), _activeSurface(NULL), _strokeWidth(1) {} virtual ~VectorRenderer() {} enum FillMode { @@ -87,10 +87,27 @@ public: */ virtual void drawCircle(int x, int y, int r) = 0; - + /** + * Draws a square starting at (x,y) with the given width and height. + * + * @param x Horizontal (X) coordinate for the center of the square + * @param y Vertical (Y) coordinate for the center of the square + * @param w Width of the square. + * @param h Height of the square + */ virtual void drawSquare(int x, int y, int w, int h) = 0; - virtual void drawRoundedSquare(int x1, int y1, int r, int w, int h) = 0; + /** + * Draws a rounded square starting at (x,y) with the given width and height. + * The corners of the square are rounded with the given radius. + * + * @param x Horizontal (X) coordinate for the center of the square + * @param y Vertical (Y) coordinate for the center of the square + * @param w Width of the square. + * @param h Height of the square + * @param r Radius of the corners. + */ + virtual void drawRoundedSquare(int x, int y, int r, int w, int h) = 0; /** * Gets the pixel pitch for the current drawing surface. @@ -115,15 +132,29 @@ public: } /** - * Set the active painting color for the renderer. - * All the drawing from then on will be done with that color, unless + * Set the active foreground painting color for the renderer. + * All the foreground drawing from then on will be done with that color, unless * specified otherwise. * + * Foreground drawing means all outlines and basic shapes. + * * @param r value of the red color byte * @param g value of the green color byte * @param b value of the blue color byte */ virtual void setFgColor(uint8 r, uint8 g, uint8 b) = 0; + + /** + * Set the active background painting color for the renderer. + * All the background drawing from then on will be done with that color, unless + * specified otherwise. + * + * Background drawing means all the shape filling. + * + * @param r value of the red color byte + * @param g value of the green color byte + * @param b value of the blue color byte + */ virtual void setBgColor(uint8 r, uint8 g, uint8 b) = 0; /** @@ -137,7 +168,10 @@ public: } /** - * Fills the active surface with the currently active drawing color. + * Fills the active surface with the specified fg/bg color. + * Defaults to using the active Foreground color for filling. + * + * @param mode Color mode (bg or fg color) used to fill. */ virtual void fillSurface(ColorMode mode = kForegroundColor) = 0; @@ -149,16 +183,46 @@ public: memset(src, 0, _activeSurface->w * _activeSurface->h * _activeSurface->bytesPerPixel); } + /** + * Sets the active fill mode for all shapes. + * + * @see VectorRenderer::FillMode + * @param mode Specified fill mode. + */ virtual void setFillMode(VectorRenderer::FillMode mode) { _fillMode = mode; } + /** + * Sets the stroke width. All shapes drawn with a stroke will + * have that width. + * + * @param width Witdh of the stroke in pixels. + */ + virtual void setStrokeWidth(int width) { + if (width > 0) _strokeWidth = width; + } + + /** + * Enables adding shadows to all drawn primitives. + * Shadows are drawn automatically under the shapes, at the + * given x/y offsets. + * + * @param x_offset Horizontal offset for the shadows. + * @param y_offset Vertical offset for the shadows. + * @see shadowDisable() + */ virtual void shadowEnable(int x_offset, int y_offset) { _shadows = true; _shadowXOffset = x_offset; _shadowYOffset = y_offset; } + /** + * Disables adding shadows to all drawn primitives. + * + * @see shadowEnable() + */ virtual void shadowDisable() { _shadows = false; } @@ -166,13 +230,14 @@ public: protected: Surface *_activeSurface; /** Pointer to the surface currently being drawn */ - FillMode _fillMode; + FillMode _fillMode; /** Defines in which way (if any) are filled the drawn shapes */ - bool _shadows; - int _shadowXOffset; - int _shadowYOffset; -}; + bool _shadows; /** Defines if shadows are automatically added to drawn shapes */ + int _shadowXOffset; /** Horizontal offset for drawn shadows */ + int _shadowYOffset; /** Vertical offset for drawn shadows */ + int _strokeWidth; /** Width of the stroke of all drawn shapes */ +}; /** @@ -204,86 +269,31 @@ public: */ void drawLine(int x1, int y1, int x2, int y2); - void drawCircle(int x, int y, int r) { - if (Base::_fillMode != kNoFill && Base::_shadows) { - drawCircleAlg(x + Base::_shadowXOffset, y + Base::_shadowYOffset, r, 0, true); - } - - switch(Base::_fillMode) { - case kNoFill: - drawCircleAlg(x, y, r, _fgColor, false); - break; - - case kForegroundFill: - drawCircleAlg(x, y, r, _fgColor, true); - break; - - case kBackgroundFill: - drawCircleAlg(x, y, r - 1, _bgColor, true); - drawCircleAlg(x, y, r, _fgColor, false); - break; - - case kGradientFill: - break; - } - } - - void drawSquare(int x, int y, int w, int h) { - if (Base::_fillMode != kNoFill && Base::_shadows) { - drawSquareAlg(x + Base::_shadowXOffset , y + h, w, Base::_shadowYOffset, 0, true); - drawSquareAlg(x + w, y + Base::_shadowYOffset, Base::_shadowXOffset, h, 0, true); - } - - switch(Base::_fillMode) { - case kNoFill: - drawSquareAlg(x, y, w, h, _fgColor, false); - break; - - case kForegroundFill: - drawSquareAlg(x, y, w, h, _fgColor, true); - break; - - case kBackgroundFill: - drawSquareAlg(x, y, w, h, _bgColor, true); - drawSquareAlg(x, y, w, h, _fgColor, false); - break; - - case kGradientFill: - break; - } - } - - void drawRoundedSquare(int x, int y, int r, int w, int h) { - if (Base::_fillMode != kNoFill && Base::_shadows) { - drawRoundedSquareAlg(x + Base::_shadowXOffset, y + Base::_shadowYOffset, r, w, h, 0, true); - } - - switch(Base::_fillMode) { - case kNoFill: - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); - break; - - case kForegroundFill: - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, true); - break; + /** + * @see VectorRenderer::drawCircle() + */ + void drawCircle(int x, int y, int r); - case kBackgroundFill: - drawRoundedSquareAlg(x, y, r + 1, w, h, _bgColor, true); - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); - break; + /** + * @see VectorRenderer::drawSquare() + */ + void drawSquare(int x, int y, int w, int h); - case kGradientFill: - break; - } - } + /** + * @see VectorRenderer::drawRoundedSquare() + */ + void drawRoundedSquare(int x, int y, int r, int w, int h); /** - * @see VectorRenderer::setColor() + * @see VectorRenderer::setFgColor() */ void setFgColor(uint8 r, uint8 g, uint8 b) { this->_fgColor = RGBToColor<PixelFormat>(r, g, b); } + /** + * @see VectorRenderer::setBgColor() + */ void setBgColor(uint8 r, uint8 g, uint8 b) { this->_bgColor = RGBToColor<PixelFormat>(r, g, b); } @@ -311,7 +321,7 @@ protected: * @param y Vertical coordinate of the pixel. * @param color Color of the pixel */ - virtual inline void putPixel( int x, int y, PixelType color ) { + virtual inline void putPixel(int x, int y, PixelType color) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); *ptr = color; } @@ -344,8 +354,8 @@ protected: virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill = false) {} virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill = false); - PixelType _fgColor; /** Color currently being used to draw on the renderer */ - PixelType _bgColor; + PixelType _fgColor; /** Foreground color currently being used to draw on the renderer */ + PixelType _bgColor; /** Background color currently being used to draw on the renderer */ }; /** @@ -397,7 +407,7 @@ protected: inline void blendPixel(int x, int y, PixelType color, uint8 alpha) { if (alpha == 255) putPixel(x, y, color); - else if (alpha > 0 ) + else if (alpha > 0) blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), color, alpha); } |