diff options
-rw-r--r-- | graphics/VectorRenderer.h | 16 | ||||
-rw-r--r-- | graphics/VectorRendererSpec.cpp | 775 | ||||
-rw-r--r-- | graphics/VectorRendererSpec.h | 26 | ||||
-rw-r--r-- | graphics/font.cpp | 2 | ||||
-rw-r--r-- | gui/ThemeEngine.cpp | 17 | ||||
-rw-r--r-- | gui/ThemeEngine.h | 9 | ||||
-rw-r--r-- | gui/about.cpp | 7 | ||||
-rw-r--r-- | gui/object.cpp | 2 | ||||
-rw-r--r-- | gui/object.h | 7 | ||||
-rw-r--r-- | gui/themes/scummclassic.zip | bin | 110000 -> 113348 bytes | |||
-rw-r--r-- | gui/themes/scummmodern.zip | bin | 1485763 -> 1489429 bytes | |||
-rw-r--r-- | gui/themes/scummmodern/scummmodern_gfx.stx | 42 | ||||
-rw-r--r-- | gui/widgets/editable.cpp | 2 | ||||
-rw-r--r-- | gui/widgets/edittext.cpp | 8 |
14 files changed, 607 insertions, 306 deletions
diff --git a/graphics/VectorRenderer.h b/graphics/VectorRenderer.h index 5d6369c08f..8e1c5e91e1 100644 --- a/graphics/VectorRenderer.h +++ b/graphics/VectorRenderer.h @@ -73,6 +73,8 @@ struct DrawStep { uint8 shadow, stroke, factor, radius, bevel; /**< Misc options... */ uint8 fillMode; /**< active fill mode */ + uint8 shadowFillMode; /**< fill mode of the shadow used */ + uint32 extraData; /**< Generic parameter for extra options (orientation/bevel) */ uint32 scale; /**< scale of all the coordinates in FIXED POINT with 16 bits mantissa */ @@ -103,7 +105,7 @@ VectorRenderer *createRenderer(int mode); */ class VectorRenderer { public: - VectorRenderer() : _activeSurface(NULL), _fillMode(kFillDisabled), _shadowOffset(0), + VectorRenderer() : _activeSurface(NULL), _fillMode(kFillDisabled), _shadowOffset(0), _shadowFillMode(kShadowExponential), _disableShadows(false), _strokeWidth(1), _gradientFactor(1) { } @@ -126,6 +128,11 @@ public: kTriangleRight }; + enum ShadowFillMode { + kShadowLinear = 0, + kShadowExponential = 1 + }; + /** * Draws a line by considering the special cases for optimization. * @@ -292,6 +299,10 @@ public: _fillMode = mode; } + virtual void setShadowFillMode(ShadowFillMode mode) { + _shadowFillMode = mode; + } + /** * Sets the stroke width. All shapes drawn with a stroke will * have that width. Pass 0 to disable shape stroking. @@ -466,7 +477,7 @@ public: */ virtual void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, Graphics::TextAlign alignH, - GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool useEllipsis) = 0; + GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool useEllipsis, const Common::Rect &textDrawableArea) = 0; /** * Allows to temporarily enable/disable all shadows drawing. @@ -485,6 +496,7 @@ protected: Surface *_activeSurface; /**< Pointer to the surface currently being drawn */ FillMode _fillMode; /**< Defines in which way (if any) are filled the drawn shapes */ + ShadowFillMode _shadowFillMode; int _shadowOffset; /**< offset for drawn shadows */ int _bevel; /**< amount of fake bevel */ diff --git a/graphics/VectorRendererSpec.cpp b/graphics/VectorRendererSpec.cpp index cb714a0b45..491a9d7f42 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 { \ @@ -648,24 +711,45 @@ darkenFill(PixelType *ptr, PixelType *end) { template<typename PixelType> void VectorRendererSpec<PixelType>:: 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); + Common::Rect drawArea; + if (textDrawableArea.isEmpty()) { + // 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). + 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); + } } /** LINES **/ @@ -819,7 +903,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); } @@ -850,13 +935,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; } } @@ -1037,6 +1123,67 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: } +template<typename PixelType> +void VectorRendererSpec<PixelType>:: +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) + 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 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, (uint8)alpha); + hb |= (1 << x); + } + + if (((1 << y) & hb) == 0) { + 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, (uint8)alpha); + ptr_fill += pitch; + } + + // 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>:: @@ -1470,118 +1617,160 @@ drawTriangleFast(int x1, int y1, int size, bool inverted, PixelType color, Vecto /** ROUNDED SQUARE ALGORITHM **/ template<typename PixelType> void VectorRendererSpec<PixelType>:: -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 - - 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; + 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); - BE_RESET(); + int real_radius = r; + int short_h = h - (2 * r) + 2; - PixelType color1 = color; - if (fill_m == kFillBackground) - color1 = _bgColor; + PixelType color1 = color; + PixelType color2 = color; - if (fill_m == kFillGradient) { - PixelType color2, color3, color4; - precalcGradient(long_h); + 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; - while (x++ < y) { - BE_ALGORITHM(); + 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(); - 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<typename PixelType> +void VectorRendererSpec<PixelType>:: +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<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color1); - colorFill<PixelType>(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<PixelType>(ptr_bl - x + py, ptr_br + x + py, color1); - colorFill<PixelType>(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<PixelType>(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<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1); - colorFill<PixelType>(ptr_fill + hp - sp + r, ptr_fill + w + hp + 1 - sp - r, color2); - sp += pitch; + colorFill<PixelType>(ptr_tl - x - py, ptr_tr + x - py, color1); + colorFill<PixelType>(ptr_tl - y - px, ptr_tr + y - px, color1); - BE_RESET(); - r--; + colorFill<PixelType>(ptr_bl - x + py, ptr_br + x + py, color1); + colorFill<PixelType>(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<PixelType>(ptr_fill, ptr_fill + w + 1, color1); } + ptr_fill += pitch; + } +} - ptr_fill += pitch * real_radius; - while (short_h--) { - colorFill<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color1); - colorFill<PixelType>(ptr_fill + w - Base::_strokeWidth + 1, ptr_fill + w + 1, color2); - 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; + 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); } } } @@ -1640,85 +1829,112 @@ drawCircleAlg(int x1, int y1, int r, PixelType color, VectorRenderer::FillMode f ********************************************************************/ template<typename PixelType> void VectorRendererSpec<PixelType>:: -drawSquareShadow(int x, int y, int w, int h, int blur) { - PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + blur); +drawSquareShadow(int x, int y, int w, int h, int offset) { + PixelType *ptr = (PixelType *)_activeSurface->getBasePtr(x + w - 1, y + offset); int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; int i, j; - i = h - blur; + i = h - offset; while (i--) { - j = blur; + j = offset; while (j--) - blendPixelPtr(ptr + j, 0, ((blur - j) << 8) / blur); + blendPixelPtr(ptr + j, 0, ((offset - j) << 8) / offset); ptr += pitch; } - ptr = (PixelType *)_activeSurface->getBasePtr(x + blur, y + h - 1); + ptr = (PixelType *)_activeSurface->getBasePtr(x + offset, y + h - 1); - while (i++ < blur) { - j = w - blur; + while (i++ < offset) { + j = w - offset; while (j--) - blendPixelPtr(ptr + j, 0, ((blur - i) << 8) / blur); + blendPixelPtr(ptr + j, 0, ((offset - i) << 8) / offset); ptr += pitch; } ptr = (PixelType *)_activeSurface->getBasePtr(x + w, y + h); i = 0; - while (i++ < blur) { - j = blur - 1; + while (i++ < offset) { + j = offset - 1; while (j--) - blendPixelPtr(ptr + j, 0, (((blur - j) * (blur - i)) << 8) / (blur * blur)); + blendPixelPtr(ptr + j, 0, (((offset - j) * (offset - i)) << 8) / (offset * offset)); ptr += pitch; } } template<typename PixelType> void VectorRendererSpec<PixelType>:: -drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int blur) { - int f, ddF_x, ddF_y; - int x, y, px, py; +drawRoundedSquareShadow(int x1, int y1, int r, int w, int h, int offset) { int pitch = _activeSurface->pitch / _activeSurface->format.bytesPerPixel; - int alpha = 102; - x1 += blur; - y1 += blur; - - PixelType *ptr_tr = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + r); - PixelType *ptr_bl = (PixelType *)Base::_activeSurface->getBasePtr(x1 + r, y1 + h - r); - PixelType *ptr_br = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - r, y1 + h - r); - PixelType *ptr_fill = (PixelType *)Base::_activeSurface->getBasePtr(x1 + w - blur, y1 + r); + // "Harder" shadows when having lower BPP, since we will have artifacts (greenish tint on the modern theme) + 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); - 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 << 8)) >> 9; } } @@ -1911,7 +2127,7 @@ drawTabAlg(int x1, int y1, int w, int h, int r, PixelType color, VectorRenderer: /** ROUNDED SQUARES **/ template<typename PixelType> void VectorRendererAA<PixelType>:: -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; @@ -1920,65 +2136,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<PixelType>(ptr_fill + sp + r, ptr_fill + w + 1 + sp - r, color1); - colorFill<PixelType>(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<PixelType>(ptr_fill, ptr_fill + Base::_strokeWidth, color1); - colorFill<PixelType>(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<typename PixelType> +void VectorRendererAA<PixelType>:: +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; @@ -1987,93 +2227,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<PixelType>(ptr_tl - x - py + 1, ptr_tr + x - py, color); + if (T < oldT || y == 1) + colorFill<PixelType>(ptr_tl - y - px + 1, ptr_tr + y - px, color); - colorFill<PixelType>(ptr_tl - x - py + 1, ptr_tr + x - py, color); - if (T < oldT || y == 1) - colorFill<PixelType>(ptr_tl - y - px + 1, ptr_tr + y - px, color); + colorFill<PixelType>(ptr_bl - x + py + 1, ptr_br + x + py, color); + if (T < oldT || y == 1) + colorFill<PixelType>(ptr_bl - y + px + 1, ptr_br + y + px, color); - colorFill<PixelType>(ptr_bl - x + py + 1, ptr_br + x + py, color); - if (T < oldT || y == 1) - colorFill<PixelType>(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<PixelType>(ptr_fill, ptr_fill + w + 1, color); + ptr_fill += pitch; + } + } +} - ptr_fill += pitch * r; - while (short_h-- >= 0) { - colorFill<PixelType>(ptr_fill, ptr_fill + w + 1, color); - ptr_fill += pitch; - } +template<typename PixelType> +void VectorRendererAA<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; + 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 **/ diff --git a/graphics/VectorRendererSpec.h b/graphics/VectorRendererSpec.h index 4ed80cb55f..c035ca0e19 100644 --- a/graphics/VectorRendererSpec.h +++ b/graphics/VectorRendererSpec.h @@ -61,7 +61,7 @@ public: } void drawString(const Graphics::Font *font, const Common::String &text, const Common::Rect &area, Graphics::TextAlign alignH, - GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool elipsis); + GUI::ThemeEngine::TextAlignVertical alignV, int deltax, bool elipsis, const Common::Rect &textDrawableArea = Common::Rect(0, 0, 0, 0)); void setFgColor(uint8 r, uint8 g, uint8 b) { _fgColor = _format.RGBToColor(r, g, b); } void setBgColor(uint8 r, uint8 g, uint8 b) { _bgColor = _format.RGBToColor(r, g, b); } @@ -158,6 +158,12 @@ protected: virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, FillMode fill_m); + virtual void drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, + PixelType color, FillMode fill_m, uint8 alpha_t, uint8 alpha_r, uint8 alpha_b, uint8 alpha_l); + + virtual void drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, + PixelType color, FillMode fill_m); + virtual void drawSquareAlg(int x, int y, int w, int h, PixelType color, FillMode fill_m); @@ -174,6 +180,8 @@ protected: PixelType color, VectorRenderer::FillMode fill_m, int baseLeft = 0, int baseRight = 0); + virtual void drawTabShadow(int x, int y, int w, int h, int r); + virtual void drawBevelTabAlg(int x, int y, int w, int h, int bevel, PixelType topColor, PixelType bottomColor, int baseLeft = 0, int baseRight = 0); @@ -186,10 +194,10 @@ protected: * There functions may be overloaded in inheriting classes to improve performance * in the slowest platforms where pixel alpha blending just doesn't cut it. * - * @param blur Intensity/size of the shadow. + * @param offset Intensity/size of the shadow. */ - virtual void drawSquareShadow(int x, int y, int w, int h, int blur); - virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur); + virtual void drawSquareShadow(int x, int y, int w, int h, int offset); + virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset); /** * Calculates the color gradient on a given point. @@ -292,10 +300,12 @@ protected: */ virtual void drawRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m); - virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int blur) { - Base::drawRoundedSquareShadow(x, y, r, w, h, blur); -// VectorRenderer::applyConvolutionMatrix(VectorRenderer::kConvolutionHardBlur, -// Common::Rect(x, y, x + w + blur * 2, y + h + blur * 2)); + virtual void drawBorderRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m, uint8 alpha_t, uint8 alpha_l, uint8 alpha_r, uint8 alpha_b); + + virtual void drawInteriorRoundedSquareAlg(int x1, int y1, int r, int w, int h, PixelType color, VectorRenderer::FillMode fill_m); + + virtual void drawRoundedSquareShadow(int x, int y, int r, int w, int h, int offset) { + Base::drawRoundedSquareShadow(x, y, r, w, h, offset); } virtual void drawTabAlg(int x, int y, int w, int h, int r, diff --git a/graphics/font.cpp b/graphics/font.cpp index 3b00cd8568..a852274b06 100644 --- a/graphics/font.cpp +++ b/graphics/font.cpp @@ -128,7 +128,7 @@ void Font::drawString(Surface *dst, const Common::String &sOld, int x, int y, in w = getCharWidth(cur); if (x+w > rightX) break; - if (x >= leftX) + if (x+w >= leftX) drawChar(dst, str[i], x, y, color); x += w; } diff --git a/gui/ThemeEngine.cpp b/gui/ThemeEngine.cpp index 2abf4a545d..688654d208 100644 --- a/gui/ThemeEngine.cpp +++ b/gui/ThemeEngine.cpp @@ -122,15 +122,16 @@ protected: class ThemeItemTextData : public ThemeItem { public: - ThemeItemTextData(ThemeEngine *engine, const TextDrawData *data, const TextColorData *color, const Common::Rect &area, const Common::String &text, - Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV, + ThemeItemTextData(ThemeEngine *engine, const TextDrawData *data, const TextColorData *color, const Common::Rect &area, const Common::Rect &textDrawableArea, + const Common::String &text, Graphics::TextAlign alignH, GUI::ThemeEngine::TextAlignVertical alignV, bool ellipsis, bool restoreBg, int deltaX) : ThemeItem(engine, area), _data(data), _color(color), _text(text), _alignH(alignH), _alignV(alignV), - _ellipsis(ellipsis), _restoreBg(restoreBg), _deltax(deltaX) {} + _ellipsis(ellipsis), _restoreBg(restoreBg), _deltax(deltaX), _textDrawableArea(textDrawableArea) {} void drawSelf(bool draw, bool restore); protected: + Common::Rect _textDrawableArea; const TextDrawData *_data; const TextColorData *_color; Common::String _text; @@ -246,7 +247,7 @@ void ThemeItemTextData::drawSelf(bool draw, bool restore) { if (draw) { _engine->renderer()->setFgColor(_color->r, _color->g, _color->b); - _engine->renderer()->drawString(_data->_fontPtr, _text, _area, _alignH, _alignV, _deltax, _ellipsis); + _engine->renderer()->drawString(_data->_fontPtr, _text, _area, _alignH, _alignV, _deltax, _ellipsis, _textDrawableArea); } _engine->addDirtyRect(_area); @@ -842,7 +843,7 @@ void ThemeEngine::queueDD(DrawData type, const Common::Rect &r, uint32 dynamic, } void ThemeEngine::queueDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg, - bool ellipsis, Graphics::TextAlign alignH, TextAlignVertical alignV, int deltax) { + bool ellipsis, Graphics::TextAlign alignH, TextAlignVertical alignV, int deltax, const Common::Rect &drawableTextArea) { if (_texts[type] == 0) return; @@ -850,7 +851,7 @@ void ThemeEngine::queueDDText(TextData type, TextColor color, const Common::Rect Common::Rect area = r; area.clip(_screen.w, _screen.h); - ThemeItemTextData *q = new ThemeItemTextData(this, _texts[type], _textColors[color], area, text, alignH, alignV, ellipsis, restoreBg, deltax); + ThemeItemTextData *q = new ThemeItemTextData(this, _texts[type], _textColors[color], area, drawableTextArea, text, alignH, alignV, ellipsis, restoreBg, deltax); if (_buffering) { _screenQueue.push_back(q); @@ -1121,7 +1122,7 @@ void ThemeEngine::drawTab(const Common::Rect &r, int tabHeight, int tabWidth, co } } -void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore) { +void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state, Graphics::TextAlign align, TextInversionState inverted, int deltax, bool useEllipsis, FontStyle font, FontColor color, bool restore, const Common::Rect &drawableTextArea) { if (!ready()) return; @@ -1191,7 +1192,7 @@ void ThemeEngine::drawText(const Common::Rect &r, const Common::String &str, Wid break; } - queueDDText(textId, colorId, r, str, restore, useEllipsis, align, kTextAlignVCenter, deltax); + queueDDText(textId, colorId, r, str, restore, useEllipsis, align, kTextAlignVCenter, deltax, drawableTextArea); } void ThemeEngine::drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state, FontColor color) { diff --git a/gui/ThemeEngine.h b/gui/ThemeEngine.h index c0e47a19e6..4dffb13e71 100644 --- a/gui/ThemeEngine.h +++ b/gui/ThemeEngine.h @@ -29,6 +29,7 @@ #include "common/hashmap.h" #include "common/list.h" #include "common/str.h" +#include "common/rect.h" #include "graphics/surface.h" #include "graphics/font.h" @@ -39,10 +40,6 @@ class OSystem; -namespace Common { -struct Rect; -} - namespace Graphics { struct DrawStep; class VectorRenderer; @@ -376,7 +373,7 @@ public: void drawDialogBackground(const Common::Rect &r, DialogBackground type, WidgetStateInfo state = kStateEnabled); - void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true); + void drawText(const Common::Rect &r, const Common::String &str, WidgetStateInfo state = kStateEnabled, Graphics::TextAlign align = Graphics::kTextAlignCenter, TextInversionState inverted = kTextInversionNone, int deltax = 0, bool useEllipsis = true, FontStyle font = kFontStyleBold, FontColor color = kFontColorNormal, bool restore = true, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0)); void drawChar(const Common::Rect &r, byte ch, const Graphics::Font *font, WidgetStateInfo state = kStateEnabled, FontColor color = kFontColorNormal); @@ -588,7 +585,7 @@ protected: */ void queueDD(DrawData type, const Common::Rect &r, uint32 dynamic = 0, bool restore = false); void queueDDText(TextData type, TextColor color, const Common::Rect &r, const Common::String &text, bool restoreBg, - bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0); + bool elipsis, Graphics::TextAlign alignH = Graphics::kTextAlignLeft, TextAlignVertical alignV = kTextAlignVTop, int deltax = 0, const Common::Rect &drawableTextArea = Common::Rect(0, 0, 0, 0)); void queueBitmap(const Graphics::Surface *bitmap, const Common::Rect &r, bool alpha); /** diff --git a/gui/about.cpp b/gui/about.cpp index 20145886c6..3bb1934e28 100644 --- a/gui/about.cpp +++ b/gui/about.cpp @@ -180,9 +180,10 @@ void AboutDialog::close() { } void AboutDialog::drawDialog() { -// g_gui.theme()->setDrawArea(Common::Rect(_x, _y, _x+_w, _y+_h)); Dialog::drawDialog(); + setTextDrawableArea(Common::Rect(_x, _y, _x + _w, _y + _h)); + // Draw text // TODO: Add a "fade" effect for the top/bottom text lines // TODO: Maybe prerender all of the text into another surface, @@ -239,8 +240,8 @@ void AboutDialog::drawDialog() { while (*str && *str == ' ') str++; - if (*str && y > _y && y + g_gui.theme()->getFontHeight() < _y + _h) - g_gui.theme()->drawText(Common::Rect(_x + _xOff, y, _x + _w - _xOff, y + g_gui.theme()->getFontHeight()), str, state, align, ThemeEngine::kTextInversionNone, 0, false); + if (*str) + g_gui.theme()->drawText(Common::Rect(_x + _xOff, y, _x + _w - _xOff, y + g_gui.theme()->getFontHeight()), str, state, align, ThemeEngine::kTextInversionNone, 0, false, ThemeEngine::kFontStyleBold, ThemeEngine::kFontColorNormal, true, _textDrawableArea); y += _lineHeight; } } diff --git a/gui/object.cpp b/gui/object.cpp index 73c4f74d6c..189a286ead 100644 --- a/gui/object.cpp +++ b/gui/object.cpp @@ -29,7 +29,7 @@ namespace GUI { GuiObject::GuiObject(const Common::String &name) - : _x(-1000), _y(-1000), _w(0), _h(0), _name(name), _firstWidget(0) { + : _x(-1000), _y(-1000), _w(0), _h(0), _name(name), _firstWidget(0), _textDrawableArea(Common::Rect(0, 0, 0, 0)) { reflowLayout(); } diff --git a/gui/object.h b/gui/object.h index bce3cd7846..dac3341b5a 100644 --- a/gui/object.h +++ b/gui/object.h @@ -24,6 +24,7 @@ #include "common/scummsys.h" #include "common/str.h" +#include "common/rect.h" namespace GUI { @@ -59,6 +60,8 @@ class Widget; class GuiObject : public CommandReceiver { friend class Widget; protected: + Common::Rect _textDrawableArea; + int16 _x, _y; uint16 _w, _h; const Common::String _name; @@ -66,10 +69,12 @@ protected: Widget *_firstWidget; public: - GuiObject(int x, int y, int w, int h) : _x(x), _y(y), _w(w), _h(h), _firstWidget(0) { } + GuiObject(int x, int y, int w, int h) : _x(x), _y(y), _w(w), _h(h), _firstWidget(0), _textDrawableArea(Common::Rect(0, 0, 0, 0)) { } GuiObject(const Common::String &name); ~GuiObject(); + virtual void setTextDrawableArea(const Common::Rect &r) { _textDrawableArea = r; } + virtual int16 getAbsX() const { return _x; } virtual int16 getAbsY() const { return _y; } virtual int16 getChildX() const { return getAbsX(); } diff --git a/gui/themes/scummclassic.zip b/gui/themes/scummclassic.zip Binary files differindex 4154c6c33a..1085aa64a4 100644 --- a/gui/themes/scummclassic.zip +++ b/gui/themes/scummclassic.zip diff --git a/gui/themes/scummmodern.zip b/gui/themes/scummmodern.zip Binary files differindex 0f10003e94..e40e8b1e26 100644 --- a/gui/themes/scummmodern.zip +++ b/gui/themes/scummmodern.zip diff --git a/gui/themes/scummmodern/scummmodern_gfx.stx b/gui/themes/scummmodern/scummmodern_gfx.stx index 1b3bcea0d6..3a1ec5a5f0 100644 --- a/gui/themes/scummmodern/scummmodern_gfx.stx +++ b/gui/themes/scummmodern/scummmodern_gfx.stx @@ -38,6 +38,14 @@ rgb = '203, 126, 107' /> + <color name = 'brightredborder' + rgb = '238, 213, 207' + /> + + <color name = 'darkredborder' + rgb = '30, 7, 1' + /> + <!-- Disabled button/slider --> <color name = 'darkeneddarkred' rgb = '120, 28, 0' @@ -73,7 +81,7 @@ rgb = '255, 255, 255' /> <color name = 'shadowcolor' - rgb = '63, 60, 17' + rgb = '105, 101, 86' /> <color name = 'darkgray' rgb = '176, 168, 144' @@ -170,6 +178,10 @@ color = '128, 128, 128' /> + <text_color id = 'color_button_hover' + color = 'white' + /> + <text_color id = 'color_alternative_inverted' color = 'white' /> @@ -186,10 +198,6 @@ color = 'white' /> - <text_color id = 'color_button_hover' - color = '255, 214, 84' - /> - <text_color id = 'color_button_disabled' color = '192, 192, 192' /> @@ -232,7 +240,7 @@ stroke = '0' gradient_start = 'darkorange' gradient_end = 'brightorange' - shadow = '3' + shadow = '7' gradient_factor = '3' /> </drawdata> @@ -466,7 +474,7 @@ fg_color = 'lightgray2' fill = 'background' bg_color = 'xtrabrightred' - shadow = '2' + shadow = '1' /> <drawstep func = 'triangle' @@ -505,7 +513,7 @@ fg_color = 'lightgray2' fill = 'background' bg_color = 'xtrabrightred' - shadow = '2' + shadow = '1' /> <drawstep func = 'triangle' @@ -663,7 +671,7 @@ fg_color = 'lightgray2' fill = 'background' bg_color = 'xtrabrightred' - shadow = '2' + shadow = '1' /> <drawstep func = 'triangle' @@ -716,7 +724,7 @@ gradient_start = 'blandyellow' gradient_end = 'xtrabrightred' fill = 'gradient' - shadow = '3' + shadow = '7' /> </drawdata> @@ -737,7 +745,7 @@ gradient_start = 'blandyellow' gradient_end = 'xtrabrightred' gradient_factor = '4' - shadow = '3' + shadow = '7' /> </drawdata> @@ -783,18 +791,18 @@ stroke = '1' fill = 'gradient' shadow = '0' - fg_color = 'shadowcolor' + fg_color = 'darkredborder' gradient_start = 'brightred' gradient_end = 'darkred' bevel = '1' - bevel_color = '237, 169, 72' + bevel_color = 'brightredborder' /> </drawdata> <!-- Hovered button --> <drawdata id = 'button_hover' cache = 'false'> <text font = 'text_button' - text_color = 'color_button_hover' + text_color = 'color_button' vertical_align = 'center' horizontal_align = 'center' /> @@ -803,11 +811,11 @@ stroke = '1' fill = 'gradient' shadow = '0' - fg_color = 'shadowcolor' + fg_color = 'darkredborder' gradient_start = 'brightpink' gradient_end = 'darkpink' bevel = '1' - bevel_color = 'xtrabrightred' + bevel_color = 'brightredborder' /> </drawdata> @@ -915,7 +923,7 @@ gradient_factor = '6' fill = 'gradient' bg_color = 'xtrabrightred' - shadow = '3' + shadow = '7' /> </drawdata> diff --git a/gui/widgets/editable.cpp b/gui/widgets/editable.cpp index 6fae9346b2..667850d6cc 100644 --- a/gui/widgets/editable.cpp +++ b/gui/widgets/editable.cpp @@ -277,7 +277,7 @@ void EditableWidget::drawCaret(bool erase) { int chrWidth = g_gui.getCharWidth(_editString[_caretPos], _font); const uint last = (_caretPos > 0) ? _editString[_caretPos - 1] : 0; x += g_gui.getKerningOffset(last, _editString[_caretPos], _font); - g_gui.theme()->drawText(Common::Rect(x, y, x + chrWidth, y + editRect.height() - 2), chr, _state, Graphics::kTextAlignLeft, _inversion, 0, false, _font); + g_gui.theme()->drawText(Common::Rect(x, y, x + chrWidth, y + editRect.height() - 2), chr, _state, Graphics::kTextAlignLeft, _inversion, 0, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea); } } diff --git a/gui/widgets/edittext.cpp b/gui/widgets/edittext.cpp index 3677f02e47..52527effd8 100644 --- a/gui/widgets/edittext.cpp +++ b/gui/widgets/edittext.cpp @@ -93,11 +93,15 @@ void EditTextWidget::drawWidget() { // Draw the text adjustOffset(); - g_gui.theme()->drawText(Common::Rect(_x+2+ _leftPadding,_y+2, _x+_leftPadding+getEditRect().width()+2, _y+_h-2), _editString, _state, Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, -_editScrollOffset, false, _font); + + const Common::Rect &r = Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 8, _y + _h); + setTextDrawableArea(r); + + g_gui.theme()->drawText(Common::Rect(_x + 2 + _leftPadding, _y + 2, _x + _leftPadding + getEditRect().width() + 2, _y + _h), _editString, _state, Graphics::kTextAlignLeft, ThemeEngine::kTextInversionNone, -_editScrollOffset, false, _font, ThemeEngine::kFontColorNormal, true, _textDrawableArea); } Common::Rect EditTextWidget::getEditRect() const { - Common::Rect r(2 + _leftPadding, 2, _w - 2 - _leftPadding - _rightPadding, _h-1); + Common::Rect r(2 + _leftPadding, 2, _w - 2 - _leftPadding - _rightPadding, _h - 1); return r; } |