aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVicent Marti2008-05-18 00:18:15 +0000
committerVicent Marti2008-05-18 00:18:15 +0000
commit55cfae33e9b54d10b602eb9ecc52aee294408a2f (patch)
tree3064e892f24a5896cba12067cd95098e70178bd4
parent4d439fe4fc19030b5b5a8b5f80b073e5644cab09 (diff)
downloadscummvm-rg350-55cfae33e9b54d10b602eb9ecc52aee294408a2f.tar.gz
scummvm-rg350-55cfae33e9b54d10b602eb9ecc52aee294408a2f.tar.bz2
scummvm-rg350-55cfae33e9b54d10b602eb9ecc52aee294408a2f.zip
- Shadows revisited.
- Test rendering... starting to look like a GUI. svn-id: r32164
-rw-r--r--graphics/VectorRenderer.cpp120
-rw-r--r--graphics/VectorRenderer.h118
2 files changed, 148 insertions, 90 deletions
diff --git a/graphics/VectorRenderer.cpp b/graphics/VectorRenderer.cpp
index 47f46e3bcf..221f525820 100644
--- a/graphics/VectorRenderer.cpp
+++ b/graphics/VectorRenderer.cpp
@@ -81,19 +81,25 @@ void vector_renderer_test(OSystem *_system) {
while (true) { // draw!!
vr->setFgColor(255, 0, 206);
- vr->fillSurface();
+ vr->setGradientFactor(1);
+ vr->setGradientColors(214, 113, 8, 240, 200, 25);
+ vr->fillSurface(VectorRenderer::kGradientFill);
- vr->setFgColor(255, 247, 222);
vr->setBgColor(25, 25, 175);
- vr->setGradientColors(206, 121, 99, 173, 40, 8);
- vr->setFillMode(VectorRenderer::kGradientFill);
+ vr->shadowEnable(3);
+ vr->setFgColor(240, 204, 120);
vr->setStrokeWidth(1);
- vr->shadowEnable(1, 1);
+ vr->setFillMode(VectorRenderer::kGradientFill);
- vr->drawLine(25, 25, 125, 300);
- vr->drawCircle(250, 250, 100);
- vr->drawSquare(150, 25, 100, 75);
- vr->drawRoundedSquare(275, 25, 16, 128, 128);
+ vr->setGradientFactor(3);
+ vr->setGradientColors(255, 231, 140, 255, 243, 206);
+ vr->drawRoundedSquare(25, 95, 18, 465, 290);
+
+ vr->setGradientFactor(1);
+ vr->setGradientColors(206, 121, 99, 173, 40, 8);
+ vr->drawRoundedSquare(500, 95, 8, 120, 30);
+ vr->drawRoundedSquare(500, 135, 8, 120, 30);
+ vr->drawRoundedSquare(500, 175, 8, 120, 30);
_system->copyRectToOverlay((OverlayColor*)_screen.getBasePtr(0, 0), _screen.w, 0, 0, _screen.w, _screen.w);
_system->updateScreen();
@@ -111,13 +117,14 @@ 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, kForegroundFill);
+ if (Base::_fillMode != kNoFill && Base::_shadowOffset) {
+ drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kForegroundFill);
}
switch(Base::_fillMode) {
case kNoFill:
- drawCircleAlg(x, y, r, _fgColor, kNoFill);
+ if (Base::_strokeWidth)
+ drawCircleAlg(x, y, r, _fgColor, kNoFill);
break;
case kForegroundFill:
@@ -125,8 +132,13 @@ drawCircle(int x, int y, int r) {
break;
case kBackgroundFill:
- drawCircleAlg(x, y, r, _fgColor, kForegroundFill);
- drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kBackgroundFill);
+ if (Base::_strokeWidth > 1) {
+ drawCircleAlg(x, y, r, _fgColor, kForegroundFill);
+ drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kBackgroundFill);
+ } else {
+ drawCircleAlg(x, y, r, _bgColor, kBackgroundFill);
+ drawCircleAlg(x, y, r, _fgColor, kNoFill);
+ }
break;
case kGradientFill:
@@ -137,13 +149,14 @@ drawCircle(int x, int y, int r) {
template<typename PixelType, typename PixelFormat>
void VectorRendererSpec<PixelType, PixelFormat>::
drawSquare(int x, int y, int w, int h) {
- if (Base::_fillMode != kNoFill && Base::_shadows) {
- drawSquareShadow(x, y, w, h);
+ if (Base::_fillMode != kNoFill && Base::_shadowOffset) {
+ drawSquareShadow(x, y, w, h, Base::_shadowOffset);
}
switch(Base::_fillMode) {
case kNoFill:
- drawSquareAlg(x, y, w, h, _fgColor, kNoFill);
+ if (Base::_strokeWidth)
+ drawSquareAlg(x, y, w, h, _fgColor, kNoFill);
break;
case kForegroundFill:
@@ -157,7 +170,8 @@ drawSquare(int x, int y, int w, int h) {
case kGradientFill:
VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kGradientFill);
- drawSquareAlg(x, y, w, h, _fgColor, kNoFill);
+ if (Base::_strokeWidth)
+ drawSquareAlg(x, y, w, h, _fgColor, kNoFill);
break;
}
}
@@ -165,13 +179,14 @@ drawSquare(int x, int y, int w, int h) {
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) {
- drawRoundedSquareShadow(x, y, r, w, h);
+ if (Base::_fillMode != kNoFill && Base::_shadowOffset) {
+ drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
}
switch(Base::_fillMode) {
case kNoFill:
- drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill);
+ if (Base::_strokeWidth)
+ drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill);
break;
case kForegroundFill:
@@ -190,7 +205,8 @@ drawRoundedSquare(int x, int y, int r, int w, int h) {
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);
+ if (Base::_strokeWidth)
+ drawRoundedSquareAlg(x, y, r, w, h, _fgColor, kNoFill);
}
break;
}
@@ -230,8 +246,7 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m) {
template<typename PixelType, typename PixelFormat>
void VectorRendererSpec<PixelType, PixelFormat>::
-drawSquareShadow(int x, int y, int w, int h) {
- int blur = 8;
+drawSquareShadow(int x, int y, int w, int h, int blur) {
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur);
int pitch = Base::surfacePitch();
int i, j;
@@ -314,7 +329,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
template<typename PixelType, typename PixelFormat>
-void VectorRendererAA<PixelType, PixelFormat>::
+void VectorRendererSpec<PixelType, PixelFormat>::
blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) {
if (alpha == 255) {
*ptr = color;
@@ -404,6 +419,9 @@ drawLine(int x1, int y1, int x2, int y2) {
if (dy == 0 && dx == 0)
return;
+ if (Base::_strokeWidth == 0)
+ return;
+
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
int pitch = Base::surfacePitch();
@@ -507,8 +525,57 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, FillMode fill_m) {
template<typename PixelType, typename PixelFormat>
void VectorRendererSpec<PixelType, PixelFormat>::
-drawRoundedSquareShadow(int x1, int y1, int r, int w, int h) {
+drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) {
+ int f, ddF_x, ddF_y;
+ int x, y, px, py;
+ int pitch = Base::surfacePitch();
+ int sw = 0, sp = 0, hp = h * pitch;
+ int alpha = 102;
+
+ x1 += blur;
+ y1 += blur;
+
+ 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 + w - blur, y1 + r);
+
+ int short_h = h - (2 * r) + 1;
+
+ __BE_RESET();
+
+ // HACK: As we are drawing circles exploting 8-axis symmetry,
+ // there are 4 pixels on each circle which are drawn twice.
+ // this is ok on filled circles, but when blending on surfaces,
+ // we cannot let it blend twice. awful.
+ bool *hb = new bool[r];
+ int i = 0;
+ while (i < r)
+ hb[i++] = false;
+
+ while (x++ < y) {
+ __BE_ALGORITHM();
+
+ if (!hb[x]) {
+ blendFill(ptr_tr - px - r, ptr_tr + y - px, 0, alpha);
+ blendFill(ptr_bl - y + px, ptr_br + y + px, 0, alpha);
+ hb[x] = true;
+ }
+
+ if (!hb[y]) {
+ blendFill(ptr_tr - r - py, ptr_tr + x - py, 0, alpha);
+ blendFill(ptr_bl - x + py, ptr_br + x + py, 0, alpha);
+ hb[y] = true;
+ }
+ }
+
+ delete[] hb;
+
+ while (short_h--) {
+ blendFill(ptr_fill - r, ptr_fill + blur, 0, alpha);
+ ptr_fill += pitch;
+ }
}
template<typename PixelType, typename PixelFormat>
@@ -577,6 +644,7 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillM
Common::set_to(ptr_bl - x + py, ptr_br + x + py, color);
Common::set_to(ptr_bl - y + px, ptr_br + y + px, color);
+ // FIXME: maybe not needed at all?
__BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py);
}
}
diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index b7b19a77e7..028b0ba74a 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), _strokeWidth(1) {}
+ VectorRenderer() : _shadowOffset(0), _fillMode(kNoFill), _activeSurface(NULL), _strokeWidth(1), _gradientFactor(1) {}
virtual ~VectorRenderer() {}
enum FillMode {
@@ -63,10 +63,10 @@ public:
kGradientFill = 3
};
- enum ColorMode {
+/* enum ColorMode {
kForegroundColor,
kBackgroundColor
- };
+ }; */
/**
* Draws a line by considering the special cases for optimization.
@@ -175,7 +175,7 @@ public:
*
* @param mode Color mode (bg or fg color) used to fill.
*/
- virtual void fillSurface(ColorMode mode = kForegroundColor) = 0;
+ virtual void fillSurface(FillMode mode = kForegroundFill) = 0;
/**
* Clears the active surface.
@@ -202,7 +202,7 @@ public:
* @param width Witdh of the stroke in pixels.
*/
virtual void setStrokeWidth(int width) {
- if (width > 0) _strokeWidth = width;
+ _strokeWidth = width;
}
/**
@@ -214,10 +214,9 @@ public:
* @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;
+ virtual void shadowEnable(int offset) {
+ if (offset > 0)
+ _shadowOffset = offset;
}
/**
@@ -226,7 +225,12 @@ public:
* @see shadowEnable()
*/
virtual void shadowDisable() {
- _shadows = false;
+ _shadowOffset = 0;
+ }
+
+ virtual void setGradientFactor(int factor) {
+ if (factor > 0)
+ _gradientFactor = factor;
}
protected:
@@ -234,11 +238,11 @@ protected:
FillMode _fillMode; /** Defines in which way (if any) are filled the drawn shapes */
- 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 _shadowOffset; /** offset for drawn shadows */
int _strokeWidth; /** Width of the stroke of all drawn shapes */
+
+ int _gradientFactor;
+ int _gradientBytes[3];
};
@@ -304,22 +308,32 @@ public:
_gradientEnd = RGBToColor<PixelFormat>(r2, g2, b2);
_gradientStart = RGBToColor<PixelFormat>(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);
+ Base::_gradientBytes[0] = (_gradientEnd & PixelFormat::kRedMask) - (_gradientStart & PixelFormat::kRedMask);
+ Base::_gradientBytes[1] = (_gradientEnd & PixelFormat::kGreenMask) - (_gradientStart & PixelFormat::kGreenMask);
+ Base::_gradientBytes[2] = (_gradientEnd & PixelFormat::kBlueMask) - (_gradientStart & PixelFormat::kBlueMask);
}
/**
* @see VectorRenderer::fillSurface()
*/
- void fillSurface(ColorMode mode = kForegroundColor) {
+ void fillSurface(FillMode mode = kForegroundFill) {
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(0, 0);
- int s = _activeSurface->w * _activeSurface->h;
- if (mode == kBackgroundColor)
- Common::set_to(ptr, ptr + s, _bgColor);
- else if (mode == kForegroundColor)
- Common::set_to(ptr, ptr + s, _fgColor);
+ int w = _activeSurface->w;
+ int h = _activeSurface->h ;
+ int pitch = surfacePitch();
+
+ if (mode == kBackgroundFill)
+ Common::set_to(ptr, ptr + w*h, _bgColor);
+ else if (mode == kForegroundFill)
+ Common::set_to(ptr, ptr + w*h, _fgColor);
+ else if (mode == kGradientFill) {
+ int i = h;
+ while (i--) {
+ Common::set_to(ptr, ptr + w, calcGradient(h - i, h));
+ ptr += pitch;
+ }
+ }
}
protected:
@@ -341,21 +355,19 @@ protected:
* Blends a single pixel on the surface with the given coordinates, color
* and Alpha intensity.
*
- * Note: Pixel blending is currently disabled on the Specialized Renderer
- * because of performance issues.
- *
* @param x Horizontal coordinate of the pixel.
* @param y Vertical coordinate of the pixel.
* @param color Color of the pixel
* @param alpha Alpha intensity of the pixel (0-255)
*/
virtual inline void blendPixel(int x, int y, PixelType color, uint8 alpha) {
- putPixel(x, y, color);
+ if (alpha == 255)
+ putPixel(x, y, color);
+ else if (alpha > 0)
+ blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), color, alpha);
}
- virtual inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) {
- *ptr = (PixelType)color;
- }
+ virtual inline void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha);
/*
* "Bresenham's Line Algorithm", as described in Wikipedia.
@@ -368,27 +380,31 @@ protected:
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);
+ virtual void drawSquareShadow(int x, int y, int w, int h, int blur);
+ virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur);
- inline PixelType calcGradient(int pos, int max, int factor = 1) {
+ inline PixelType calcGradient(uint32 pos, uint32 max) {
PixelType output = 0;
- pos = (0x1000 * MIN(pos * factor, max)) / max;
+ pos = (MIN(pos * Base::_gradientFactor, max) << 12) / 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 |= (_gradientStart + ((Base::_gradientBytes[0] * pos) >> 12)) & PixelFormat::kRedMask;
+ output |= (_gradientStart + ((Base::_gradientBytes[1] * pos) >> 12)) & PixelFormat::kGreenMask;
+ output |= (_gradientStart + ((Base::_gradientBytes[2] * pos) >> 12)) & PixelFormat::kBlueMask;
output |= ~(PixelFormat::kRedMask | PixelFormat::kGreenMask | PixelFormat::kBlueMask);
return output;
}
+ inline void blendFill(PixelType *first, PixelType *last, PixelType color, uint8 alpha) {
+ while (first != last)
+ blendPixelPtr(first++, color, alpha);
+ }
+
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];
};
/**
@@ -419,32 +435,6 @@ protected:
void drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color);
/**
- * Perform alpha blending on top of a given pixel, not on a given
- * coordinate (just so we don't have to recalculate the surface
- * pointer while we are blending consecutive pixels).
- *
- * Everything from blendPixel() applies here.
- *
- * @see VectorRenderer::blendPixel()
- * @param ptr Pointer to the pixel where we must draw
- * @param alpha Intensity of the pixel (0-255).
- */
- inline virtual void blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha);
-
- /**
- * @see VectorRenderer::blendPixel()
- *
- * The AA renderer does support alpha blending. Special cases are
- * handled separately.
- */
- inline void blendPixel(int x, int y, PixelType color, uint8 alpha) {
- if (alpha == 255)
- putPixel(x, y, color);
- else if (alpha > 0)
- blendPixelPtr((PixelType*)Base::_activeSurface->getBasePtr(x, y), color, alpha);
- }
-
- /**
* "Wu's Circle Antialiasing Algorithm" as published by Xiaolin Wu, July 1991
* Based on the theoretical concept of the algorithm.
*