From 887a99e211c25fd16e4cf3b7505ae17678c2f997 Mon Sep 17 00:00:00 2001 From: Narek Mailian Date: Thu, 13 Jun 2013 12:32:36 +0000 Subject: GRAPHICS: Added changes and improved code from inisider/scummvm (partial text) Includes code from https://github.com/inisider/scummvm/ , which has been squashed and bugfixed --- graphics/VectorRendererSpec.cpp | 86 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 76 insertions(+), 10 deletions(-) (limited to 'graphics/VectorRendererSpec.cpp') diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index e4843ba78b..f9041fc8ff 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -646,24 +646,90 @@ darkenFill(PixelType *ptr, PixelType *end) { template void VectorRendererSpec:: drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, - Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool ellipsis) { + Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool ellipsis, const Common::Rect &textDrawableArea) { int offset = area.top; if (font->getFontHeight() < area.height()) { switch (alignV) { - case GUI::ThemeEngine::kTextAlignVCenter: - offset = area.top + ((area.height() - font->getFontHeight()) >> 1); - break; - case GUI::ThemeEngine::kTextAlignVBottom: - offset = area.bottom - font->getFontHeight(); - break; - default: - break; + case GUI::ThemeEngine::kTextAlignVCenter: + offset = area.top + ((area.height() - font->getFontHeight()) >> 1); + break; + case GUI::ThemeEngine::kTextAlignVBottom: + offset = area.bottom - font->getFontHeight(); + break; + default: + break; } } - font->drawString(_activeSurface, text, area.left, offset, area.width() - deltax, _fgColor, alignH, deltax, ellipsis); + if (textDrawableArea.isEmpty()) { + font->drawString(_activeSurface, text, area.left, offset, area.width() - deltax, _fgColor, alignH, deltax, ellipsis); + // warning("there is no text drawable area. Please set this area for clipping"); + return; + } + + int textWidth = font->getStringWidth(text); + + int emptySpace = 0; + + switch (alignH) { + case Graphics::kTextAlignLeft: + // Let emptyspace = 0 + break; + case Graphics::kTextAlignCenter: + emptySpace = (area.width() - textWidth) / 2; + break; + case Graphics::kTextAlignRight: + emptySpace = area.right - textWidth; + break; + case Graphics::kTextAlignInvalid: + // warning("VectorRendererSpec::drawString(...) invalid text align"); + // return; + default: + break; + } + + // if text drawable area don't have any text for clipping + if ((textDrawableArea.right < (area.left + emptySpace)) || (textDrawableArea.left > (area.right - emptySpace))) + return; + + Surface backSurface; + backSurface.create(area.width(), font->getFontHeight() + 4, _activeSurface->format); + + byte *activeSurfacePtr = (byte *)_activeSurface->getBasePtr(area.left, area.top); + byte *backSurfacePtr = (byte *)backSurface.getBasePtr(0, 0); + + // copy background... + for (int i = 0; i < backSurface.h; i++) { + memcpy(backSurfacePtr, activeSurfacePtr, backSurface.w * backSurface.format.bytesPerPixel); + + activeSurfacePtr += _activeSurface->pitch; + backSurfacePtr += backSurface.pitch; + } + + font->drawString(&backSurface, text, 0, 0, area.width() - deltax, _fgColor, alignH, deltax, ellipsis); + + int fromX = ((area.left + emptySpace) < textDrawableArea.left) ? textDrawableArea.left : area.left + emptySpace; + int toX = ((area.right - emptySpace) > textDrawableArea.right) ? textDrawableArea.right : area.right - emptySpace; + + int bytesX = toX - fromX; + + int fromY = (area.top < textDrawableArea.top) ? textDrawableArea.top : area.top; + int toY = (textDrawableArea.bottom < area.bottom) ? textDrawableArea.bottom : area.bottom; + + // copy text from backSurface to activeSurface + activeSurfacePtr = (byte *)_activeSurface->getBasePtr(fromX, fromY); + backSurfacePtr = (byte *)backSurface.getBasePtr(fromX - area.left, fromY - area.top); + + for (int i = fromY; i < toY; i++) { + memcpy(activeSurfacePtr, backSurfacePtr, bytesX * backSurface.format.bytesPerPixel); + + activeSurfacePtr += _activeSurface->pitch; + backSurfacePtr += backSurface.pitch; + } + + backSurface.free(); } /** LINES **/ -- cgit v1.2.3 From 5c00dbbd2ac3d39e4ef801f3b50c3bb057422072 Mon Sep 17 00:00:00 2001 From: Narek Mailian Date: Mon, 1 Jul 2013 21:55:09 +0000 Subject: GRAPHICS: Add support for Soft Shadows with rounded squares --- graphics/VectorRendererSpec.cpp | 120 +++++++++++++++++++++++++--------------- 1 file changed, 74 insertions(+), 46 deletions(-) (limited to 'graphics/VectorRendererSpec.cpp') 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 void VectorRendererSpec:: -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 void VectorRendererSpec:: -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; } } -- cgit v1.2.3 From b91e10f931d481510d7d19c1e9d9169a7bf3b5c7 Mon Sep 17 00:00:00 2001 From: Narek Mailian Date: Tue, 23 Jul 2013 19:57:26 +0200 Subject: GRAPHICS: Shadows on tabs --- graphics/VectorRendererSpec.cpp | 66 +++++++++++++++++++++++++++++++++++++++-- 1 file changed, 64 insertions(+), 2 deletions(-) (limited to 'graphics/VectorRendererSpec.cpp') diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 85865124a6..e65d9d8831 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -915,13 +915,14 @@ drawTab(int x, int y, int r, int w, int h) { // 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.) - drawTabAlg(x, y, w, h, r, (Base::_fillMode == kFillBackground) ? _bgColor : _fgColor, Base::_fillMode); + 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: - drawTabAlg(x, y, w, h, r, (Base::_fillMode == kFillBackground) ? _bgColor : _fgColor, Base::_fillMode); + drawTabAlg(x, y, w, h, r, _fgColor, Base::_fillMode); break; } } @@ -1102,6 +1103,67 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: } +template +void VectorRendererSpec:: +drawTabShadow(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) + double expFactor = (_activeSurface->format.bytesPerPixel > 2) ? 1.60 : 1.25; + double alpha = (_activeSurface->format.bytesPerPixel > 2) ? 1 : 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 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) { + blendFill(ptr_tl - y - px, ptr_tr + y - px, color, alpha); + hb |= (1 << x); + } + + if (((1 << y) & hb) == 0) { + blendFill(ptr_tl - x - py, ptr_tr + x - py, color, alpha); + hb |= (1 << y); + } + } + + ptr_fill += pitch * r; + while (short_h--) { + blendFill(ptr_fill, ptr_fill + width + 1, color, alpha); + ptr_fill += pitch; + } + + // Move shadow one pixel upward each iteration + xstart += 1; + + alpha = alpha * expFactor; + } +} + /** BEVELED TABS FOR CLASSIC THEME **/ template void VectorRendererSpec:: -- cgit v1.2.3 From 52ee92625f0e3af8b0839fe3609a53afb37cbcd1 Mon Sep 17 00:00:00 2001 From: Narek Mailian Date: Tue, 6 Aug 2013 00:36:15 +0200 Subject: GRAPHICS: Change soft-shadow calculation to not use doubles --- graphics/VectorRendererSpec.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'graphics/VectorRendererSpec.cpp') diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index e65d9d8831..04859245b9 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -1110,8 +1110,8 @@ drawTabShadow(int x1, int y1, int w, int h, int r) { int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; // "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; + uint8 expFactor = 3; + uint16 alpha = (_activeSurface->format.bytesPerPixel > 2) ? 4 : 8; int xstart = x1; int ystart = y1; @@ -1141,26 +1141,26 @@ drawTabShadow(int x1, int y1, int w, int h, int r) { BE_ALGORITHM(); if (((1 << x) & hb) == 0) { - blendFill(ptr_tl - y - px, ptr_tr + y - px, color, alpha); + blendFill(ptr_tl - y - px, ptr_tr + y - px, color, (uint8)alpha); hb |= (1 << x); } if (((1 << y) & hb) == 0) { - blendFill(ptr_tl - x - py, ptr_tr + x - py, color, alpha); + blendFill(ptr_tl - x - py, ptr_tr + x - py, color, (uint8)alpha); hb |= (1 << y); } } ptr_fill += pitch * r; while (short_h--) { - blendFill(ptr_fill, ptr_fill + width + 1, color, alpha); + blendFill(ptr_fill, ptr_fill + width + 1, color, (uint8)alpha); ptr_fill += pitch; } // Move shadow one pixel upward each iteration xstart += 1; - - alpha = alpha * expFactor; + // Multiply with expfactor + alpha = (alpha * (expFactor << 8)) >> 9; } } @@ -1807,8 +1807,8 @@ drawRoundedSquareShadow(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) - double expFactor = (_activeSurface->format.bytesPerPixel > 2) ? 1.60 : 1.25; - double alpha = (_activeSurface->format.bytesPerPixel > 2) ? 1 : 8; + 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; @@ -1872,7 +1872,7 @@ drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) { if (_shadowFillMode == kShadowExponential) // Multiply with expfactor - alpha = alpha * expFactor; + alpha = (alpha * (expFactor << 8)) >> 9; } } -- cgit v1.2.3 From 6fa3c7751f0f60071ebf8cd8e1ccd4b819939c32 Mon Sep 17 00:00:00 2001 From: Narek Mailian Date: Sat, 20 Jul 2013 16:47:47 +0200 Subject: GRAPHICS: Gradient blending on borders of rounded squares --- graphics/VectorRendererSpec.cpp | 546 +++++++++++++++++++++++++--------------- 1 file changed, 349 insertions(+), 197 deletions(-) (limited to 'graphics/VectorRendererSpec.cpp') diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 04859245b9..2414f667ab 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -119,6 +119,38 @@ inline frac_t fp_sqroot(uint32 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) + +#define BE_DRAWCIRCLE_BCOLOR_TR_CCW(ptr,x,y,px,py,a) do { \ + 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) + +#define BE_DRAWCIRCLE_BCOLOR_TL_CCW(ptr,x,y,px,py,a) do { \ + 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) + +#define BE_DRAWCIRCLE_BCOLOR_BL_CCW(ptr,x,y,px,py,a) do { \ + 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) + +#define BE_DRAWCIRCLE_BCOLOR_BR_CCW(ptr,x,y,px,py,a) do { \ + 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; \ @@ -222,6 +254,37 @@ inline frac_t fp_sqroot(uint32 x) { this->blendPixelPtr(ptr4 + (y) + (px), color2, a); \ } while (0) +#define WU_DRAWCIRCLE_BCOLOR_TR_CW(ptr,x,y,px,py,a) do { \ + this->blendPixelPtr(ptr + (y) - (px), color, a); \ +} while (0) + +#define WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr,x,y,px,py,a) do { \ + this->blendPixelPtr(ptr + (x) - (py), color, a); \ +} while (0) + +#define WU_DRAWCIRCLE_BCOLOR_TL_CW(ptr,x,y,px,py,a) do { \ + this->blendPixelPtr(ptr - (x) - (py), color, a); \ +} while (0) + +#define WU_DRAWCIRCLE_BCOLOR_TL_CCW(ptr,x,y,px,py,a) do { \ + this->blendPixelPtr(ptr - (y) - (px), color, a); \ +} while (0) + +#define WU_DRAWCIRCLE_BCOLOR_BL_CW(ptr,x,y,px,py,a) do { \ + this->blendPixelPtr(ptr - (y) + (px), color, a); \ +} while (0) + +#define WU_DRAWCIRCLE_BCOLOR_BL_CCW(ptr,x,y,px,py,a) do { \ + this->blendPixelPtr(ptr - (x) + (py), color, a); \ +} while (0) + +#define WU_DRAWCIRCLE_BCOLOR_BR_CW(ptr,x,y,px,py,a) do { \ + this->blendPixelPtr(ptr + (x) + (py), color, a); \ +} while (0) + +#define WU_DRAWCIRCLE_BCOLOR_BR_CCW(ptr,x,y,px,py,a) do { \ + this->blendPixelPtr(ptr + (y) + (px), color, a); \ +} while (0) // optimized Wu's algorithm #define WU_ALGORITHM() do { \ @@ -1597,118 +1660,160 @@ drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, Vecto /** ROUNDED SQUARE ALGORITHM **/ template void VectorRendererSpec:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { +drawBorderRoundedSquareAlg(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; - // TODO: Split this up into border, bevel and interior functions + 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); - if (fill_m != kFillDisabled) { - 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; + int real_radius = r; + int short_h = h - (2 * r) + 2; - BE_RESET(); + PixelType color1 = color; + PixelType color2 = color; - PixelType color1 = color; - if (fill_m == kFillBackground) - color1 = _bgColor; + while (sw++ < Base::_strokeWidth) { + blendFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1, alpha_t); // top + blendFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2, alpha_b); // bottom + sp += pitch; - if (fill_m == kFillGradient) { - PixelType color2, color3, color4; - precalcGradient(long_h); + 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)); - while (x++ < y) { - BE_ALGORITHM(); + // Avoid blending the last pixels twice, since we have an alpha + while (x++ < (y - 2)) { + 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); + 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))); + BE_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, x, y, px, py, (uint8)(alpha_t + (alphaStep_tl * x))); + + BE_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, x, y, px, py, (uint8)(alpha_t - (alphaStep_tr * x))); + BE_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, x, y, px, py, (uint8)(alpha_r - (alphaStep_br * x))); + BE_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, x, y, px, py, (uint8)(alpha_b - (alphaStep_bl * x))); + BE_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, x, y, px, py, (uint8)(alpha_l - (alphaStep_tl * x))); + + if (Base::_strokeWidth > 1) { + BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py); + BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py); + } + } + } - gradientFill(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y); - gradientFill(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x); + ptr_fill += pitch * real_radius; + while (short_h--) { + blendFill(ptr_fill, ptr_fill + Base::_strokeWidth, color1, alpha_l); // left + blendFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2, alpha_r); // right + ptr_fill += pitch; + } +} - gradientFill(ptr_bl - x + py, w - 2 * r + 2 * x, x1 + r - x - y, long_h - r + y); - gradientFill(ptr_bl - y + px, w - 2 * r + 2 * y, x1 + r - y - x, long_h - r + x); +template +void VectorRendererSpec:: +drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { + int f, ddF_x, ddF_y; + int x, y, px, py; + int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; - BE_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); - } - } else { - while (x++ < y) { - BE_ALGORITHM(); + 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); - colorFill(ptr_tl - x - py, ptr_tr + x - py, color1); - colorFill(ptr_tl - y - px, ptr_tr + y - px, color1); + int real_radius = r; + int short_h = h - (2 * r) + 2; + int long_h = h; - colorFill(ptr_bl - x + py, ptr_br + x + py, color1); - colorFill(ptr_bl - y + px, ptr_br + y + px, color1); + BE_RESET(); - // do not remove - messes up the drawing at lower resolutions - BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); - } - } + PixelType color1 = color; - ptr_fill += pitch * r; - while (short_h--) { - if (fill_m == kFillGradient) { - gradientFill(ptr_fill, w + 1, x1, real_radius++); - } else { - colorFill(ptr_fill, ptr_fill + w + 1, color1); - } - ptr_fill += pitch; - } - } + if (fill_m == kFillGradient) { + PixelType color2, color3, color4; + precalcGradient(long_h); + while (x++ < y) { + BE_ALGORITHM(); - if (Base::_strokeWidth) { - int sw = 0, sp = 0, hp = h * pitch; + 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); - 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); + gradientFill(ptr_tl - x - py, w - 2 * r + 2 * x, x1 + r - x - y, real_radius - y); + gradientFill(ptr_tl - y - px, w - 2 * r + 2 * y, x1 + r - y - x, real_radius - x); - int real_radius = r; - int short_h = h - (2 * r) + 2; + gradientFill(ptr_bl - x + py, w - 2 * r + 2 * x, x1 + r - x - y, long_h - r + y); + gradientFill(ptr_bl - y + px, w - 2 * r + 2 * y, x1 + r - y - x, long_h - r + x); - // TODO: A gradient effect on the bevel - PixelType color1, color2; - color1 = Base::_bevel ? _bevelColor : color; - color2 = color; + BE_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + } + } else { + while (x++ < y) { + BE_ALGORITHM(); - while (sw++ < Base::_strokeWidth) { - colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1); - colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2); - sp += pitch; + colorFill(ptr_tl - x - py, ptr_tr + x - py, color1); + colorFill(ptr_tl - y - px, ptr_tr + y - px, color1); - BE_RESET(); - r--; + colorFill(ptr_bl - x + py, ptr_br + x + py, color1); + colorFill(ptr_bl - y + px, ptr_br + y + px, color1); - while (x++ < y) { - BE_ALGORITHM(); - BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + // do not remove - messes up the drawing at lower resolutions + BE_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py); + } + } - if (Base::_strokeWidth > 1) { - BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x - 1, y, px, py); - BE_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px - pitch, py); - } - } + ptr_fill += pitch * r; + while (short_h--) { + if (fill_m == kFillGradient) { + gradientFill(ptr_fill, w + 1, x1, real_radius++); + } else { + colorFill(ptr_fill, ptr_fill + w + 1, color1); } + ptr_fill += pitch; + } +} - ptr_fill += pitch * real_radius; - while (short_h--) { - colorFill(ptr_fill, ptr_fill + Base::_strokeWidth, color1); - colorFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2); - ptr_fill += pitch; +template +void VectorRendererSpec:: +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; + 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) + drawInteriorRoundedSquareAlg(x1, y1, r, w, h, _bgColor, fill_m); + else + drawInteriorRoundedSquareAlg(x1, y1, r, w, h, color, fill_m); + } + + if (Base::_strokeWidth) { + if (r != 0 && _bevel > 0) { + drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l); + drawBorderRoundedSquareAlg(x1, y1, r, w, h, _bevelColor, fill_m, bevelAlpha_t, bevelAlpha_r, bevelAlpha_b, bevelAlpha_l); + } else { + drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, 255, 255, 255, 255); } } } @@ -2065,7 +2170,7 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: /** ROUNDED SQUARES **/ template void VectorRendererAA:: -drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { +drawBorderRoundedSquareAlg(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 x, y; const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel; int px, py; @@ -2074,65 +2179,89 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto frac_t T = 0, oldT; uint8 a1, a2; - // TODO: Split this up into border, bevel and interior functions + 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); - if (Base::_strokeWidth) { - 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 sw = 0, sp = 0; - int short_h = h - 2 * r; - int hp = h * pitch; - - int strokeWidth = Base::_strokeWidth; - // If we're going to fill the inside, draw a slightly thicker border - // so we can blend the inside on top of it. - if (fill_m != Base::kFillDisabled) strokeWidth++; - - // TODO: A gradient effect on the bevel - PixelType color1, color2; - color1 = Base::_bevel ? Base::_bevelColor : color; - color2 = color; + int sw = 0, sp = 0; + int short_h = h - 2 * r; + int hp = h * pitch; + int strokeWidth = Base::_strokeWidth; - while (sw++ < strokeWidth) { - colorFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1); - colorFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2); - sp += pitch; + while (sw++ < strokeWidth) { + this->blendFill(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color, alpha_b); // bottom + this->blendFill(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color, alpha_t); // top - x = r - (sw - 1); - y = 0; - T = 0; - px = pitch * x; - py = 0; + sp += pitch; - while (x > y++) { - WU_ALGORITHM(); + x = r - (sw - 1); + y = 0; + T = 0; + px = pitch * x; + py = 0; - // sw == 1: outside, sw = _strokeWidth: inside - // We always draw the outer edge AAed, but the inner edge - // only when the inside isn't filled - if (sw != strokeWidth || fill_m != Base::kFillDisabled) - a2 = 255; + int alphaStep_tr = ((alpha_t - alpha_r)/(x+1)); + int alphaStep_br = ((alpha_r - alpha_b)/(x+1)); + int alphaStep_bl = ((alpha_b - alpha_l)/(x+1)); + int alphaStep_tl = ((alpha_l - alpha_t)/(x+1)); - // inner arc - WU_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, (x - 1), y, (px - pitch), py, a2); + while (x > y++) { + WU_ALGORITHM(); - if (sw == 1) // outer arc - WU_DRAWCIRCLE_BCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); + // sw == 1: outside, sw = _strokeWidth: inside + // We always draw the outer edge AAed, but the inner edge + // only when the inside isn't filled + if (sw != strokeWidth || fill_m != Base::kFillDisabled) + a2 = 255; + + // inner arc + WU_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_t - (alphaStep_tr * y)) << 8) * a2) >> 16)); + WU_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_r - (alphaStep_br * y)) << 8) * a2) >> 16)); + WU_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_b - (alphaStep_bl * y)) << 8) * a2) >> 16)); + WU_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_l - (alphaStep_tl * y)) << 8) * a2) >> 16)); + + WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_r + (alphaStep_tr * y)) << 8) * a2) >> 16)); + WU_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_b + (alphaStep_br * y)) << 8) * a2) >> 16)); + WU_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_l + (alphaStep_bl * y)) << 8) * a2) >> 16)); + WU_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, (x - 1), y, (px - pitch), py, (uint8)((uint32)(((alpha_t + (alphaStep_tl * y)) << 8) * a2) >> 16)); + + // outer arc + if (sw == 1) { + WU_DRAWCIRCLE_BCOLOR_TR_CW(ptr_tr, x, y, px, py, (uint8)((uint32)(((alpha_t - (alphaStep_tr * y)) << 8) * a1) >> 16)); + WU_DRAWCIRCLE_BCOLOR_BR_CW(ptr_br, x, y, px, py, (uint8)((uint32)(((alpha_r - (alphaStep_br * y)) << 8) * a1) >> 16)); + WU_DRAWCIRCLE_BCOLOR_BL_CW(ptr_bl, x, y, px, py, (uint8)((uint32)(((alpha_b - (alphaStep_bl * y)) << 8) * a1) >> 16)); + WU_DRAWCIRCLE_BCOLOR_TL_CW(ptr_tl, x, y, px, py, (uint8)((uint32)(((alpha_l - (alphaStep_tl * y)) << 8) * a1) >> 16)); + + WU_DRAWCIRCLE_BCOLOR_TR_CCW(ptr_tr, x, y, px, py, (uint8)((uint32)(((alpha_r + (alphaStep_tr * y)) << 8) * a1) >> 16)); + WU_DRAWCIRCLE_BCOLOR_BR_CCW(ptr_br, x, y, px, py, (uint8)((uint32)(((alpha_b + (alphaStep_br * y)) << 8) * a1) >> 16)); + WU_DRAWCIRCLE_BCOLOR_BL_CCW(ptr_bl, x, y, px, py, (uint8)((uint32)(((alpha_l + (alphaStep_bl * y)) << 8) * a1) >> 16)); + WU_DRAWCIRCLE_BCOLOR_TL_CCW(ptr_tl, x, y, px, py, (uint8)((uint32)(((alpha_t + (alphaStep_tl * y)) << 8) * a1) >> 16)); + } } - } ptr_fill += pitch * r; - while (short_h-- >= 0) { - colorFill(ptr_fill, ptr_fill + Base::_strokeWidth, color1); - colorFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2); + + while (short_h-- >= -2) { + this->blendFill(ptr_fill, ptr_fill + Base::_strokeWidth, color, alpha_l); // left + this->blendFill(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color, alpha_r); // right ptr_fill += pitch; } } +} + +template +void VectorRendererAA:: +drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m) { + int x, y; + const int pitch = Base::_activeSurface->pitch / Base::_activeSurface->format.bytesPerPixel; + int px, py; + + uint32 rsq = r*r; + frac_t T = 0, oldT; + uint8 a1, a2; r -= Base::_strokeWidth; x1 += Base::_strokeWidth; @@ -2141,93 +2270,116 @@ drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, Vecto h -= 2*Base::_strokeWidth; rsq = r*r; - if (w <= 0 || h <= 0) - return; // Only border is visible + 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); - if (fill_m != Base::kFillDisabled) { - if (fill_m == Base::kFillBackground) - color = Base::_bgColor; + int short_h = h - 2 * r; + x = r; + y = 0; + T = 0; + px = pitch * x; + py = 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_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); + if (fill_m == Base::kFillGradient) { - int short_h = h - 2 * r; - x = r; - y = 0; - T = 0; - px = pitch * x; - py = 0; + Base::precalcGradient(h); - if (fill_m == Base::kFillGradient) { + PixelType color1, color2, color3, color4; + while (x > y++) { + WU_ALGORITHM(); - Base::precalcGradient(h); + color1 = Base::calcGradient(r - x, h); + color2 = Base::calcGradient(r - y, h); + color3 = Base::calcGradient(h - r + x, h); + color4 = Base::calcGradient(h - r + y, h); - PixelType color1, color2, color3, color4; - while (x > y++) { - WU_ALGORITHM(); + Base::gradientFill(ptr_tl - x - py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, r - y); - color1 = Base::calcGradient(r - x, h); - color2 = Base::calcGradient(r - y, h); - color3 = Base::calcGradient(h - r + x, h); - color4 = Base::calcGradient(h - r + y, h); + // Only fill each horizontal line once (or we destroy + // the gradient effect at the edges) + if (T < oldT || y == 1) + Base::gradientFill(ptr_tl - y - px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, r - x); - Base::gradientFill(ptr_tl - x - py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, r - y); + Base::gradientFill(ptr_bl - x + py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, h - r + y); - // Only fill each horizontal line once (or we destroy - // the gradient effect at the edges) - if (T < oldT || y == 1) - Base::gradientFill(ptr_tl - y - px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, r - x); + // Only fill each horizontal line once (or we destroy + // the gradient effect at the edges) + if (T < oldT || y == 1) + Base::gradientFill(ptr_bl - y + px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, h - r + x); - Base::gradientFill(ptr_bl - x + py + 1, w - 2 * r + 2 * x - 1, x1 + r - x - y + 1, h - r + y); + // This shape is used for dialog backgrounds. + // If we're drawing on top of an empty overlay background, + // and the overlay supports alpha, we have to do AA by + // setting the dest alpha channel, instead of blending with + // dest color channels. + if (!g_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha)) + WU_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1, blendPixelPtr); + else + WU_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1, blendPixelDestAlphaPtr); + } - // Only fill each horizontal line once (or we destroy - // the gradient effect at the edges) - if (T < oldT || y == 1) - Base::gradientFill(ptr_bl - y + px + 1, w - 2 * r + 2 * y - 1, x1 + r - y - x + 1, h - r + x); - - // This shape is used for dialog backgrounds. - // If we're drawing on top of an empty overlay background, - // and the overlay supports alpha, we have to do AA by - // setting the dest alpha channel, instead of blending with - // dest color channels. - if (!g_system->hasFeature(OSystem::kFeatureOverlaySupportsAlpha)) - WU_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1, blendPixelPtr); - else - WU_DRAWCIRCLE_XCOLOR(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1, blendPixelDestAlphaPtr); - } + ptr_fill += pitch * r; + while (short_h-- >= 0) { + Base::gradientFill(ptr_fill, w + 1, x1, r++); + ptr_fill += pitch; + } - ptr_fill += pitch * r; - while (short_h-- >= 0) { - Base::gradientFill(ptr_fill, w + 1, x1, r++); - ptr_fill += pitch; - } + } else { - } else { + while (x > 1 + y++) { + WU_ALGORITHM(); - while (x > 1 + y++) { - WU_ALGORITHM(); + colorFill(ptr_tl - x - py + 1, ptr_tr + x - py, color); + if (T < oldT || y == 1) + colorFill(ptr_tl - y - px + 1, ptr_tr + y - px, color); - colorFill(ptr_tl - x - py + 1, ptr_tr + x - py, color); - if (T < oldT || y == 1) - colorFill(ptr_tl - y - px + 1, ptr_tr + y - px, color); + colorFill(ptr_bl - x + py + 1, ptr_br + x + py, color); + if (T < oldT || y == 1) + colorFill(ptr_bl - y + px + 1, ptr_br + y + px, color); - colorFill(ptr_bl - x + py + 1, ptr_br + x + py, color); - if (T < oldT || y == 1) - colorFill(ptr_bl - y + px + 1, ptr_br + y + px, color); + WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); + } - WU_DRAWCIRCLE(ptr_tr, ptr_tl, ptr_bl, ptr_br, x, y, px, py, a1); - } + ptr_fill += pitch * r; + while (short_h-- >= 0) { + colorFill(ptr_fill, ptr_fill + w + 1, color); + ptr_fill += pitch; + } + } +} - ptr_fill += pitch * r; - while (short_h-- >= 0) { - colorFill(ptr_fill, ptr_fill + w + 1, color); - ptr_fill += pitch; - } +template +void VectorRendererAA:: +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; + 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 (Base::_strokeWidth) { + if (r != 0 && Base::_bevel > 0) { + drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, borderAlpha_t, borderAlpha_r, borderAlpha_b, borderAlpha_l); + drawBorderRoundedSquareAlg(x1, y1, r, w, h, Base::_bevelColor, fill_m, bevelAlpha_t, bevelAlpha_r, bevelAlpha_b, bevelAlpha_l); + } else { + drawBorderRoundedSquareAlg(x1, y1, r, w, h, color, fill_m, 255, 255, 255, 255); } } + + // If only border is visible + if ((!(w <= 0 || h <= 0)) && (fill_m != Base::kFillDisabled)) { + if (fill_m == Base::kFillBackground) + drawInteriorRoundedSquareAlg(x1, y1, r, w, h, Base::_bgColor, fill_m); + else + drawInteriorRoundedSquareAlg(x1, y1, r, w, h, color, fill_m); + } } /** CIRCLES **/ -- cgit v1.2.3 From 8c2bbb09a8789b17adc4abe609571d1a0b64e535 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Mon, 19 Aug 2013 19:34:41 +0200 Subject: GRAPHICS: Add missing "break"s in switch, CID 1063214 This won't actually make any difference, since the fall through would do nothing and then reach the break in the default case. But I think it's less error-prone this way if the code is ever modified. --- graphics/VectorRendererSpec.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'graphics/VectorRendererSpec.cpp') diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index e4843ba78b..cb714a0b45 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -287,12 +287,14 @@ VectorRenderer *createRenderer(int mode) { return new VectorRendererSpec(format); else if (g_system->getOverlayFormat().bytesPerPixel == 2) return new VectorRendererSpec(format); + break; #ifndef DISABLE_FANCY_THEMES case GUI::ThemeEngine::kGfxAntialias: if (g_system->getOverlayFormat().bytesPerPixel == 4) return new VectorRendererAA(format); else if (g_system->getOverlayFormat().bytesPerPixel == 2) return new VectorRendererAA(format); + break; #endif default: break; -- cgit v1.2.3 From 81ae06cae36a398c4126cfa80022677703e9ab57 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 6 Aug 2013 22:28:35 +0200 Subject: GRAPHICS: Simplify VectorRendererSpec::drawString. This removes the two additional copy steps for rendering when a drawable text area is specified. Instead it uses Surface::getSubArea to draw directly onto _activeSurface. --- graphics/VectorRendererSpec.cpp | 73 ++++++----------------------------------- 1 file changed, 10 insertions(+), 63 deletions(-) (limited to 'graphics/VectorRendererSpec.cpp') diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 2414f667ab..73fcee10e6 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -729,70 +729,17 @@ drawString(const Graphics::Font *font, const Common::String &text, const Common: if (textDrawableArea.isEmpty()) { font->drawString(_activeSurface, text, area.left, offset, area.width() - deltax, _fgColor, alignH, deltax, ellipsis); // warning("there is no text drawable area. Please set this area for clipping"); - return; - } - - int textWidth = font->getStringWidth(text); - - int emptySpace = 0; - - switch (alignH) { - case Graphics::kTextAlignLeft: - // Let emptyspace = 0 - break; - case Graphics::kTextAlignCenter: - emptySpace = (area.width() - textWidth) / 2; - break; - case Graphics::kTextAlignRight: - emptySpace = area.right - textWidth; - break; - case Graphics::kTextAlignInvalid: - // warning("VectorRendererSpec::drawString(...) invalid text align"); - // return; - default: - break; - } - - // if text drawable area don't have any text for clipping - if ((textDrawableArea.right < (area.left + emptySpace)) || (textDrawableArea.left > (area.right - emptySpace))) - return; - - Surface backSurface; - backSurface.create(area.width(), font->getFontHeight() + 4, _activeSurface->format); - - byte *activeSurfacePtr = (byte *)_activeSurface->getBasePtr(area.left, area.top); - byte *backSurfacePtr = (byte *)backSurface.getBasePtr(0, 0); - - // copy background... - for (int i = 0; i < backSurface.h; i++) { - memcpy(backSurfacePtr, activeSurfacePtr, backSurface.w * backSurface.format.bytesPerPixel); - - activeSurfacePtr += _activeSurface->pitch; - backSurfacePtr += backSurface.pitch; - } - - font->drawString(&backSurface, text, 0, 0, area.width() - deltax, _fgColor, alignH, deltax, ellipsis); - - int fromX = ((area.left + emptySpace) < textDrawableArea.left) ? textDrawableArea.left : area.left + emptySpace; - int toX = ((area.right - emptySpace) > textDrawableArea.right) ? textDrawableArea.right : area.right - emptySpace; - - int bytesX = toX - fromX; - - int fromY = (area.top < textDrawableArea.top) ? textDrawableArea.top : area.top; - int toY = (textDrawableArea.bottom < area.bottom) ? textDrawableArea.bottom : area.bottom; - - // copy text from backSurface to activeSurface - activeSurfacePtr = (byte *)_activeSurface->getBasePtr(fromX, fromY); - backSurfacePtr = (byte *)backSurface.getBasePtr(fromX - area.left, fromY - area.top); - - for (int i = fromY; i < toY; i++) { - memcpy(activeSurfacePtr, backSurfacePtr, bytesX * backSurface.format.bytesPerPixel); - - activeSurfacePtr += _activeSurface->pitch; - backSurfacePtr += backSurface.pitch; + } else { + // The area we can draw to is the intersection between the allowed + // drawing area (textDrawableArea) and the area where we try to draw + // the text (area). + Common::Rect drawArea = textDrawableArea.findIntersectingRect(area); + + if (!drawArea.isEmpty()) { + Surface textAreaSurface = _activeSurface->getSubArea(drawArea); + font->drawString(&textAreaSurface, text, area.left - drawArea.left, offset - drawArea.top, area.width() - deltax, _fgColor, alignH, deltax, ellipsis); + } } - - backSurface.free(); } /** LINES **/ -- cgit v1.2.3 From af13b74d023c3f7880f1b06f427d3b69e5c8831e Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 6 Aug 2013 22:31:36 +0200 Subject: GRAPHICS: Unify drawing paths in VectorRendererSpec::drawString. Formerly, the behavior between when a drawable area was specified and when not was different in a sense which is not expected. For example, when an empty textDrawableArea was passed and the text could be drawn outside the 'area' specified. While when a textDrawableArea covering the whole screen was passed the text was clipped inside 'area'. Now, the code does follow the latter logic in both cases. I am not sure whether this will cause any issues, but a quick check of the launcher and options menu didn't reveal anything... --- graphics/VectorRendererSpec.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'graphics/VectorRendererSpec.cpp') diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index 73fcee10e6..e68242575e 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -726,19 +726,22 @@ drawString(const Graphics::Font *font, const Common::String &text, const Common: } } + Common::Rect drawArea; if (textDrawableArea.isEmpty()) { - font->drawString(_activeSurface, text, area.left, offset, area.width() - deltax, _fgColor, alignH, deltax, ellipsis); + // In case no special area to draw to is given we only draw in the + // area specified by the user. + drawArea = area; // warning("there is no text drawable area. Please set this area for clipping"); } else { // The area we can draw to is the intersection between the allowed // drawing area (textDrawableArea) and the area where we try to draw // the text (area). - Common::Rect drawArea = textDrawableArea.findIntersectingRect(area); - - if (!drawArea.isEmpty()) { - Surface textAreaSurface = _activeSurface->getSubArea(drawArea); - font->drawString(&textAreaSurface, text, area.left - drawArea.left, offset - drawArea.top, area.width() - deltax, _fgColor, alignH, deltax, ellipsis); - } + drawArea = textDrawableArea.findIntersectingRect(area); + } + + if (!drawArea.isEmpty()) { + Surface textAreaSurface = _activeSurface->getSubArea(drawArea); + font->drawString(&textAreaSurface, text, area.left - drawArea.left, offset - drawArea.top, area.width() - deltax, _fgColor, alignH, deltax, ellipsis); } } -- cgit v1.2.3 From a2fabef87c3558a6407fb2f53e86b3b687a755f6 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 6 Aug 2013 22:59:59 +0200 Subject: GRAPHICS: Increase robustness of VectorRendererSpec::drawString. --- graphics/VectorRendererSpec.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'graphics/VectorRendererSpec.cpp') diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index e68242575e..280bd6ec76 100644 --- a/graphics/VectorRendererSpec.cpp +++ b/graphics/VectorRendererSpec.cpp @@ -738,7 +738,12 @@ drawString(const Graphics::Font *font, const Common::String &text, const Common: // the text (area). drawArea = textDrawableArea.findIntersectingRect(area); } - + + // Better safe than sorry. We intersect with the actual surface boundaries + // to avoid any ugly clipping in _activeSurface->getSubArea which messes + // up the calculation of the x and y coordinates where to draw the string. + drawArea = drawArea.findIntersectingRect(Common::Rect(0, 0, _activeSurface->w, _activeSurface->h)); + if (!drawArea.isEmpty()) { Surface textAreaSurface = _activeSurface->getSubArea(drawArea); font->drawString(&textAreaSurface, text, area.left - drawArea.left, offset - drawArea.top, area.width() - deltax, _fgColor, alignH, deltax, ellipsis); -- cgit v1.2.3