From b999366ae911172b9a8ab8a0e8955b73b055cce2 Mon Sep 17 00:00:00 2001 From: Vicent Marti Date: Fri, 16 May 2008 20:40:24 +0000 Subject: - Shadows revisited - Gradients. svn-id: r32145 --- graphics/VectorRenderer.cpp | 202 +++++++++++++++++++++++++++++--------------- graphics/VectorRenderer.h | 45 ++++++++-- 2 files changed, 175 insertions(+), 72 deletions(-) (limited to 'graphics') diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp index 6f6aa9b125..ad2ef2b250 100644 --- a/graphics/VectorRenderer.cpp +++ b/graphics/VectorRenderer.cpp @@ -30,12 +30,33 @@ #include "common/system.h" #include "common/events.h" -namespace Graphics { +inline uint32 fp_sqroot(uint32 x) { + register uint32 root, remHI, remLO, testDIV, count; + + root = 0; + remHI = 0; + remLO = x; + count = 23; + + do { + remHI = (remHI << 2) | (remLO >> 30); + remLO <<= 2; + root <<= 1; + testDIV = (root << 1) + 1; -inline uint32 fp_sqroot(uint32 x); + if (remHI >= testDIV) { + remHI -= testDIV; + root++; + } + } while (count--); + + return root; +} + +namespace Graphics { VectorRenderer *createRenderer() { - return new VectorRendererSpec >; + return new VectorRendererAA >; } @@ -59,19 +80,20 @@ void vector_renderer_test(OSystem *_system) { _system->showOverlay(); while (true) { // draw!! - vr->setFgColor(255, 255, 255); + vr->setFgColor(255, 0, 206); vr->fillSurface(); - vr->setFgColor(255, 0, 0); + vr->setFgColor(255, 247, 222); vr->setBgColor(25, 25, 175); - vr->setFillMode(VectorRenderer::kForegroundFill); - vr->setStrokeWidth(6); + vr->setGradientColors(206, 121, 99, 173, 40, 8); + vr->setFillMode(VectorRenderer::kGradientFill); + vr->setStrokeWidth(1); vr->shadowEnable(1, 1); vr->drawLine(25, 25, 125, 300); vr->drawCircle(250, 250, 100); vr->drawSquare(150, 25, 100, 75); - vr->drawRoundedSquare(275, 25, 8, 100, 75); + vr->drawRoundedSquare(275, 25, 16, 128, 128); _system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w); _system->updateScreen(); @@ -90,21 +112,21 @@ template void VectorRendererSpec:: 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); + drawCircleAlg(x + Base::_shadowXOffset + 1, y + Base::_shadowYOffset + 1, r, 0, kForegroundFill); } switch(Base::_fillMode) { case kNoFill: - drawCircleAlg(x, y, r, _fgColor, false); + drawCircleAlg(x, y, r, _fgColor, kNoFill); break; case kForegroundFill: - drawCircleAlg(x, y, r, _fgColor, true); + drawCircleAlg(x, y, r, _fgColor, kForegroundFill); break; case kBackgroundFill: - VectorRendererSpec::drawCircleAlg(x, y, r, _bgColor, true); - drawCircleAlg(x, y, r, _fgColor, false); + drawCircleAlg(x, y, r, _fgColor, kForegroundFill); + drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kBackgroundFill); break; case kGradientFill: @@ -116,24 +138,26 @@ template void VectorRendererSpec:: 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); + drawSquareShadow(x, y, w, h); } switch(Base::_fillMode) { case kNoFill: - drawSquareAlg(x, y, w, h, _fgColor, false); + drawSquareAlg(x, y, w, h, _fgColor, kNoFill); break; case kForegroundFill: - drawSquareAlg(x, y, w, h, _fgColor, true); + drawSquareAlg(x, y, w, h, _fgColor, kForegroundFill); break; case kBackgroundFill: - drawSquareAlg(x, y, w, h, _bgColor, true); - drawSquareAlg(x, y, w, h, _fgColor, false); + drawSquareAlg(x, y, w, h, _bgColor, kBackgroundFill); + drawSquareAlg(x, y, w, h, _fgColor, kNoFill); break; case kGradientFill: + VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kGradientFill); + drawSquareAlg(x, y, w, h, _fgColor, kNoFill); break; } } @@ -142,37 +166,48 @@ template void VectorRendererSpec:: 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); + drawRoundedSquareShadow(x, y, r, w, h); } switch(Base::_fillMode) { case kNoFill: - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill); break; case kForegroundFill: - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, true); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kForegroundFill); break; case kBackgroundFill: - VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, _bgColor, true); - drawRoundedSquareAlg(x, y, r, w, h, _fgColor, false); + VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, _bgColor, kBackgroundFill); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill); break; case kGradientFill: + if (Base::_strokeWidth > 1) { + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kForegroundFill); + VectorRendererSpec::drawRoundedSquareAlg(x + Base::_strokeWidth/2, y + Base::_strokeWidth/2, + r - Base::_strokeWidth/2, w - Base::_strokeWidth, h - Base::_strokeWidth, 0, kGradientFill); + } else { + VectorRendererSpec::drawRoundedSquareAlg(x, y, r, w, h, 0, kGradientFill); + drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill); + } break; } } template void VectorRendererSpec:: -drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill) { - +drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m) { PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y); int pitch = Base::surfacePitch(); + int max_h = h; - if (fill) { + if (fill_m != kNoFill) { while (h--) { + if (fill_m == kGradientFill) + color = calcGradient(max_h - h, max_h); + Common::set_to(ptr, ptr + w, color); ptr += pitch; } @@ -193,6 +228,43 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, bool fill) { } } +template +void VectorRendererSpec:: +drawSquareShadow(int x, int y, int w, int h) { + int blur = 8; + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur); + int pitch = Base::surfacePitch(); + int i, j; + + i = h - blur; + + while (i--) { + j = blur; + while (j--) + blendPixelPtr(ptr + j, 0, ((blur - j) << 8) / blur); + ptr += pitch; + } + + ptr = (PixelType *)_activeSurface->getBasePtr(x + blur, y + h - 1); + + while (i++ < blur) { + j = w - blur; + while (j--) + blendPixelPtr(ptr + j, 0, ((blur - i) << 8) / blur); + ptr += pitch; + } + + ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h); + + i = 0; + while (i++ < blur) { + j = blur - 1; + while (j--) + blendPixelPtr(ptr + j, 0, (((blur - j) * (blur - i)) << 8) / (blur * blur)); + ptr += pitch; + } +} + template void VectorRendererSpec:: drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) { @@ -361,29 +433,6 @@ drawLine(int x1, int y1, int x2, int y2) { } } -inline uint32 fp_sqroot(uint32 x) { - register uint32 root, remHI, remLO, testDIV, count; - - root = 0; - remHI = 0; - remLO = x; - count = 23; - - do { - remHI = (remHI << 2) | (remLO >> 30); - remLO <<= 2; - root <<= 1; - testDIV = (root << 1) + 1; - - if (remHI >= testDIV) { - remHI -= testDIV; - root++; - } - } while (count--); - - return root; -} - #define __BE_ALGORITHM() { \ if (f >= 0) { \ y--; \ @@ -416,13 +465,13 @@ inline uint32 fp_sqroot(uint32 x) { template void VectorRendererSpec:: -drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { +drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { int f, ddF_x, ddF_y; int x, y, px, py, sw = 0; int pitch = Base::surfacePitch(); PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - if (fill == false) { + if (fill_m == kNoFill) { while (sw++ < Base::_strokeWidth) { __BE_RESET(); r--; @@ -458,7 +507,13 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { template void VectorRendererSpec:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill) { +drawRoundedSquareShadow(int x1, int y1, int r, int w, int h) { + +} + +template +void VectorRendererSpec:: +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m) { int f, ddF_x, ddF_y; int x, y, px, py; int pitch = Base::surfacePitch(); @@ -470,10 +525,11 @@ 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); - int short_h = h - (2 * r) + 2; int real_radius = r; + int short_h = h - (2 * r) + 2; + int long_h = h; - if (fill == false) { + if (fill_m == kNoFill) { 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); @@ -501,20 +557,34 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool } } else { __BE_RESET(); - while (x++ < y) { - __BE_ALGORITHM(); - Common::set_to(ptr_tl - x - py, ptr_tr + x - py, color); - Common::set_to(ptr_tl - y - px, ptr_tr + y - px, color); + if (fill_m == kGradientFill) { + while (x++ < y) { + __BE_ALGORITHM(); + Common::set_to(ptr_tl - x - py, ptr_tr + x - py, calcGradient(real_radius - y, long_h)); + Common::set_to(ptr_tl - y - px, ptr_tr + y - px, calcGradient(real_radius - x, long_h)); - Common::set_to(ptr_bl - x + py, ptr_br + x + py, color); - Common::set_to(ptr_bl - y + px, ptr_br + y + px, color); + Common::set_to(ptr_bl - x + py, ptr_br + x + py, calcGradient(long_h - r + y, long_h)); + Common::set_to(ptr_bl - y + px, ptr_br + y + px, calcGradient(long_h - r + x, long_h)); + } + } else { + while (x++ < y) { + __BE_ALGORITHM(); + + 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); - __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + __BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + } } ptr_fill += pitch * r; while (short_h--) { + if (fill_m == kGradientFill) + color = calcGradient(real_radius++, long_h); Common::set_to(ptr_fill, ptr_fill + w + 1, color); ptr_fill += pitch; } @@ -545,7 +615,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool template void VectorRendererAA:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill) { +drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m) { int x, y; int p = Base::surfacePitch(), px, py; int sw = 0, sp = 0, hp = h * p; @@ -562,7 +632,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool int short_h = h - 2 * r; - if (fill == false) { + if (fill_m == kNoFill) { 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); @@ -614,7 +684,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool template void VectorRendererAA:: -drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { +drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) { int x, y, sw = 0; int p = Base::surfacePitch(), px, py; @@ -624,7 +694,7 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1); - if (fill == false) { + if (fill_m == kNoFill) { while (sw++ < Base::_strokeWidth) { x = r - (sw - 1); y = 0; T = 0; px = p * x; py = 0; @@ -662,4 +732,4 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, bool fill) { } } -} // end of namespace Graphics +} // end of namespace Graphics \ No newline at end of file diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index bed1e337ca..23653aa5fc 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -157,6 +157,8 @@ public: */ virtual void setBgColor(uint8 r, uint8 g, uint8 b) = 0; + virtual void setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) = 0; + /** * Sets the active drawing surface. All drawing from this * point on will be done on that surface. @@ -298,6 +300,15 @@ public: this->_bgColor = RGBToColor(r, g, b); } + void setGradientColors(uint8 r1, uint8 g1, uint8 b1, uint8 r2, uint8 g2, uint8 b2) { + _gradientEnd = RGBToColor(r2, g2, b2); + _gradientStart = RGBToColor(r1, g1, b1); + + _gradientBytes[0] = (_gradientEnd & PixelFormat::kRedMask) - (_gradientStart & PixelFormat::kRedMask); + _gradientBytes[1] = (_gradientEnd & PixelFormat::kGreenMask) - (_gradientStart & PixelFormat::kGreenMask); + _gradientBytes[2] = (_gradientEnd & PixelFormat::kBlueMask) - (_gradientStart & PixelFormat::kBlueMask); + } + /** * @see VectorRenderer::fillSurface() */ @@ -342,6 +353,10 @@ protected: putPixel(x, y, color); } + virtual inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) { + *ptr = (PixelType)color; + } + /* * "Bresenham's Line Algorithm", as described in Wikipedia. * Based on the current implementation in "graphics/primitives.cpp". @@ -350,12 +365,30 @@ protected: * floating point operations and direct access to pixel buffer, assumes no special cases. */ virtual void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color); - virtual void drawCircleAlg(int x, int y, int r, PixelType color, bool fill = false); - 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); + virtual void drawCircleAlg(int x, int y, int r, PixelType color, FillMode fill_m); + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m); + virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m); + virtual void drawSquareShadow(int x, int y, int w, int h); + virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h); + + inline PixelType calcGradient(int pos, int max, int factor = 1) { + PixelType output = 0; + pos = (0x1000 * MIN(pos * factor, max)) / max; + + output |= (_gradientStart + (_gradientBytes[0] * pos >> 12)) & PixelFormat::kRedMask; + output |= (_gradientStart + (_gradientBytes[1] * pos >> 12)) & PixelFormat::kGreenMask; + output |= (_gradientStart + (_gradientBytes[2] * pos >> 12)) & PixelFormat::kBlueMask; + output |= ~(PixelFormat::kRedMask | PixelFormat::kGreenMask | PixelFormat::kBlueMask); + + return output; + } PixelType _fgColor; /** Foreground color currently being used to draw on the renderer */ PixelType _bgColor; /** Background color currently being used to draw on the renderer */ + + PixelType _gradientStart; + PixelType _gradientEnd; + int _gradientBytes[3]; }; /** @@ -396,7 +429,7 @@ protected: * @param ptr Pointer to the pixel where we must draw * @param alpha Intensity of the pixel (0-255). */ - inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha); + inline virtual void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha); /** * @see VectorRenderer::blendPixel() @@ -420,9 +453,9 @@ protected: * * @see VectorRenderer::drawCircleAlg() */ - virtual void drawCircleAlg(int x, int y, int r, PixelType color, bool fill = false); + virtual void drawCircleAlg(int x, int y, int r, PixelType color, FillMode fill_m); - virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, bool fill = false); + virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m); }; } // end of namespace Graphics -- cgit v1.2.3