From 216fca2d218c3e0dcb5cdb4273cfb609da06cbd2 Mon Sep 17 00:00:00 2001 From: Neil Date: Fri, 19 Mar 2021 21:03:17 +1100 Subject: Support strokeWidth and float cornerSize in AlphaRectangle. Use FillStroke instead of separate colour and alpha arguments. --- win32/PlatWin.cxx | 87 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 87 insertions(+) (limited to 'win32/PlatWin.cxx') diff --git a/win32/PlatWin.cxx b/win32/PlatWin.cxx index 3fae8e90f..ae819bb69 100644 --- a/win32/PlatWin.cxx +++ b/win32/PlatWin.cxx @@ -494,6 +494,7 @@ public: void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back) override; void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill, ColourDesired outline, int alphaOutline, int flags) override; + void AlphaRectangle(PRectangle rc, XYPOSITION cornerSize, FillStroke fillStroke) override; void GradientRectangle(PRectangle rc, const std::vector &stops, GradientOptions options) override; void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) override; void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back) override; @@ -908,6 +909,55 @@ void SurfaceGDI::AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fil } } +void SurfaceGDI::AlphaRectangle(PRectangle rc, XYPOSITION cornerSize, FillStroke fillStroke) { + // TODO: Implement strokeWidth + const RECT rcw = RectFromPRectangle(rc); + const SIZE size = SizeOfRect(rcw); + + if (size.cx > 0) { + + DIBSection section(hdc, size); + + if (section) { + + // Ensure not distorted too much by corners when small + const LONG corner = std::min(static_cast(cornerSize), (std::min(size.cx, size.cy) / 2) - 2); + + constexpr DWORD valEmpty = dwordFromBGRA(0,0,0,0); + const DWORD valFill = dwordMultiplied(fillStroke.fill.colour, fillStroke.fill.colour.GetAlpha()); + const DWORD valOutline = dwordMultiplied(fillStroke.stroke.colour, fillStroke.stroke.colour.GetAlpha()); + + // Draw a framed rectangle + for (int y=0; y &stops, GradientOptions options) { const RECT rcw = RectFromPRectangle(rc); @@ -1242,6 +1292,14 @@ constexpr D2D_COLOR_F ColorFromColourAlpha(ColourAlpha colour) noexcept { }; } +constexpr D2D1_RECT_F RectangleInset(D2D1_RECT_F rect, FLOAT inset) noexcept { + return D2D1_RECT_F{ + rect.left + inset, + rect.top + inset, + rect.right - inset, + rect.bottom - inset }; +} + } class BlobInline; @@ -1305,6 +1363,7 @@ public: void RoundedRectangle(PRectangle rc, ColourDesired fore, ColourDesired back) override; void AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fill, int alphaFill, ColourDesired outline, int alphaOutline, int flags) override; + void AlphaRectangle(PRectangle rc, XYPOSITION cornerSize, FillStroke fillStroke) override; void GradientRectangle(PRectangle rc, const std::vector &stops, GradientOptions options) override; void DrawRGBAImage(PRectangle rc, int width, int height, const unsigned char *pixelsImage) override; void Ellipse(PRectangle rc, ColourDesired fore, ColourDesired back) override; @@ -1673,6 +1732,34 @@ void SurfaceD2D::AlphaRectangle(PRectangle rc, int cornerSize, ColourDesired fil } } +void SurfaceD2D::AlphaRectangle(PRectangle rc, XYPOSITION cornerSize, FillStroke fillStroke) { + const D2D1_RECT_F rect = RectangleFromPRectangle(rc); + const D2D1_RECT_F rectFill = RectangleInset(rect, fillStroke.stroke.width); + const float halfStroke = fillStroke.stroke.width / 2.0f; + const D2D1_RECT_F rectOutline = RectangleInset(rect, halfStroke); + if (pRenderTarget) { + if (cornerSize == 0) { + // When corner size is zero, draw square rectangle to prevent blurry pixels at corners + D2DPenColourAlpha(fillStroke.fill.colour); + pRenderTarget->FillRectangle(rectFill, pBrush); + + D2DPenColourAlpha(fillStroke.stroke.colour); + pRenderTarget->DrawRectangle(rectOutline, pBrush, fillStroke.stroke.width); + } else { + const float cornerSizeF = static_cast(cornerSize); + D2D1_ROUNDED_RECT roundedRectFill = { + rectFill, cornerSizeF - 1.0f, cornerSizeF - 1.0f }; + D2DPenColourAlpha(fillStroke.fill.colour); + pRenderTarget->FillRoundedRectangle(roundedRectFill, pBrush); + + D2D1_ROUNDED_RECT roundedRect = { + rectOutline, cornerSizeF, cornerSizeF}; + D2DPenColourAlpha(fillStroke.stroke.colour); + pRenderTarget->DrawRoundedRectangle(roundedRect, pBrush, fillStroke.stroke.width); + } + } +} + void SurfaceD2D::GradientRectangle(PRectangle rc, const std::vector &stops, GradientOptions options) { if (pRenderTarget) { D2D1_LINEAR_GRADIENT_BRUSH_PROPERTIES lgbp { -- cgit v1.2.3