aboutsummaryrefslogtreecommitdiff
path: root/graphics/VectorRendererSpec.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'graphics/VectorRendererSpec.cpp')
-rw-r--r--graphics/VectorRendererSpec.cpp1787
1 files changed, 1773 insertions, 14 deletions
diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp
index 81a0c04441..fc741f6e77 100644
--- a/graphics/VectorRendererSpec.cpp
+++ b/graphics/VectorRendererSpec.cpp
@@ -108,6 +108,33 @@ inline frac_t fp_sqroot(uint32 x) {
BE_DRAWCIRCLE_BOTTOM(ptr3,ptr4,x,y,px,py); \
} while (0)
+#define BE_DRAWCIRCLE_TOP_CLIP(ptr1,ptr2,x,y,px,py,realX1,realY1,realX2,realY2) do { \
+ if (IS_IN_CLIP((realX1) + (y), (realY1) - (x))) \
+ *(ptr1 + (y) - (px)) = color; \
+ if (IS_IN_CLIP((realX1) + (x), (realY1) - (y))) \
+ *(ptr1 + (x) - (py)) = color; \
+ if (IS_IN_CLIP((realX2) - (x), (realY2) - (y))) \
+ *(ptr2 - (x) - (py)) = color; \
+ if (IS_IN_CLIP((realX2) - (y), (realY2) - (x))) \
+ *(ptr2 - (y) - (px)) = color; \
+} while (0)
+
+#define BE_DRAWCIRCLE_BOTTOM_CLIP(ptr3,ptr4,x,y,px,py,realX3,realY3,realX4,realY4) do { \
+ if (IS_IN_CLIP((realX3) - (y), (realY3) + (x))) \
+ *(ptr3 - (y) + (px)) = color; \
+ if (IS_IN_CLIP((realX3) - (x), (realY3) + (y))) \
+ *(ptr3 - (x) + (py)) = color; \
+ if (IS_IN_CLIP((realX4) + (x), (realY4) + (y))) \
+ *(ptr4 + (x) + (py)) = color; \
+ if (IS_IN_CLIP((realX4) + (y), (realY4) + (x))) \
+ *(ptr4 + (y) + (px)) = color; \
+} while (0)
+
+#define BE_DRAWCIRCLE_CLIP(ptr1,ptr2,ptr3,ptr4,x,y,px,py,realX1,realY1,realX2,realY2,realX3,realY3,realX4,realY4) do { \
+ BE_DRAWCIRCLE_TOP_CLIP(ptr1,ptr2,x,y,px,py,realX1,realY1,realX2,realY2); \
+ BE_DRAWCIRCLE_BOTTOM_CLIP(ptr3,ptr4,x,y,px,py,realX3,realY3,realX4,realY4); \
+} while (0)
+
#define BE_DRAWCIRCLE_BCOLOR(ptr1,ptr2,ptr3,ptr4,x,y,px,py) do { \
*(ptr1 + (y) - (px)) = color1; \
*(ptr1 + (x) - (py)) = color1; \
@@ -119,6 +146,25 @@ inline frac_t fp_sqroot(uint32 x) {
*(ptr4 + (y) + (px)) = color2; \
} while (0)
+#define BE_DRAWCIRCLE_BCOLOR_CLIP(ptr1,ptr2,ptr3,ptr4,x,y,px,py,realX1,realY1,realX2,realY2,realX3,realY3,realX4,realY4) do { \
+ if (IS_IN_CLIP((realX1) + (y), (realY1) - (x))) \
+ *(ptr1 + (y) - (px)) = color1; \
+ if (IS_IN_CLIP((realX1) + (x), (realY1) - (y))) \
+ *(ptr1 + (x) - (py)) = color1; \
+ if (IS_IN_CLIP((realX2) - (x), (realY2) - (y))) \
+ *(ptr2 - (x) - (py)) = color1; \
+ if (IS_IN_CLIP((realX2) - (y), (realY2) - (x))) \
+ *(ptr2 - (y) - (px)) = color1; \
+ if (IS_IN_CLIP((realX3) - (y), (realY3) + (x))) \
+ *(ptr3 - (y) + (px)) = color1; \
+ if (IS_IN_CLIP((realX3) - (x), (realY3) + (y))) \
+ *(ptr3 - (x) + (py)) = color1; \
+ if (IS_IN_CLIP((realX4) + (x), (realY4) + (y))) \
+ *(ptr4 + (x) + (py)) = color2; \
+ if (IS_IN_CLIP((realX4) + (y), (realY4) + (x))) \
+ *(ptr4 + (y) + (px)) = color2; \
+} while (0)
+
#define BE_DRAWCIRCLE_BCOLOR_TR_CW(ptr,x,y,px,py,a) do { \
this->blendPixelPtr(ptr + (y) - (px), color, a); \
} while (0)
@@ -127,6 +173,16 @@ inline frac_t fp_sqroot(uint32 x) {
this->blendPixelPtr(ptr + (x) - (py), color, a); \
} while (0)
+#define BE_DRAWCIRCLE_BCOLOR_TR_CW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+ if (IS_IN_CLIP((realX) + (y), (realY) - (x))) \
+ this->blendPixelPtr(ptr + (y) - (px), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_TR_CCW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+ if (IS_IN_CLIP((realX) + (x), (realY) - (y))) \
+ this->blendPixelPtr(ptr + (x) - (py), color, a); \
+} while (0)
+
#define BE_DRAWCIRCLE_BCOLOR_TL_CW(ptr,x,y,px,py,a) do { \
this->blendPixelPtr(ptr - (x) - (py), color, a); \
} while (0)
@@ -135,6 +191,16 @@ inline frac_t fp_sqroot(uint32 x) {
this->blendPixelPtr(ptr - (y) - (px), color, a); \
} while (0)
+#define BE_DRAWCIRCLE_BCOLOR_TL_CW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+ if (IS_IN_CLIP((realX) - (x), (realY) - (y))) \
+ this->blendPixelPtr(ptr - (x) - (py), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_TL_CCW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+ if (IS_IN_CLIP((realX) - (y), (realY) - (x))) \
+ this->blendPixelPtr(ptr - (y) - (px), color, a); \
+} while (0)
+
#define BE_DRAWCIRCLE_BCOLOR_BL_CW(ptr,x,y,px,py,a) do { \
this->blendPixelPtr(ptr - (y) + (px), color, a); \
} while (0)
@@ -143,6 +209,16 @@ inline frac_t fp_sqroot(uint32 x) {
this->blendPixelPtr(ptr - (x) + (py), color, a); \
} while (0)
+#define BE_DRAWCIRCLE_BCOLOR_BL_CW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+ if (IS_IN_CLIP((realX) - (y), (realY) + (x))) \
+ this->blendPixelPtr(ptr - (y) + (px), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_BL_CCW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+ if (IS_IN_CLIP((realX) - (x), (realY) + (y))) \
+ this->blendPixelPtr(ptr - (x) + (py), color, a); \
+} while (0)
+
#define BE_DRAWCIRCLE_BCOLOR_BR_CW(ptr,x,y,px,py,a) do { \
this->blendPixelPtr(ptr + (x) + (py), color, a); \
} while (0)
@@ -151,6 +227,16 @@ inline frac_t fp_sqroot(uint32 x) {
this->blendPixelPtr(ptr + (y) + (px), color, a); \
} while (0)
+#define BE_DRAWCIRCLE_BCOLOR_BR_CW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+ if (IS_IN_CLIP((realX) + (x), (realY) + (y))) \
+ this->blendPixelPtr(ptr + (x) + (py), color, a); \
+} while (0)
+
+#define BE_DRAWCIRCLE_BCOLOR_BR_CCW_CLIP(ptr,x,y,px,py,a,realX,realY) do { \
+ if (IS_IN_CLIP((realX) + (y), (realY) + (x))) \
+ this->blendPixelPtr(ptr + (y) + (px), color, a); \
+} while (0)
+
#define BE_DRAWCIRCLE_XCOLOR_TOP(ptr1,ptr2,x,y,px,py) do { \
*(ptr1 + (y) - (px)) = color1; \
*(ptr1 + (x) - (py)) = color2; \
@@ -170,6 +256,42 @@ inline frac_t fp_sqroot(uint32 x) {
BE_DRAWCIRCLE_XCOLOR_BOTTOM(ptr3,ptr4,x,y,px,py); \
} while (0)
+#define IS_IN_CLIP(x,y) (_clippingArea.left <= (x) && (x) < _clippingArea.right \
+ && _clippingArea.top <= (y) && (y) < _clippingArea.bottom)
+
+#define BE_DRAWCIRCLE_XCOLOR_TOP_CLIP(ptr1,ptr2,x,y,px,py,realX1,realY1,realX2,realY2) do { \
+ if (IS_IN_CLIP((realX1) + (y), (realY1) - (x))) \
+ *(ptr1 + (y) - (px)) = color1; \
+\
+ if (IS_IN_CLIP((realX1) + (x), (realY1) - (y))) \
+ *(ptr1 + (x) - (py)) = color2; \
+\
+ if (IS_IN_CLIP((realX2) - (x), (realY2) - (y))) \
+ *(ptr2 - (x) - (py)) = color2; \
+\
+ if (IS_IN_CLIP((realX2) - (y), (realY2) - (x))) \
+ *(ptr2 - (y) - (px)) = color1; \
+} while (0)
+
+#define BE_DRAWCIRCLE_XCOLOR_BOTTOM_CLIP(ptr3,ptr4,x,y,px,py,realX3,realY3,realX4,realY4) do { \
+ if (IS_IN_CLIP((realX3) - (y), (realY3) + (x))) \
+ *(ptr3 - (y) + (px)) = color3; \
+\
+ if (IS_IN_CLIP((realX3) - (x), (realY3) + (y))) \
+ *(ptr3 - (x) + (py)) = color4; \
+\
+ if (IS_IN_CLIP((realX4) + (x), (realY4) + (y))) \
+ *(ptr4 + (x) + (py)) = color4; \
+\
+ if (IS_IN_CLIP((realX4) + (y), (realY4) + (x))) \
+ *(ptr4 + (y) + (px)) = color3; \
+} while (0)
+
+#define BE_DRAWCIRCLE_XCOLOR_CLIP(ptr1,ptr2,ptr3,ptr4,x,y,px,py,realX1,realY1,realX2,realY2,realX3,realY3,realX4,realY4) do { \
+ BE_DRAWCIRCLE_XCOLOR_TOP_CLIP(ptr1,ptr2,x,y,px,py,realX1,realY1,realX2,realY2); \
+ BE_DRAWCIRCLE_XCOLOR_BOTTOM_CLIP(ptr3,ptr4,x,y,px,py,realX3,realY3,realX4,realY4); \
+} while (0)
+
#define BE_RESET() do { \
f = 1 - r; \
@@ -337,6 +459,45 @@ void colorFill(PixelType *first, PixelType *last, PixelType color) {
}
}
+template<typename PixelType>
+void colorFillClip(PixelType *first, PixelType *last, PixelType color, int realX, int realY, Common::Rect &clippingArea) {
+ if (realY < clippingArea.top || realY >= clippingArea.bottom)
+ return;
+
+ register int count = (last - first);
+
+ if (realX > clippingArea.right || realX + count < clippingArea.left)
+ return;
+
+ if (realX < clippingArea.left) {
+ register int diff = (clippingArea.left - realX);
+ realX += diff;
+ count -= diff;
+ }
+
+ if (clippingArea.right <= realX + count) {
+ register int diff = (realX + count - clippingArea.right);
+ count -= diff;
+ }
+
+ if (!count)
+ return;
+
+ register int n = (count + 7) >> 3;
+ switch (count % 8) {
+ case 0: do {
+ *first++ = color;
+ case 7: *first++ = color;
+ case 6: *first++ = color;
+ case 5: *first++ = color;
+ case 4: *first++ = color;
+ case 3: *first++ = color;
+ case 2: *first++ = color;
+ case 1: *first++ = color;
+ } while (--n > 0);
+ }
+}
+
VectorRenderer *createRenderer(int mode) {
#ifdef DISABLE_FANCY_THEMES
@@ -376,6 +537,7 @@ VectorRendererSpec(PixelFormat format) :
_alphaMask((0xFF >> format.aLoss) << format.aShift) {
_bitmapAlphaColor = _format.RGBToColor(255, 0, 255);
+ _clippingArea = Common::Rect(0, 0, 32767, 32767);
}
/****************************
@@ -441,13 +603,56 @@ template<typename PixelType>
void VectorRendererSpec<PixelType>::
gradientFill(PixelType *ptr, int width, int x, int y) {
bool ox = ((y & 1) == 1);
- int stripSize;
int curGrad = 0;
while (_gradIndexes[curGrad + 1] <= y)
curGrad++;
- stripSize = _gradIndexes[curGrad + 1] - _gradIndexes[curGrad];
+ // precalcGradient assures that _gradIndexes entries always differ in
+ // their value. This assures stripSize is always different from zero.
+ int stripSize = _gradIndexes[curGrad + 1] - _gradIndexes[curGrad];
+
+ int grad = (((y - _gradIndexes[curGrad]) % stripSize) << 2) / stripSize;
+
+ // Dithering:
+ // +--+ +--+ +--+ +--+
+ // | | | | | *| | *|
+ // | | | *| |* | |**|
+ // +--+ +--+ +--+ +--+
+ // 0 1 2 3
+ if (grad == 0 ||
+ _gradCache[curGrad] == _gradCache[curGrad + 1] || // no color change
+ stripSize < 2) { // the stip is small
+ colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad]);
+ } else if (grad == 3 && ox) {
+ colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad + 1]);
+ } else {
+ for (int j = x; j < x + width; j++, ptr++) {
+ bool oy = ((j & 1) == 1);
+
+ if ((ox && oy) ||
+ ((grad == 2 || grad == 3) && ox && !oy) ||
+ (grad == 3 && oy))
+ *ptr = _gradCache[curGrad + 1];
+ else
+ *ptr = _gradCache[curGrad];
+ }
+ }
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+gradientFillClip(PixelType *ptr, int width, int x, int y, int realX, int realY) {
+ if (realY < _clippingArea.top || realY >= _clippingArea.bottom) return;
+ bool ox = ((y & 1) == 1);
+ int curGrad = 0;
+
+ while (_gradIndexes[curGrad + 1] <= y)
+ curGrad++;
+
+ // precalcGradient assures that _gradIndexes entries always differ in
+ // their value. This assures stripSize is always different from zero.
+ int stripSize = _gradIndexes[curGrad + 1] - _gradIndexes[curGrad];
int grad = (((y - _gradIndexes[curGrad]) % stripSize) << 2) / stripSize;
@@ -465,6 +670,7 @@ gradientFill(PixelType *ptr, int width, int x, int y) {
colorFill<PixelType>(ptr, ptr + width, _gradCache[curGrad + 1]);
} else {
for (int j = x; j < x + width; j++, ptr++) {
+ if (realX + j - x < _clippingArea.left || realX + j - x >= _clippingArea.right) continue;
bool oy = ((j & 1) == 1);
if ((ox && oy) ||
@@ -502,6 +708,44 @@ fillSurface() {
template<typename PixelType>
void VectorRendererSpec<PixelType>::
+fillSurfaceClip(Common::Rect clipping) {
+ int w = _activeSurface->w;
+ int h = _activeSurface->h;
+ if (clipping.isEmpty() || (clipping.left == 0 && clipping.top == 0 && clipping.right == w && clipping.bottom == h)) {
+ fillSurface();
+ return;
+ }
+
+ byte *ptr = (byte *)_activeSurface->getPixels();
+ int pitch = _activeSurface->pitch;
+
+ if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillForeground) {
+ PixelType color = (Base::_fillMode == kFillBackground ? _bgColor : _fgColor);
+ byte *ptrLeft = (ptr + _clippingArea.left), *ptrRight = ptr + _clippingArea.right;
+ for (int i = 0; i < h; i++) {
+ if (_clippingArea.top <= i && i < _clippingArea.bottom) {
+ colorFill<PixelType>((PixelType *)ptrLeft, (PixelType *)ptrRight, color);
+ }
+
+ ptrLeft += pitch;
+ ptrRight += pitch;
+ }
+
+ } else if (Base::_fillMode == kFillGradient) {
+ precalcGradient(h);
+
+ for (int i = 0; i < h; i++) {
+ if (_clippingArea.top <= i && i < _clippingArea.bottom) {
+ gradientFill((PixelType *)ptr + _clippingArea.left, _clippingArea.width(), 0, i);
+ }
+
+ ptr += pitch;
+ }
+ }
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
copyFrame(OSystem *sys, const Common::Rect &r) {
sys->copyRectToOverlay(
@@ -553,6 +797,58 @@ blitSubSurface(const Graphics::Surface *source, const Common::Rect &r) {
template<typename PixelType>
void VectorRendererSpec<PixelType>::
+blitSubSurfaceClip(const Graphics::Surface *source, const Common::Rect &r, const Common::Rect &clipping) {
+ if (clipping.isEmpty() || clipping.contains(r)) {
+ blitSubSurface(source, r);
+ return;
+ }
+
+ int16 x = r.left;
+ int16 y = r.top;
+
+ if (r.width() > source->w)
+ x = x + (r.width() >> 1) - (source->w >> 1);
+
+ if (r.height() > source->h)
+ y = y + (r.height() >> 1) - (source->h >> 1);
+
+ int w = source->w, h = source->h;
+ int usedW = w, usedH = h;
+ int offsetX = 0, offsetY = 0;
+
+ if (x > clipping.right || x + w < clipping.left) return;
+ if (y > clipping.bottom || y + h < clipping.top) return;
+ if (x < clipping.left) {
+ offsetX = clipping.left - x;
+ usedW -= offsetX;
+ x = clipping.left;
+ }
+ if (y < clipping.top) {
+ offsetY = clipping.top - y;
+ usedH -= offsetY;
+ y = clipping.top;
+ }
+ if (usedW > clipping.width()) usedW = clipping.width();
+ if (usedH > clipping.height()) usedH = clipping.height();
+
+ byte *dst_ptr = (byte *)_activeSurface->getBasePtr(x, y);
+ const byte *src_ptr = (const byte *)source->getBasePtr(offsetX, offsetY);
+
+ const int dst_pitch = _activeSurface->pitch;
+ const int src_pitch = source->pitch;
+
+ int lines = usedH;
+ const int sz = usedW * sizeof(PixelType);
+
+ while (lines--) {
+ memcpy(dst_ptr, src_ptr, sz);
+ dst_ptr += dst_pitch;
+ src_ptr += src_pitch;
+ }
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r) {
int16 x = r.left;
int16 y = r.top;
@@ -589,6 +885,65 @@ blitAlphaBitmap(const Graphics::Surface *source, const Common::Rect &r) {
template<typename PixelType>
void VectorRendererSpec<PixelType>::
+blitAlphaBitmapClip(const Graphics::Surface *source, const Common::Rect &r, const Common::Rect &clipping) {
+ if (clipping.isEmpty() || clipping.contains(r)) {
+ blitAlphaBitmap(source, r);
+ return;
+ }
+
+ int16 x = r.left;
+ int16 y = r.top;
+
+ if (r.width() > source->w)
+ x = x + (r.width() >> 1) - (source->w >> 1);
+
+ if (r.height() > source->h)
+ y = y + (r.height() >> 1) - (source->h >> 1);
+
+ int w = source->w, h = source->h;
+ int usedW = w, usedH = h;
+ int offsetX = 0, offsetY = 0;
+
+ if (x > clipping.right || x + w < clipping.left) return;
+ if (y > clipping.bottom || y + h < clipping.top) return;
+ if (x < clipping.left) {
+ offsetX = clipping.left - x;
+ usedW -= offsetX;
+ x = clipping.left;
+ }
+ if (y < clipping.top) {
+ offsetY = clipping.top - y;
+ usedH -= offsetY;
+ y = clipping.top;
+ }
+ if (usedW > clipping.width()) usedW = clipping.width();
+ if (usedH > clipping.height()) usedH = clipping.height();
+
+ PixelType *dst_ptr = (PixelType *)_activeSurface->getBasePtr(x, y);
+ const PixelType *src_ptr = (const PixelType *)source->getBasePtr(offsetX, offsetY);
+
+ int dst_pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+ int src_pitch = source->pitch / source->format.bytesPerPixel;
+
+ h = usedH;
+ while (h--) {
+ w = usedW;
+
+ while (w--) {
+ if (*src_ptr != _bitmapAlphaColor)
+ *dst_ptr = *src_ptr;
+
+ dst_ptr++;
+ src_ptr++;
+ }
+
+ dst_ptr = dst_ptr - usedW + dst_pitch;
+ src_ptr = src_ptr - usedW + src_pitch;
+ }
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
applyScreenShading(GUI::ThemeEngine::ShadingStyle shadingStyle) {
int pixels = _activeSurface->w * _activeSurface->h;
PixelType *ptr = (PixelType *)_activeSurface->getPixels();
@@ -666,6 +1021,13 @@ blendPixelPtr(PixelType *ptr, PixelType color, uint8 alpha) {
template<typename PixelType>
inline void VectorRendererSpec<PixelType>::
+blendPixelPtrClip(PixelType *ptr, PixelType color, uint8 alpha, int x, int y) {
+ if (IS_IN_CLIP(x, y))
+ blendPixelPtr(ptr, color, alpha);
+}
+
+template<typename PixelType>
+inline void VectorRendererSpec<PixelType>::
blendPixelDestAlphaPtr(PixelType *ptr, PixelType color, uint8 alpha) {
int idst = *ptr;
// This function is only used for corner pixels in rounded rectangles, so
@@ -709,6 +1071,36 @@ darkenFill(PixelType *ptr, PixelType *end) {
}
}
+template<typename PixelType>
+inline void VectorRendererSpec<PixelType>::
+darkenFillClip(PixelType *ptr, PixelType *end, int x, int y) {
+ PixelType mask = (PixelType)((3 << _format.rShift) | (3 << _format.gShift) | (3 << _format.bShift));
+
+ if (!g_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha)) {
+ // !kFeatureOverlaySupportsAlpha (but might have alpha bits)
+
+ while (ptr != end) {
+ if (IS_IN_CLIP(x, y)) *ptr = ((*ptr & ~mask) >> 2) | _alphaMask;
+ ++ptr;
+ ++x;
+ }
+ } else {
+ // kFeatureOverlaySupportsAlpha
+ // assuming at least 3 alpha bits
+
+ mask |= 3 << _format.aShift;
+ PixelType addA = (PixelType)(3 << (_format.aShift + 6 - _format.aLoss));
+
+ while (ptr != end) {
+ // Darken the color, and increase the alpha
+ // (0% -> 75%, 100% -> 100%)
+ if (IS_IN_CLIP(x, y)) *ptr = (PixelType)(((*ptr & ~mask) >> 2) + addA);
+ ++ptr;
+ ++x;
+ }
+ }
+}
+
/********************************************************************
********************************************************************
* Primitive shapes drawing - Public API calls - VectorRendererSpec *
@@ -773,8 +1165,8 @@ drawLine(int x1, int y1, int x2, int y2) {
SWAP(y1, y2);
}
- int dx = ABS(x2 - x1);
- int dy = ABS(y2 - y1);
+ uint dx = ABS(x2 - x1);
+ uint dy = ABS(y2 - y1);
// this is a point, not a line. stoopid.
if (dy == 0 && dx == 0)
@@ -803,7 +1195,7 @@ drawLine(int x1, int y1, int x2, int y2) {
ptr += pitch;
}
- } else if (ABS(dx) == ABS(dy)) { // diagonal lines
+ } else if (dx == dy) { // diagonal lines
// these ones also use a fixed pitch increase
pitch += (x2 > x1) ? 1 : -1;
@@ -817,6 +1209,77 @@ drawLine(int x1, int y1, int x2, int y2) {
}
}
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawLineClip(int x1, int y1, int x2, int y2, Common::Rect clipping) {
+ x1 = CLIP(x1, 0, (int)Base::_activeSurface->w);
+ x2 = CLIP(x2, 0, (int)Base::_activeSurface->w);
+ y1 = CLIP(y1, 0, (int)Base::_activeSurface->h);
+ y2 = CLIP(y2, 0, (int)Base::_activeSurface->h);
+
+ // we draw from top to bottom
+ if (y2 < y1) {
+ SWAP(x1, x2);
+ SWAP(y1, y2);
+ }
+
+ uint dx = ABS(x2 - x1);
+ uint dy = ABS(y2 - y1);
+
+ // this is a point, not a line. stoopid.
+ if (dy == 0 && dx == 0)
+ return;
+
+ if (Base::_strokeWidth == 0)
+ return;
+
+ PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+ int st = Base::_strokeWidth >> 1;
+
+ Common::Rect backup = _clippingArea;
+ _clippingArea = clipping;
+ bool needsClipping = !_clippingArea.isEmpty() && (!_clippingArea.contains(x1, y1) || !_clippingArea.contains(x2, y2));
+ if (!needsClipping) {
+ drawLine(x1, y1, x2, y2);
+ _clippingArea = backup;
+ return;
+ }
+
+ int ptr_x = x1, ptr_y = y1;
+
+ if (dy == 0) { // horizontal lines
+ colorFillClip<PixelType>(ptr, ptr + dx + 1, (PixelType)_fgColor, x1, y1, _clippingArea);
+
+ for (int i = 0, p = pitch; i < st; ++i, p += pitch) {
+ colorFillClip<PixelType>(ptr + p, ptr + dx + 1 + p, (PixelType)_fgColor, x1, y1 + p/pitch, _clippingArea);
+ colorFillClip<PixelType>(ptr - p, ptr + dx + 1 - p, (PixelType)_fgColor, x1, y1 - p/pitch, _clippingArea);
+ }
+
+ } else if (dx == 0) { // vertical lines
+ // these ones use a static pitch increase.
+ while (y1++ <= y2) {
+ colorFillClip<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor, x1 - st, ptr_y, _clippingArea);
+ ptr += pitch;
+ ++ptr_y;
+ }
+
+ } else if (dx == dy) { // diagonal lines
+ // these ones also use a fixed pitch increase
+ pitch += (x2 > x1) ? 1 : -1;
+
+ while (dy--) {
+ colorFillClip<PixelType>(ptr - st, ptr + st, (PixelType)_fgColor, ptr_x - st, ptr_y, _clippingArea);
+ ptr += pitch;
+ ++ptr_y;
+ if (x2 > x1) ++ptr_x; else --ptr_x;
+ }
+
+ } else { // generic lines, use the standard algorithm...
+ drawLineAlgClip(x1, y1, x2, y2, dx, dy, (PixelType)_fgColor);
+ }
+}
+
/** CIRCLES **/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
@@ -856,6 +1319,70 @@ drawCircle(int x, int y, int r) {
}
}
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawCircleClip(int x, int y, int r, Common::Rect clipping) {
+ if (x + r > Base::_activeSurface->w || y + r > Base::_activeSurface->h ||
+ x - r < 0 || y - r < 0 || x == 0 || y == 0 || r <= 0)
+ return;
+
+ Common::Rect backup = _clippingArea;
+ _clippingArea = clipping;
+ bool useClippingVersions = !(_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x - r, y - r, x + r, y + r)));
+
+ if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
+ && x + r + Base::_shadowOffset < Base::_activeSurface->w
+ && y + r + Base::_shadowOffset < Base::_activeSurface->h) {
+ if (useClippingVersions)
+ drawCircleAlgClip(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillForeground);
+ else
+ drawCircleAlg(x + Base::_shadowOffset + 1, y + Base::_shadowOffset + 1, r, 0, kFillForeground);
+ }
+
+ switch (Base::_fillMode) {
+ case kFillDisabled:
+ if (Base::_strokeWidth) {
+ if (useClippingVersions)
+ drawCircleAlgClip(x, y, r, _fgColor, kFillDisabled);
+ else
+ drawCircleAlg(x, y, r, _fgColor, kFillDisabled);
+ }
+ break;
+
+ case kFillForeground:
+ if (useClippingVersions)
+ drawCircleAlgClip(x, y, r, _fgColor, kFillForeground);
+ else
+ drawCircleAlg(x, y, r, _fgColor, kFillForeground);
+ break;
+
+ case kFillBackground:
+ if (Base::_strokeWidth > 1) {
+ if (useClippingVersions) {
+ drawCircleAlgClip(x, y, r, _fgColor, kFillForeground);
+ drawCircleAlgClip(x, y, r - Base::_strokeWidth, _bgColor, kFillBackground);
+ } else {
+ drawCircleAlg(x, y, r, _fgColor, kFillForeground);
+ drawCircleAlg(x, y, r - Base::_strokeWidth, _bgColor, kFillBackground);
+ }
+ } else {
+ if (useClippingVersions) {
+ drawCircleAlgClip(x, y, r, _bgColor, kFillBackground);
+ drawCircleAlgClip(x, y, r, _fgColor, kFillDisabled);
+ } else {
+ drawCircleAlg(x, y, r, _bgColor, kFillBackground);
+ drawCircleAlg(x, y, r, _fgColor, kFillDisabled);
+ }
+ }
+ break;
+
+ case kFillGradient:
+ break;
+ }
+
+ _clippingArea = backup;
+}
+
/** SQUARES **/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
@@ -893,6 +1420,67 @@ drawSquare(int x, int y, int w, int h) {
}
}
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawSquareClip(int x, int y, int w, int h, Common::Rect clipping) {
+ if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
+ w <= 0 || h <= 0 || x < 0 || y < 0)
+ return;
+
+ Common::Rect backup = _clippingArea;
+ _clippingArea = clipping;
+ bool useClippingVersions = !(_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h)));
+
+ if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
+ && x + w + Base::_shadowOffset < Base::_activeSurface->w
+ && y + h + Base::_shadowOffset < Base::_activeSurface->h) {
+ if (useClippingVersions)
+ drawSquareShadowClip(x, y, w, h, Base::_shadowOffset);
+ else
+ drawSquareShadow(x, y, w, h, Base::_shadowOffset);
+ }
+
+ switch (Base::_fillMode) {
+ case kFillDisabled:
+ if (Base::_strokeWidth) {
+ if (useClippingVersions)
+ drawSquareAlgClip(x, y, w, h, _fgColor, kFillDisabled);
+ else
+ drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
+ }
+ break;
+
+ case kFillForeground:
+ if (useClippingVersions)
+ drawSquareAlgClip(x, y, w, h, _fgColor, kFillForeground);
+ else
+ drawSquareAlg(x, y, w, h, _fgColor, kFillForeground);
+ break;
+
+ case kFillBackground:
+ if (useClippingVersions) {
+ drawSquareAlgClip(x, y, w, h, _bgColor, kFillBackground);
+ drawSquareAlgClip(x, y, w, h, _fgColor, kFillDisabled);
+ } else {
+ drawSquareAlg(x, y, w, h, _bgColor, kFillBackground);
+ drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
+ }
+ break;
+
+ case kFillGradient:
+ VectorRendererSpec::drawSquareAlg(x, y, w, h, 0, kFillGradient);
+ if (Base::_strokeWidth) {
+ if (useClippingVersions)
+ drawSquareAlgClip(x, y, w, h, _fgColor, kFillDisabled);
+ else
+ drawSquareAlg(x, y, w, h, _fgColor, kFillDisabled);
+ }
+ break;
+ }
+
+ _clippingArea = backup;
+}
+
/** ROUNDED SQUARES **/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
@@ -919,6 +1507,43 @@ drawRoundedSquare(int x, int y, int r, int w, int h) {
template<typename PixelType>
void VectorRendererSpec<PixelType>::
+drawRoundedSquareClip(int x, int y, int r, int w, int h, Common::Rect clipping) {
+ if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
+ w <= 0 || h <= 0 || x < 0 || y < 0 || r <= 0)
+ return;
+
+ if ((r * 2) > w || (r * 2) > h)
+ r = MIN(w / 2, h / 2);
+
+ if (r <= 0)
+ return;
+
+ Common::Rect backup = _clippingArea;
+ _clippingArea = clipping;
+ bool useOriginal = (_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h)));
+
+ if (Base::_fillMode != kFillDisabled && Base::_shadowOffset
+ && x + w + Base::_shadowOffset + 1 < Base::_activeSurface->w
+ && y + h + Base::_shadowOffset + 1 < Base::_activeSurface->h
+ && h > (Base::_shadowOffset + 1) * 2) {
+ if (useOriginal) {
+ drawRoundedSquareShadow(x, y, r, w, h, Base::_shadowOffset);
+ } else {
+ drawRoundedSquareShadowClip(x, y, r, w, h, Base::_shadowOffset);
+ }
+ }
+
+ if (useOriginal) {
+ drawRoundedSquareAlg(x, y, r, w, h, _fgColor, Base::_fillMode);
+ } else {
+ drawRoundedSquareAlgClip(x, y, r, w, h, _fgColor, Base::_fillMode);
+ }
+
+ _clippingArea = backup;
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
drawTab(int x, int y, int r, int w, int h) {
if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
w <= 0 || h <= 0 || x < 0 || y < 0 || r > w || r > h)
@@ -955,6 +1580,66 @@ drawTab(int x, int y, int r, int w, int h) {
template<typename PixelType>
void VectorRendererSpec<PixelType>::
+drawTabClip(int x, int y, int r, int w, int h, Common::Rect clipping) {
+ if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h ||
+ w <= 0 || h <= 0 || x < 0 || y < 0 || r > w || r > h)
+ return;
+
+ Common::Rect backup = _clippingArea;
+ _clippingArea = clipping;
+ bool useClippingVersions = !(_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h)));
+
+ if (r == 0 && Base::_bevel > 0) {
+ if (useClippingVersions)
+ drawBevelTabAlgClip(x, y, w, h, Base::_bevel, _bevelColor, _fgColor, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
+ else
+ drawBevelTabAlg(x, y, w, h, Base::_bevel, _bevelColor, _fgColor, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
+ _clippingArea = backup;
+ return;
+ }
+
+ if (r == 0) {
+ _clippingArea = backup;
+ return;
+ }
+
+ switch (Base::_fillMode) {
+ case kFillDisabled:
+ // FIXME: Implement this
+ _clippingArea = backup;
+ 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.)
+ if (useClippingVersions) {
+ drawTabShadowClip(x, y, w - 2, h, r);
+ drawTabAlgClip(x, y, w - 2, h, r, _bgColor, Base::_fillMode);
+ if (Base::_strokeWidth)
+ drawTabAlgClip(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
+ } else {
+ drawTabShadow(x, y, w - 2, h, r);
+ drawTabAlg(x, y, w - 2, h, r, _bgColor, Base::_fillMode);
+ if (Base::_strokeWidth)
+ drawTabAlg(x, y, w, h, r, _fgColor, kFillDisabled, (Base::_dynamicData >> 16), (Base::_dynamicData & 0xFFFF));
+ }
+ break;
+
+ case kFillForeground:
+ if (useClippingVersions)
+ drawTabAlgClip(x, y, w, h, r, _fgColor, Base::_fillMode);
+ else
+ drawTabAlg(x, y, w, h, r, _fgColor, Base::_fillMode);
+ break;
+ }
+
+ _clippingArea = backup;
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) {
if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h)
@@ -1021,8 +1706,88 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) {
}
}
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawTriangleClip(int x, int y, int w, int h, TriangleOrientation orient, Common::Rect clipping) {
+ if (x + w > Base::_activeSurface->w || y + h > Base::_activeSurface->h)
+ return;
+
+ PixelType color = 0;
+
+ if (Base::_strokeWidth <= 1) {
+ if (Base::_fillMode == kFillForeground)
+ color = _fgColor;
+ else if (Base::_fillMode == kFillBackground)
+ color = _bgColor;
+ } else {
+ if (Base::_fillMode == kFillDisabled)
+ return;
+ color = _fgColor;
+ }
+
+ if (Base::_dynamicData != 0)
+ orient = (TriangleOrientation)Base::_dynamicData;
+
+ Common::Rect backup = _clippingArea;
+ _clippingArea = clipping;
+ bool useClippingVersions = !(_clippingArea.isEmpty() || _clippingArea.contains(Common::Rect(x, y, x + w, y + h)));
+
+ if (w == h) {
+ int newW = w;
+
+ switch (orient) {
+ case kTriangleUp:
+ case kTriangleDown:
+ if (useClippingVersions)
+ drawTriangleVertAlgClip(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
+ else
+ drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
+ break;
+
+ case kTriangleLeft:
+ case kTriangleRight:
+ case kTriangleAuto:
+ break;
+ }
+
+ if (Base::_strokeWidth > 0)
+ if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) {
+ if (useClippingVersions)
+ drawTriangleVertAlgClip(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
+ else
+ drawTriangleVertAlg(x, y, newW, newW, (orient == kTriangleDown), color, Base::_fillMode);
+ }
+ } else {
+ int newW = w;
+ int newH = h;
+
+ switch (orient) {
+ case kTriangleUp:
+ case kTriangleDown:
+ if (useClippingVersions)
+ drawTriangleVertAlgClip(x, y, newW, newH, (orient == kTriangleDown), color, Base::_fillMode);
+ else
+ drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), color, Base::_fillMode);
+ break;
+ case kTriangleLeft:
+ case kTriangleRight:
+ case kTriangleAuto:
+ break;
+ }
+ if (Base::_strokeWidth > 0) {
+ if (Base::_fillMode == kFillBackground || Base::_fillMode == kFillGradient) {
+ if (useClippingVersions)
+ drawTriangleVertAlgClip(x, y, newW, newH, (orient == kTriangleDown), _fgColor, kFillDisabled);
+ else
+ drawTriangleVertAlg(x, y, newW, newH, (orient == kTriangleDown), _fgColor, kFillDisabled);
+ }
+ }
+ }
+
+ _clippingArea = backup;
+}
/********************************************************************
@@ -1034,6 +1799,11 @@ drawTriangle(int x, int y, int w, int h, TriangleOrientation orient) {
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) {
+ // Don't draw anything for empty rects.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
int f, ddF_x, ddF_y;
int x, y, px, py;
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
@@ -1128,6 +1898,120 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer:
}
}
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawTabAlgClip(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer::FillMode fill_m, int baseLeft, int baseRight) {
+ // Don't draw anything for empty rects.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
+ int f, ddF_x, ddF_y;
+ int x, y, px, py;
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+ int sw = 0, sp = 0, hp = 0;
+
+ 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 tl_x = x1 + r, tl_y = y1 + r;
+ int tr_x = x1 + w - r, tr_y = y1 + r;
+ int fill_x = x1, fill_y = y1;
+
+ int real_radius = r;
+ int short_h = h - r + 2;
+ int long_h = h;
+
+ if (fill_m == kFillDisabled) {
+ while (sw++ < Base::_strokeWidth) {
+ colorFillClip<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color, fill_x + r, fill_y + sp/pitch, _clippingArea);
+ colorFillClip<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color, fill_x + r, fill_y + hp / pitch - sp / pitch, _clippingArea);
+ sp += pitch;
+
+ BE_RESET();
+ r--;
+
+ while (x++ < y) {
+ BE_ALGORITHM();
+ BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
+
+ if (Base::_strokeWidth > 1)
+ BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px - pitch, py, tr_x, tr_y, tl_x, tl_y);
+ }
+ }
+
+ ptr_fill += pitch * real_radius;
+ fill_y += real_radius;
+ while (short_h--) {
+ colorFillClip<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color, fill_x, fill_y, _clippingArea);
+ colorFillClip<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color, fill_x + w - Base::_strokeWidth + 1, fill_y, _clippingArea);
+ ptr_fill += pitch;
+ ++fill_y;
+ }
+
+ if (baseLeft) {
+ sw = 0;
+ ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1 + h + 1);
+ fill_x = x1;
+ fill_y = y1 + h + 1;
+ while (sw++ < Base::_strokeWidth) {
+ colorFillClip<PixelType>(ptr_fill - baseLeft, ptr_fill, color, fill_x - baseLeft, fill_y, _clippingArea);
+ ptr_fill += pitch;
+ ++fill_y;
+ }
+ }
+
+ if (baseRight) {
+ sw = 0;
+ ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w, y1 + h + 1);
+ fill_x = x1 + w;
+ fill_y = y1 + h + 1;
+ while (sw++ < Base::_strokeWidth) {
+ colorFillClip<PixelType>(ptr_fill, ptr_fill + baseRight, color, fill_x, fill_y, _clippingArea);
+ ptr_fill += pitch;
+ ++fill_y;
+ }
+ }
+ } else {
+ BE_RESET();
+
+ precalcGradient(long_h);
+
+ PixelType color1, color2;
+ color1 = color2 = color;
+
+ while (x++ < y) {
+ BE_ALGORITHM();
+
+ if (fill_m == kFillGradient) {
+ color1 = calcGradient(real_radius - x, long_h);
+ color2 = calcGradient(real_radius - y, long_h);
+
+ gradientFillClip(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y, tl_x - x, tl_y - y);
+ gradientFillClip(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x, tl_x - y, tl_y - x);
+
+ BE_DRAWCIRCLE_XCOLOR_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
+ } else {
+ colorFillClip<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color, tl_x - x, tl_y - y, _clippingArea);
+ colorFillClip<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color, tl_x - y, tl_y - x, _clippingArea);
+
+ BE_DRAWCIRCLE_TOP_CLIP(ptr_tr, ptr_tl, x, y, px, py, tr_x, tr_y, tl_x, tl_y);
+ }
+ }
+
+ ptr_fill += pitch * r;
+ fill_y += r;
+ while (short_h--) {
+ if (fill_m == kFillGradient) {
+ gradientFillClip(ptr_fill, w + 1, x1, real_radius++, fill_x, fill_y);
+ } else {
+ colorFillClip<PixelType>(ptr_fill, ptr_fill + w + 1, color, fill_x, fill_y, _clippingArea);
+ }
+ ptr_fill += pitch;
+ ++fill_y;
+ }
+ }
+}
template<typename PixelType>
void VectorRendererSpec<PixelType>::
@@ -1190,6 +2074,72 @@ drawTabShadow(int x1, int y1, int w, int h, int r) {
}
}
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawTabShadowClip(int x1, int y1, int w, int h, int r) {
+ int offset = 3;
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+
+ // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
+ uint8 expFactor = 3;
+ uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8;
+
+ int xstart = x1;
+ int ystart = y1;
+ int width = w;
+ 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_fill = (PixelType *)Base::_activeSurface->getBasePtr(xstart, ystart);
+
+ int tl_x = xstart + r, tl_y = ystart + r;
+ int fill_x = xstart, fill_y = ystart;
+
+ int short_h = height - (2 * r) + 2;
+ PixelType color = _format.RGBToColor(0, 0, 0);
+
+ 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();
+
+ if (((1 << x) & hb) == 0) {
+ blendFillClip(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha, tl_x - y, tl_y - x);
+ hb |= (1 << x);
+ }
+
+ if (((1 << y) & hb) == 0) {
+ blendFillClip(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha, tl_x - x, tl_y - y);
+ hb |= (1 << y);
+ }
+ }
+
+ ptr_fill += pitch * r;
+ fill_y += r;
+ while (short_h--) {
+ blendFillClip(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha, fill_x, fill_y);
+ ptr_fill += pitch;
+ ++fill_y;
+ }
+
+ // Move shadow one pixel upward each iteration
+ xstart += 1;
+ // Multiply with expfactor
+ alpha = (alpha * (expFactor << 8)) >> 9;
+ }
+}
+
/** BEVELED TABS FOR CLASSIC THEME **/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
@@ -1234,10 +2184,66 @@ drawBevelTabAlg(int x, int y, int w, int h, int bevel, PixelType top_color, Pixe
}
}
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawBevelTabAlgClip(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, int baseLeft, int baseRight) {
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+ int i, j;
+
+ PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
+ int ptr_x = x, ptr_y = y;
+
+ i = bevel;
+ while (i--) {
+ colorFillClip<PixelType>(ptr_left, ptr_left + w, top_color, ptr_x, ptr_y, _clippingArea);
+ ptr_left += pitch;
+ ++ptr_y;
+ }
+
+ if (baseLeft > 0) {
+ i = h - bevel;
+ ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
+ ptr_x = x; ptr_y = y;
+ while (i--) {
+ colorFillClip<PixelType>(ptr_left, ptr_left + bevel, top_color, ptr_x, ptr_y, _clippingArea);
+ ptr_left += pitch;
+ ++ptr_y;
+ }
+ }
+
+ i = h - bevel;
+ j = bevel - 1;
+ ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y);
+ ptr_x = x + w - bevel; ptr_y = y;
+ while (i--) {
+ colorFillClip<PixelType>(ptr_left + j, ptr_left + bevel, bottom_color, ptr_x + j, ptr_y, _clippingArea);
+ if (j > 0) j--;
+ ptr_left += pitch;
+ ++ptr_y;
+ }
+
+ i = bevel;
+ ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y + h - bevel);
+ ptr_x = x + w - bevel; ptr_y = y + h - bevel;
+ while (i--) {
+ colorFillClip<PixelType>(ptr_left, ptr_left + baseRight + bevel, bottom_color, ptr_x, ptr_y, _clippingArea);
+
+ if (baseLeft)
+ colorFillClip<PixelType>(ptr_left - w - baseLeft + bevel, ptr_left - w + bevel + bevel, top_color, ptr_x - w - baseLeft + bevel, ptr_y, _clippingArea);
+ ptr_left += pitch;
+ ++ptr_y;
+ }
+}
+
/** SQUARE ALGORITHM **/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawSquareAlg(int x, int y, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+ // Do not draw anything for empty rects.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y);
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int max_h = h;
@@ -1267,6 +2273,46 @@ drawSquareAlg(int x, int y, int w, int h, PixelType color, VectorRenderer::FillM
}
}
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawSquareAlgClip(int x, int y, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+ // Do not draw anything for empty rects.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
+ PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x, y);
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+ int max_h = h;
+ int ptr_y = y;
+
+ if (fill_m != kFillDisabled) {
+ while (h--) {
+ if (fill_m == kFillGradient)
+ color = calcGradient(max_h - h, max_h);
+
+ colorFillClip<PixelType>(ptr, ptr + w, color, x, ptr_y, _clippingArea);
+ ptr += pitch;
+ ++ptr_y;
+ }
+ } else {
+ int sw = Base::_strokeWidth, sp = 0, hp = pitch * (h - 1);
+
+ while (sw--) {
+ colorFillClip<PixelType>(ptr + sp, ptr + w + sp, color, x, ptr_y + sp/pitch, _clippingArea);
+ colorFillClip<PixelType>(ptr + hp - sp, ptr + w + hp - sp, color, x, ptr_y + h - sp/pitch, _clippingArea);
+ sp += pitch;
+ }
+
+ while (h--) {
+ colorFillClip<PixelType>(ptr, ptr + Base::_strokeWidth, color, x, ptr_y, _clippingArea);
+ colorFillClip<PixelType>(ptr + w - Base::_strokeWidth, ptr + w, color, x + w - Base::_strokeWidth, ptr_y, _clippingArea);
+ ptr += pitch;
+ ptr_y += 1;
+ }
+ }
+}
+
/** SQUARE ALGORITHM **/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
@@ -1323,10 +2369,76 @@ drawBevelSquareAlg(int x, int y, int w, int h, int bevel, PixelType top_color, P
}
}
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawBevelSquareAlgClip(int x, int y, int w, int h, int bevel, PixelType top_color, PixelType bottom_color, bool fill) {
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+ int i, j;
+ PixelType *ptr_left;
+ int ptr_x, ptr_y;
+
+ // Fill Background
+ ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
+ ptr_x = x; ptr_y = y;
+ i = h;
+ if (fill) {
+ assert((_bgColor & ~_alphaMask) == 0); // only support black
+ while (i--) {
+ darkenFillClip(ptr_left, ptr_left + w, ptr_x, ptr_y);
+ ptr_left += pitch;
+ ++ptr_y;
+ }
+ }
+
+ x = MAX(x - bevel, 0);
+ y = MAX(y - bevel, 0);
+
+ w = MIN(w + (bevel * 2), (int)_activeSurface->w);
+ h = MIN(h + (bevel * 2), (int)_activeSurface->h);
+
+ ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y);
+ ptr_x = x; ptr_y = y;
+ i = bevel;
+ while (i--) {
+ colorFillClip<PixelType>(ptr_left, ptr_left + w, top_color, ptr_x, ptr_y, _clippingArea);
+ ptr_left += pitch;
+ ++ptr_y;
+ }
+
+ ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + bevel);
+ ptr_x = x; ptr_y = y + bevel;
+ i = h - bevel;
+ while (i--) {
+ colorFillClip<PixelType>(ptr_left, ptr_left + bevel, top_color, ptr_x, ptr_y, _clippingArea);
+ ptr_left += pitch;
+ ++ptr_y;
+ }
+
+ ptr_left = (PixelType *)_activeSurface->getBasePtr(x, y + h - bevel);
+ ptr_x = x; ptr_y = y + h - bevel;
+ i = bevel;
+ while (i--) {
+ colorFillClip<PixelType>(ptr_left + i, ptr_left + w, bottom_color, ptr_x + i, ptr_y, _clippingArea);
+ ptr_left += pitch;
+ ++ptr_y;
+ }
+
+ ptr_left = (PixelType *)_activeSurface->getBasePtr(x + w - bevel, y);
+ ptr_x = x + w - bevel; ptr_y = y;
+ i = h - bevel;
+ j = bevel - 1;
+ while (i--) {
+ colorFillClip<PixelType>(ptr_left + j, ptr_left + bevel, bottom_color, ptr_x + j, ptr_y, _clippingArea);
+ if (j > 0) j--;
+ ptr_left += pitch;
+ ++ptr_y;
+ }
+}
+
/** GENERIC LINE ALGORITHM **/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
-drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
+drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int xdir = (x2 > x1) ? 1 : -1;
@@ -1371,6 +2483,59 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
*ptr = (PixelType)color;
}
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawLineAlgClip(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
+ PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x1, y1);
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+ int xdir = (x2 > x1) ? 1 : -1;
+ int ptr_x = x1, ptr_y = y1;
+
+ if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
+
+ if (dx > dy) {
+ int ddy = dy * 2;
+ int dysub = ddy - (dx * 2);
+ int error_term = ddy - dx;
+
+ while (dx--) {
+ if (error_term >= 0) {
+ ptr += pitch;
+ ++ptr_y;
+ error_term += dysub;
+ } else {
+ error_term += ddy;
+ }
+
+ ptr += xdir;
+ ptr_x += xdir;
+ if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
+ }
+ } else {
+ int ddx = dx * 2;
+ int dxsub = ddx - (dy * 2);
+ int error_term = ddx - dy;
+
+ while (dy--) {
+ if (error_term >= 0) {
+ ptr += xdir;
+ ptr_x += xdir;
+ error_term += dxsub;
+ } else {
+ error_term += ddx;
+ }
+
+ ptr += pitch;
+ ++ptr_y;
+ if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
+ }
+ }
+
+ ptr = (PixelType *)_activeSurface->getBasePtr(x2, y2);
+ ptr_x = x2; ptr_y = y2;
+ if (IS_IN_CLIP(ptr_x, ptr_y)) *ptr = (PixelType)color;
+}
+
/** VERTICAL TRIANGLE DRAWING ALGORITHM **/
/**
FIXED POINT ARITHMETIC
@@ -1393,6 +2558,12 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) {
+ // Don't draw anything for empty rects. This assures dy is always different
+ // from zero.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int gradient_h = 0;
if (!inverted) {
@@ -1422,6 +2593,9 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
blendPixelPtr(floor, color, 50);
#if FIXED_POINT
+ // In this branch dx is always different from zero. This is because
+ // abs(dx) is strictly greater than abs(dy), and abs returns zero
+ // as minimal value.
int gradient = (dy << 8) / dx;
int intery = (y1 << 8) + gradient;
#else
@@ -1560,10 +2734,221 @@ drawTriangleVertAlg(int x1, int y1, int w, int h, bool inverted, PixelType color
}
+/////////////
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawTriangleVertAlgClip(int x1, int y1, int w, int h, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) {
+ // Don't draw anything for empty rects. This assures dy is always different
+ // from zero.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+ int gradient_h = 0;
+ int y_pitch_sign = 1;
+ if (!inverted) {
+ pitch = -pitch;
+ y1 += h;
+ y_pitch_sign = -1;
+ }
+
+ PixelType *ptr_right = (PixelType *)_activeSurface->getBasePtr(x1, y1);
+ PixelType *floor = ptr_right - 1;
+ PixelType *ptr_left = (PixelType *)_activeSurface->getBasePtr(x1 + w, y1);
+
+ int x2 = x1 + w / 2;
+ int y2 = y1 + h;
+ int x_right = x1;
+ int y_right = y1;
+ int x_left = x1 + w;
+ int y_left = y1;
+ int x_floor = x_right - 1;
+ int y_floor = y_right;
+
+#if FIXED_POINT
+ int dx = (x2 - x1) << 8;
+ int dy = (y2 - y1) << 8;
+
+ if (abs(dx) > abs(dy)) {
+#else
+ double dx = (double)x2 - (double)x1;
+ double dy = (double)y2 - (double)y1;
+
+ if (fabs(dx) > fabs(dy)) {
+#endif
+ while (floor++ != ptr_left)
+ blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
+
+#if FIXED_POINT
+ // In this branch dx is always different from zero. This is because
+ // abs(dx) is strictly greater than abs(dy), and abs returns zero
+ // as minimal value.
+ int gradient = (dy << 8) / dx;
+ int intery = (y1 << 8) + gradient;
+#else
+ double gradient = dy / dx;
+ double intery = y1 + gradient;
+#endif
+
+ for (int x = x1 + 1; x < x2; x++) {
+#if FIXED_POINT
+ if (intery + gradient > ipart(intery) + 0x100) {
+#else
+ if (intery + gradient > ipart(intery) + 1) {
+#endif
+ ptr_right++;
+ ptr_left--;
+ ++x_right;
+ --x_left;
+ }
+
+ ptr_left += pitch;
+ ptr_right += pitch;
+ y_right += y_pitch_sign;
+ y_left += y_pitch_sign;
+
+ intery += gradient;
+
+ switch (fill_m) {
+ case kFillDisabled:
+ if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
+ if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
+ break;
+ case kFillForeground:
+ case kFillBackground:
+ colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right+1, y_right, _clippingArea);
+ blendPixelPtrClip(ptr_right, color, rfpart(intery), x_right, y_right);
+ blendPixelPtrClip(ptr_left, color, rfpart(intery), x_left, y_left);
+ break;
+ case kFillGradient:
+ colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
+ blendPixelPtrClip(ptr_right, color, rfpart(intery), x_right, y_right);
+ blendPixelPtrClip(ptr_left, color, rfpart(intery), x_left, y_left);
+ break;
+ }
+ }
+
+ return;
+ }
+
+#if FIXED_POINT
+ if (abs(dx) < abs(dy)) {
+#else
+ if (fabs(dx) < fabs(dy)) {
+#endif
+ ptr_left--;
+ --x_left;
+ while (floor++ != ptr_left)
+ blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
+
+#if FIXED_POINT
+ int gradient = (dx << 8) / (dy + 0x100);
+ int interx = (x1 << 8) + gradient;
+#else
+ double gradient = dx / (dy + 1);
+ double interx = x1 + gradient;
+#endif
+
+ for (int y = y1 + 1; y < y2; y++) {
+#if FIXED_POINT
+ if (interx + gradient > ipart(interx) + 0x100) {
+#else
+ if (interx + gradient > ipart(interx) + 1) {
+#endif
+ ptr_right++;
+ ptr_left--;
+ ++x_right;
+ --x_left;
+ }
+
+ ptr_left += pitch;
+ ptr_right += pitch;
+ y_right += y_pitch_sign;
+ y_left += y_pitch_sign;
+
+ interx += gradient;
+
+ switch (fill_m) {
+ case kFillDisabled:
+ if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
+ if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
+ break;
+ case kFillForeground:
+ case kFillBackground:
+ colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right+1, y_right, _clippingArea);
+ blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
+ blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
+ break;
+ case kFillGradient:
+ colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
+ blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
+ blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
+ break;
+ }
+ }
+
+ return;
+ }
+
+ ptr_left--;
+ --x_left;
+ while (floor++ != ptr_left)
+ blendPixelPtrClip(floor, color, 50, ++x_floor, y_floor);
+
+#if FIXED_POINT
+ int gradient = (dx / dy) << 8;
+ int interx = (x1 << 8) + gradient;
+#else
+ double gradient = dx / dy;
+ double interx = x1 + gradient;
+#endif
+
+ for (int y = y1 + 1; y < y2; y++) {
+ ptr_right++;
+ ptr_left--;
+ ++x_right;
+ --x_left;
+
+ ptr_left += pitch;
+ ptr_right += pitch;
+ y_right += y_pitch_sign;
+ y_left += y_pitch_sign;
+
+ interx += gradient;
+
+ switch (fill_m) {
+ case kFillDisabled:
+ if (IS_IN_CLIP(x_left, y_left)) *ptr_left = color;
+ if (IS_IN_CLIP(x_right, y_right)) *ptr_right = color;
+ break;
+ case kFillForeground:
+ case kFillBackground:
+ colorFillClip<PixelType>(ptr_right + 1, ptr_left, color, x_right+1, y_right, _clippingArea);
+ blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
+ blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
+ break;
+ case kFillGradient:
+ colorFillClip<PixelType>(ptr_right, ptr_left, calcGradient(gradient_h++, h), x_right, y_right, _clippingArea);
+ blendPixelPtrClip(ptr_right, color, rfpart(interx), x_right, y_right);
+ blendPixelPtrClip(ptr_left, color, rfpart(interx), x_left, y_left);
+ break;
+ }
+ }
+}
+
+/////////////
+
/** VERTICAL TRIANGLE DRAWING - FAST VERSION FOR SQUARED TRIANGLES */
template<typename PixelType>
void VectorRendererSpec<PixelType>::
drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, VectorRenderer::FillMode fill_m) {
+ // Do not draw anything for empty rects.
+ if (size <= 0) {
+ return;
+ }
+
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
if (!inverted) {
@@ -1657,6 +3042,9 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
while (x++ < (y - 2)) {
BE_ALGORITHM();
+ if (x < _clippingArea.left || x > _clippingArea.right) continue;
+ if (y < _clippingArea.top || y > _clippingArea.bottom) continue;
+
BE_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, x, y, px, py, (uint8)(alpha_r + (alphaStep_tr * x)));
BE_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, x, y, px, py, (uint8)(alpha_b + (alphaStep_br * x)));
BE_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, x, y, px, py, (uint8)(alpha_l + (alphaStep_bl * x)));
@@ -1684,7 +3072,80 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
template<typename PixelType>
void VectorRendererSpec<PixelType>::
+drawBorderRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m, uint8 alpha_t, uint8 alpha_r, uint8 alpha_b, uint8 alpha_l) {
+ int f, ddF_x, ddF_y;
+ int x, y, px, py;
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+ int sw = 0, sp = 0, hp = h * pitch;
+
+ 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_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, y1);
+
+ int real_radius = r;
+ int short_h = h - (2 * r) + 2;
+
+ PixelType color1 = color;
+ PixelType color2 = color;
+
+ while (sw++ < Base::_strokeWidth) {
+ blendFillClip(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1, alpha_t,
+ x1 + r, y1 + sp/pitch); // top
+ blendFillClip(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2, alpha_b,
+ x1 + r, y1 + (hp - sp)/ pitch); // bottom
+ sp += pitch;
+
+ BE_RESET();
+ r--;
+
+ int alphaStep_tr = ((alpha_t - alpha_r) / (y + 1));
+ int alphaStep_br = ((alpha_r - alpha_b) / (y + 1));
+ int alphaStep_bl = ((alpha_b - alpha_l) / (y + 1));
+ int alphaStep_tl = ((alpha_l - alpha_t) / (y + 1));
+
+ // Avoid blending the last pixels twice, since we have an alpha
+ while (x++ < (y - 2)) {
+ BE_ALGORITHM();
+
+ BE_DRAWCIRCLE_BCOLOR_TR_CW_CLIP(ptr_tr, x, y, px, py, (uint8)(alpha_r + (alphaStep_tr * x)), x1 + w - r, y1 + r);
+ BE_DRAWCIRCLE_BCOLOR_BR_CW_CLIP(ptr_br, x, y, px, py, (uint8)(alpha_b + (alphaStep_br * x)), x1 + w - r, y1 + h - r);
+ BE_DRAWCIRCLE_BCOLOR_BL_CW_CLIP(ptr_bl, x, y, px, py, (uint8)(alpha_l + (alphaStep_bl * x)), x1 + r, y1 + h - r);
+ BE_DRAWCIRCLE_BCOLOR_TL_CW_CLIP(ptr_tl, x, y, px, py, (uint8)(alpha_t + (alphaStep_tl * x)), x1 + r, y1 + r);
+
+ BE_DRAWCIRCLE_BCOLOR_TR_CCW_CLIP(ptr_tr, x, y, px, py, (uint8)(alpha_t - (alphaStep_tr * x)), x1 + w - r, y1 + r);
+ BE_DRAWCIRCLE_BCOLOR_BR_CCW_CLIP(ptr_br, x, y, px, py, (uint8)(alpha_r - (alphaStep_br * x)), x1 + w - r, y1 + h - r);
+ BE_DRAWCIRCLE_BCOLOR_BL_CCW_CLIP(ptr_bl, x, y, px, py, (uint8)(alpha_b - (alphaStep_bl * x)), x1 + r, y1 + h - r);
+ BE_DRAWCIRCLE_BCOLOR_TL_CCW_CLIP(ptr_tl, x, y, px, py, (uint8)(alpha_l - (alphaStep_tl * x)), x1 + r, y1 + r);
+
+ if (Base::_strokeWidth > 1) {
+ BE_DRAWCIRCLE_BCOLOR_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py,
+ x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
+ BE_DRAWCIRCLE_BCOLOR_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py,
+ x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
+ }
+ }
+ }
+
+ ptr_fill += pitch * real_radius;
+ while (short_h--) {
+ blendFillClip(ptr_fill, ptr_fill + Base::_strokeWidth, color1, alpha_l,
+ x1, y1 + real_radius + h - (2 * r) + 2 - short_h - 1); // left
+ blendFillClip(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2, alpha_r,
+ x1 + w - Base::_strokeWidth + 1, y1 + real_radius + h - (2 * r) + 2 - short_h - 1); // right
+ ptr_fill += pitch;
+ }
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+ // Do not draw empty space rounded squares.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
int f, ddF_x, ddF_y;
int x, y, px, py;
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
@@ -1710,6 +3171,8 @@ drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType colo
while (x++ < y) {
BE_ALGORITHM();
+ if (y1 + r + y < _clippingArea.top || y1 + r + y > _clippingArea.bottom) continue;
+
color1 = calcGradient(real_radius - x, long_h);
color2 = calcGradient(real_radius - y, long_h);
color3 = calcGradient(long_h - r + x, long_h);
@@ -1751,6 +3214,91 @@ drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType colo
template<typename PixelType>
void VectorRendererSpec<PixelType>::
+drawInteriorRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+ // Do not draw empty space rounded squares.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
+ int f, ddF_x, ddF_y;
+ int x, y, px, py;
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+
+ 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_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, y1);
+
+ int real_radius = r;
+ int short_h = h - (2 * r) + 2;
+ int long_h = h;
+
+ BE_RESET();
+
+ PixelType color1 = color;
+
+ if (fill_m == kFillGradient) {
+ PixelType color2, color3, color4;
+ precalcGradient(long_h);
+
+ while (x++ < y) {
+ BE_ALGORITHM();
+
+ color1 = calcGradient(real_radius - x, long_h);
+ color2 = calcGradient(real_radius - y, long_h);
+ color3 = calcGradient(long_h - r + x, long_h);
+ color4 = calcGradient(long_h - r + y, long_h);
+
+ //TL = (x1 + r, y1 + r)
+ gradientFillClip(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y,
+ x1 + r - x, y1 + r - y);
+ gradientFillClip(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x,
+ x1 + r - y, y1 + r - x);
+
+ //BL = (x1 + r, y1 + h - r)
+ gradientFillClip(ptr_bl - x + py, w - 2 * r + 2 * x, x1 + r - x - y, long_h - r + y,
+ x1 + r - x, y1 + h - r + y);
+ gradientFillClip(ptr_bl - y + px, w - 2 * r + 2 * y, x1 + r - y - x, long_h - r + x,
+ x1 + r - y, y1 + h - r + x);
+
+ BE_DRAWCIRCLE_XCOLOR_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py,
+ x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
+ }
+ } else {
+ while (x++ < y) {
+ BE_ALGORITHM();
+
+ colorFillClip<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color1,
+ x1 + r - x, y1 + r - y, _clippingArea);
+ colorFillClip<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color1,
+ x1 + r - y, y1 + r - x, _clippingArea);
+
+ colorFillClip<PixelType>(ptr_bl - x + py, ptr_br + x + py, color1,
+ x1 + r - x, y1 + h - r + y, _clippingArea);
+ colorFillClip<PixelType>(ptr_bl - y + px, ptr_br + y + px, color1,
+ x1 + r - y, y1 + h - r + x, _clippingArea);
+
+ // do not remove - messes up the drawing at lower resolutions
+ BE_DRAWCIRCLE_CLIP(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py,
+ x1 + w - r, y1 + r, x1 + r, y1 + r, x1 + r, y1 + h - r, x1 + w - r, y1 + h - r);
+ }
+ }
+
+ ptr_fill += pitch * r;
+ int short_h_orig = short_h;
+ while (short_h--) {
+ if (fill_m == kFillGradient) {
+ gradientFillClip(ptr_fill, w + 1, x1, real_radius++, x1, y1 + r + short_h_orig - short_h -1);
+ } else {
+ colorFillClip<PixelType>(ptr_fill, ptr_fill + w + 1, color1, x1, y1 + r + short_h_orig - short_h - 1, _clippingArea);
+ }
+ ptr_fill += pitch;
+ }
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
const uint8 borderAlpha_t = 0;
const uint8 borderAlpha_r = 127;
@@ -1780,6 +3328,38 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto
}
}
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawRoundedSquareAlgClip(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+ const uint8 borderAlpha_t = 0;
+ const uint8 borderAlpha_r = 127;
+ const uint8 borderAlpha_b = 255;
+ const uint8 borderAlpha_l = 63;
+
+ const uint8 bevelAlpha_t = 255;
+ const uint8 bevelAlpha_r = 31;
+ const uint8 bevelAlpha_b = 0;
+ const uint8 bevelAlpha_l = 127;
+
+ // If only border is visible
+ if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) {
+ if (fill_m == Base::kFillBackground)
+ drawInteriorRoundedSquareAlgClip(x1, y1, r, w, h, _bgColor, fill_m);
+ else
+ drawInteriorRoundedSquareAlgClip(x1, y1, r, w, h, color, fill_m);
+ }
+
+ //I expect these to work fine with clipping:
+ if (Base::_strokeWidth) {
+ if (r != 0 && _bevel > 0) {
+ drawBorderRoundedSquareAlgClip(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l);
+ drawBorderRoundedSquareAlgClip(x1, y1, r, w, h, _bevelColor, fill_m, bevelAlpha_t, bevelAlpha_r, bevelAlpha_b, bevelAlpha_l);
+ } else {
+ drawBorderRoundedSquareAlgClip(x1, y1, r, w, h, color, fill_m, 255, 255, 255, 255);
+ }
+ }
+}
+
/** CIRCLE ALGORITHM **/
template<typename PixelType>
void VectorRendererSpec<PixelType>::
@@ -1824,7 +3404,47 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode f
}
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawCircleAlgClip(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode fill_m) {
+ int f, ddF_x, ddF_y;
+ int x, y, px, py, sw = 0;
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+ PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
+
+ if (fill_m == kFillDisabled) {
+ while (sw++ < Base::_strokeWidth) {
+ BE_RESET();
+ r--;
+
+ if (IS_IN_CLIP(x1 + y, y1)) *(ptr + y) = color;
+ if (IS_IN_CLIP(x1 - y, y1)) *(ptr - y) = color;
+ if (IS_IN_CLIP(x1, y1 + y)) *(ptr + py) = color;
+ if (IS_IN_CLIP(x1, y1 - y)) *(ptr - py) = color;
+
+ while (x++ < y) {
+ BE_ALGORITHM();
+ BE_DRAWCIRCLE_CLIP(ptr, ptr, ptr, ptr, x, y, px, py, x1, y1, x1, y1, x1, y1, x1, y1);
+
+ if (Base::_strokeWidth > 1) {
+ BE_DRAWCIRCLE_CLIP(ptr, ptr, ptr, ptr, x - 1, y, px, py, x1, y1, x1, y1, x1, y1, x1, y1);
+ BE_DRAWCIRCLE_CLIP(ptr, ptr, ptr, ptr, x, y, px - pitch, py, x1, y1, x1, y1, x1, y1, x1, y1);
+ }
+ }
+ }
+ } else {
+ colorFillClip<PixelType>(ptr - r, ptr + r, color, x1 - r, y1 + r, _clippingArea);
+ BE_RESET();
+ while (x++ < y) {
+ BE_ALGORITHM();
+ colorFillClip<PixelType>(ptr - x + py, ptr + x + py, color, x1 - x, y1 + y, _clippingArea);
+ colorFillClip<PixelType>(ptr - x - py, ptr + x - py, color, x1 - x, y1 - y, _clippingArea);
+ colorFillClip<PixelType>(ptr - y + px, ptr + y + px, color, x1 - y, y1 + x, _clippingArea);
+ colorFillClip<PixelType>(ptr - y - px, ptr + y - px, color, x1 - y, y1 - x, _clippingArea);
+ }
+ }
+}
/********************************************************************
@@ -1835,6 +3455,11 @@ 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 offset) {
+ // Do nothing for empty rects or no shadow offset.
+ if (w <= 0 || h <= 0 || offset <= 0) {
+ return;
+ }
+
PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + offset);
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
int i, j;
@@ -1870,6 +3495,54 @@ drawSquareShadow(int x, int y, int w, int h, int offset) {
template<typename PixelType>
void VectorRendererSpec<PixelType>::
+drawSquareShadowClip(int x, int y, int w, int h, int offset) {
+ // Do nothing for empty rects or no shadow offset.
+ if (w <= 0 || h <= 0 || offset <= 0) {
+ return;
+ }
+
+ PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + offset);
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+ int i, j, ptr_x = x+w-1, ptr_y = y+offset;
+
+ i = h - offset;
+
+ while (i--) {
+ j = offset;
+ while (j--)
+ blendPixelPtrClip(ptr + j, 0, ((offset - j) << 8) / offset, ptr_x + j, ptr_y);
+ ptr += pitch;
+ ++ptr_y;
+ }
+
+ ptr = (PixelType *)_activeSurface->getBasePtr(x + offset, y + h - 1);
+ ptr_x = x + offset;
+ ptr_y = y + h - 1;
+
+ while (i++ < offset) {
+ j = w - offset;
+ while (j--)
+ blendPixelPtrClip(ptr + j, 0, ((offset - i) << 8) / offset, ptr_x + j, ptr_y);
+ ptr += pitch;
+ ++ptr_y;
+ }
+
+ ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h);
+ ptr_x = x + w;
+ ptr_y = y + h;
+
+ i = 0;
+ while (i++ < offset) {
+ j = offset - 1;
+ while (j--)
+ blendPixelPtrClip(ptr + j, 0, (((offset - j) * (offset - i)) << 8) / (offset * offset), ptr_x + j, ptr_y);
+ ptr += pitch;
+ ++ptr_y;
+ }
+}
+
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
@@ -1907,7 +3580,6 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
while (x++ < y) {
BE_ALGORITHM();
-
if (((1 << x) & hb) == 0) {
blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha);
@@ -1943,6 +3615,83 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
}
}
+template<typename PixelType>
+void VectorRendererSpec<PixelType>::
+drawRoundedSquareShadowClip(int x1, int y1, int r, int w, int h, int offset) {
+ int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel;
+
+ // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme)
+ uint8 expFactor = 3;
+ uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 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);
+
+ 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();
+
+ if (((1 << x) & hb) == 0) {
+ blendFillClip(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha,
+ xstart + r - y, ystart + r - x);
+
+ // Will create a dark line of pixles if left out
+ if (hb > 0) {
+ blendFillClip(ptr_bl - y + px, ptr_br + y + px, color, (uint8)alpha,
+ xstart + r - y, ystart + height - r + x);
+ }
+ hb |= (1 << x);
+ }
+
+ if (((1 << y) & hb) == 0) {
+ blendFillClip(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha, xstart + r - x, ystart + r - y);
+ blendFillClip(ptr_bl - x + py, ptr_br + x + py, color, (uint8)alpha, xstart + r - x, ystart + height - r + y);
+ hb |= (1 << y);
+ }
+ }
+
+ ptr_fill += pitch * r;
+ int orig_short_h = short_h;
+ while (short_h--) {
+ blendFillClip(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha,
+ xstart, ystart + r + orig_short_h - short_h - 1);
+ 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 << 8)) >> 9;
+ }
+}
/******************************************************************************/
@@ -1956,8 +3705,7 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) {
/** LINES **/
template<typename PixelType>
void VectorRendererAA<PixelType>::
-drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
-
+drawLineAlg(int x1, int y1, int x2, int y2, uint dx, uint dy, PixelType color) {
PixelType *ptr = (PixelType *)Base::_activeSurface->getBasePtr(x1, y1);
int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
int xdir = (x2 > x1) ? 1 : -1;
@@ -1967,7 +3715,7 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
*ptr = (PixelType)color;
if (dx > dy) {
- gradient = (uint32)(dy << 16) / (uint32)dx;
+ gradient = (dy << 16) / dx;
error_acc = 0;
while (--dx) {
@@ -1983,8 +3731,8 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
this->blendPixelPtr(ptr, color, ~alpha);
this->blendPixelPtr(ptr + pitch, color, alpha);
}
- } else {
- gradient = (uint32)(dx << 16) / (uint32)dy;
+ } else if (dy != 0) {
+ gradient = (dx << 16) / dy;
error_acc = 0;
while (--dy) {
@@ -2009,6 +3757,11 @@ drawLineAlg(int x1, int y1, int x2, int y2, int dx, int dy, PixelType color) {
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) {
+ // Don't draw anything for empty rects.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
int x, y, px, py;
int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
int sw = 0, sp = 0, hp = 0;
@@ -2217,6 +3970,14 @@ drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color,
template<typename PixelType>
void VectorRendererAA<PixelType>::
drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) {
+ w -= 2*Base::_strokeWidth;
+ h -= 2*Base::_strokeWidth;
+
+ // Do not draw empty space rounded squares.
+ if (w <= 0 || h <= 0) {
+ return;
+ }
+
int x, y;
const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel;
int px, py;
@@ -2228,8 +3989,6 @@ drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType colo
r -= Base::_strokeWidth;
x1 += Base::_strokeWidth;
y1 += Base::_strokeWidth;
- w -= 2*Base::_strokeWidth;
- h -= 2*Base::_strokeWidth;
rsq = r*r;
PixelType *ptr_tl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + r);