aboutsummaryrefslogtreecommitdiff
path: root/graphics
diff options
context:
space:
mode:
authorNarek Mailian2013-07-01 21:55:09 +0000
committerNarek Mailian2013-08-16 20:54:08 +0200
commit5c00dbbd2ac3d39e4ef801f3b50c3bb057422072 (patch)
treef54c2d3c91066efdfe26a00c1a4e078b2872c0e9 /graphics
parent887a99e211c25fd16e4cf3b7505ae17678c2f997 (diff)
downloadscummvm-rg350-5c00dbbd2ac3d39e4ef801f3b50c3bb057422072.tar.gz
scummvm-rg350-5c00dbbd2ac3d39e4ef801f3b50c3bb057422072.tar.bz2
scummvm-rg350-5c00dbbd2ac3d39e4ef801f3b50c3bb057422072.zip
GRAPHICS: Add support for Soft Shadows with rounded squares
Diffstat (limited to 'graphics')
-rw-r--r--graphics/VectorRenderer.h14
-rw-r--r--graphics/VectorRendererSpec.cpp120
-rw-r--r--graphics/VectorRendererSpec.h12
3 files changed, 92 insertions, 54 deletions
diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h
index 4ca76224e1..8e1c5e91e1 100644
--- a/graphics/VectorRenderer.h
+++ b/graphics/VectorRenderer.h
@@ -73,6 +73,8 @@ struct DrawStep {
uint8 shadow, stroke, factor, radius, bevel; /**< Misc options... */
uint8 fillMode; /**< active fill mode */
+ uint8 shadowFillMode; /**< fill mode of the shadow used */
+
uint32 extraData; /**< Generic parameter for extra options (orientation/bevel) */
uint32 scale; /**< scale of all the coordinates in FIXED POINT with 16 bits mantissa */
@@ -103,7 +105,7 @@ VectorRenderer *createRenderer(int mode);
*/
class VectorRenderer {
public:
- VectorRenderer() : _activeSurface(NULL), _fillMode(kFillDisabled), _shadowOffset(0),
+ VectorRenderer() : _activeSurface(NULL), _fillMode(kFillDisabled), _shadowOffset(0), _shadowFillMode(kShadowExponential),
_disableShadows(false), _strokeWidth(1), _gradientFactor(1) {
}
@@ -126,6 +128,11 @@ public:
kTriangleRight
};
+ enum ShadowFillMode {
+ kShadowLinear = 0,
+ kShadowExponential = 1
+ };
+
/**
* Draws a line by considering the special cases for optimization.
*
@@ -292,6 +299,10 @@ public:
_fillMode = mode;
}
+ virtual void setShadowFillMode(ShadowFillMode mode) {
+ _shadowFillMode = mode;
+ }
+
/**
* Sets the stroke width. All shapes drawn with a stroke will
* have that width. Pass 0 to disable shape stroking.
@@ -485,6 +496,7 @@ protected:
Surface *_activeSurface; /**< Pointer to the surface currently being drawn */
FillMode _fillMode; /**< Defines in which way (if any) are filled the drawn shapes */
+ ShadowFillMode _shadowFillMode;
int _shadowOffset; /**< offset for drawn shadows */
int _bevel; /**< amount of fake bevel */
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index f9041fc8ff..85865124a6 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -883,7 +883,8 @@ drawRoundedSquare(int x, int y, int r, int w, int h) {
if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
&& x + w + Base::_shadowOffset + 1 < Base::_activeSurface->w
- && y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h) {
+ && y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h
+ && h > (Base::_shadowOffset + 1) * 2) {
drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
}
@@ -1704,85 +1705,112 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode f
********************************************************************/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
-drawSquareShadow(int x, int y, int w, int h, int blur) {
- PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur);
+drawSquareShadow(int x, int y, int w, int h, int offset) {
+ PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + offset);
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int i, j;
- i = h - blur;
+ i = h - offset;
while (i--) {
- j = blur;
+ j = offset;
while (j--)
- blendPixelPtr(ptr + j, 0, ((blur - j) << 8) / blur);
+ blendPixelPtr(ptr + j, 0, ((offset - j) << 8) / offset);
ptr += pitch;
}
- ptr = (PixelType *)_activeSurface->getBasePtr(x + blur, y + h - 1);
+ ptr = (PixelType *)_activeSurface->getBasePtr(x + offset, y + h - 1);
- while (i++ < blur) {
- j = w - blur;
+ while (i++ < offset) {
+ j = w - offset;
while (j--)
- blendPixelPtr(ptr + j, 0, ((blur - i) << 8) / blur);
+ blendPixelPtr(ptr + j, 0, ((offset - i) << 8) / offset);
ptr += pitch;
}
ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h);
i = 0;
- while (i++ < blur) {
- j = blur - 1;
+ while (i++ < offset) {
+ j = offset - 1;
while (j--)
- blendPixelPtr(ptr + j, 0, (((blur - j) * (blur - i)) << 8) / (blur * blur));
+ blendPixelPtr(ptr + j, 0, (((offset - j) * (offset - i)) << 8) / (offset * offset));
ptr += pitch;
}
}
template<typename PixelType>
void VectorRendererSpec<PixelType>::
-drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) {
- int f, ddF_x, ddF_y;
- int x, y, px, py;
+drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
- 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);
+ // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
+ double expFactor = (_activeSurface->format.bytesPerPixel > 2) ? 1.60 : 1.25;
+ double alpha = (_activeSurface->format.bytesPerPixel > 2) ? 1 : 8;
+
+ // These constants ensure a border of 2px on the left and of each rounded square
+ int xstart = (x1 > 2) ? x1 - 2 : x1;
+ int ystart = y1;
+ int width = w + offset + 2;
+ int height = h + offset + 1;
+
+ for (int i = offset; i >= 0; i--) {
+ int f, ddF_x, ddF_y;
+ int x, y, px, py;
+
+ PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + r);
+ PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + r);
+ PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(xstart + r, ystart + height - r);
+ PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(xstart + width - r, ystart + height - r);
+ PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
+
+ int short_h = height - (2 * r) + 2;
+ PixelType color = _format.RGBToColor(0, 0, 0);
- int short_h = h - (2 * r) + 1;
+ BE_RESET();
- 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.
+ uint32 hb = 0;
+
+ while (x++ < y) {
+ BE_ALGORITHM();
- // 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.
- uint32 hb = 0;
- while (x++ < y) {
- BE_ALGORITHM();
+ if (((1 << x) & hb) == 0) {
+ blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
+
+ // Will create a dark line of pixles if left out
+ if (hb > 0) {
+ blendFill(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha);
+ }
+ hb |= (1 << x);
+ }
- if (((1 << x) & hb) == 0) {
- blendFill(ptr_tr - px - r, ptr_tr + y - px, 0, alpha);
- blendFill(ptr_bl - y + px, ptr_br + y + px, 0, alpha);
- hb |= (1 << x);
+ if (((1 << y) & hb) == 0) {
+ blendFill(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha);
+ blendFill(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha);
+ hb |= (1 << y);
+ }
}
-
- if (((1 << y) & hb) == 0) {
- blendFill(ptr_tr - r - py, ptr_tr + x - py, 0, alpha);
- blendFill(ptr_bl - x + py, ptr_br + x + py, 0, alpha);
- hb |= (1 << y);
+
+ ptr_fill += pitch * r;
+ while (short_h--) {
+ blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha);
+ ptr_fill += pitch;
}
- }
- while (short_h--) {
- blendFill(ptr_fill - r, ptr_fill + blur, 0, alpha);
- ptr_fill += pitch;
+ // Make shadow smaller each iteration, and move it one pixel inward
+ xstart += 1;
+ ystart += 1;
+ width -= 2;
+ height -= 2;
+
+ if (_shadowFillMode == kShadowExponential)
+ // Multiply with expfactor
+ alpha = alpha * expFactor;
}
}
diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h
index 08d00dd569..35b7af32f7 100644
--- a/graphics/VectorRendererSpec.h
+++ b/graphics/VectorRendererSpec.h
@@ -186,10 +186,10 @@ protected:
* There functions may be overloaded in inheriting classes to improve performance
* in the slowest platforms where pixel alpha blending just doesn't cut it.
*
- * @param blur Intensity/size of the shadow.
+ * @param offset Intensity/size of the shadow.
*/
- 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);
+ virtual void drawSquareShadow(int x, int y, int w, int h, int offset);
+ virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset);
/**
* Calculates the color gradient on a given point.
@@ -292,10 +292,8 @@ protected:
*/
virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m);
- virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur) {
- Base::drawRoundedSquareShadow(x, y, r, w, h, blur);
-// VectorRenderer::applyConvolutionMatrix(VectorRenderer::kConvolutionHardBlur,
-// Common::Rect(x, y, x + w + blur * 2, y + h + blur * 2));
+ virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset) {
+ Base::drawRoundedSquareShadow(x, y, r, w, h, offset);
}
virtual void drawTabAlg(int x, int y, int w, int h, int r,