vcl/headless/CairoCommon.cxx | 5 ++-- vcl/qa/cppunit/outdev.cxx | 53 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+), 2 deletions(-)
New commits: commit 99d7bbf367eeb85055853d0d03ec46b2d6bbebe3 Author: Noel Grandin <[email protected]> AuthorDate: Thu Oct 16 11:01:47 2025 +0200 Commit: Noel Grandin <[email protected]> CommitDate: Sat Oct 18 08:37:12 2025 +0200 tdf#168730 fix DrawRect with alpha Where we were merging the fill color with the background instead of overwriting it. regression from commit 088a7c7c451321a800ca8d3523a18b6bb93239b7 Author: Noel Grandin <[email protected]> Date: Tue Sep 24 16:18:11 2024 +0200 remove alpha device from OutputDevice And add some unit tests for this and for DrawPolyPolygon. Verified both the new unit tests on a build from before the regression commit. Change-Id: Ia27e075d8be71fd35a2d6ef6b08e8f42b36a7776 Reviewed-on: https://gerrit.libreoffice.org/c/core/+/192482 Tested-by: Jenkins Reviewed-by: Noel Grandin <[email protected]> diff --git a/vcl/headless/CairoCommon.cxx b/vcl/headless/CairoCommon.cxx index a9bdff539014..b2a6b13d31f8 100644 --- a/vcl/headless/CairoCommon.cxx +++ b/vcl/headless/CairoCommon.cxx @@ -629,6 +629,7 @@ cairo_t* CairoCommon::createTmpCompatibleCairoContext() const void CairoCommon::applyColor(cairo_t* cr, Color aColor, double fTransparency) { + cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); if (cairo_surface_get_content(cairo_get_target(cr)) != CAIRO_CONTENT_ALPHA) { cairo_set_source_rgba(cr, aColor.GetRed() / 255.0, aColor.GetGreen() / 255.0, @@ -638,7 +639,6 @@ void CairoCommon::applyColor(cairo_t* cr, Color aColor, double fTransparency) { double fSet = aColor == COL_BLACK ? 1.0 : 0.0; cairo_set_source_rgba(cr, 1, 1, 1, fSet); - cairo_set_operator(cr, CAIRO_OPERATOR_SOURCE); } } @@ -880,7 +880,8 @@ void CairoCommon::drawRect(double nX, double nY, double nWidth, double nHeight, basegfx::B2DRectangle(nX, nY, nX + nWidth, nY + nHeight)); m_oFillColor = aOrigFillColor; - drawPolyPolygon(basegfx::B2DHomMatrix(), basegfx::B2DPolyPolygon(aRect), 0.0, bAntiAlias); + drawPolyPolygon(basegfx::B2DHomMatrix(), basegfx::B2DPolyPolygon(aRect), + (255 - aOrigFillColor->GetAlpha()) / 255.0, bAntiAlias); m_oFillColor = std::nullopt; } diff --git a/vcl/qa/cppunit/outdev.cxx b/vcl/qa/cppunit/outdev.cxx index 1f1652174580..45a2a100e70a 100644 --- a/vcl/qa/cppunit/outdev.cxx +++ b/vcl/qa/cppunit/outdev.cxx @@ -1847,6 +1847,59 @@ CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawPolyPolygon) } } +// Test and document existing behaviour +CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawPolyPolygonAlpha) +{ + Size aSize(100, 100); + ScopedVclPtrInstance<VirtualDevice> pVDev(DeviceFormat::WITH_ALPHA); + pVDev->SetOutputSizePixel(aSize); + + // create a square polypolygon + tools::Polygon aPolygon(4); + aPolygon.SetPoint(Point(0, 0), 0); + aPolygon.SetPoint(Point(0, 100), 1); + aPolygon.SetPoint(Point(100, 100), 2); + aPolygon.SetPoint(Point(0, 0), 3); + tools::PolyPolygon aPolyPolygon(aPolygon); + aPolyPolygon.Optimize(PolyOptimizeFlags::CLOSE); + basegfx::B2DPolyPolygon aB2DPolyPolygon(aPolyPolygon.getB2DPolyPolygon()); + + Color aLineColor(ColorAlpha, 255, 255, 0, 0); // opaque red + Color aFillColor(ColorAlpha, 127, 255, 0, 0); // 50% transparent red + pVDev->SetLineColor(aLineColor); + pVDev->SetFillColor(aFillColor); + pVDev->DrawPolyPolygon(aB2DPolyPolygon); + + CPPUNIT_ASSERT_EQUAL(aLineColor, pVDev->GetPixel(Point(0, 0))); + // existing behaviour - we drop the alpha when we fill a polypolygon + CPPUNIT_ASSERT_EQUAL(Color(ColorAlpha, 255, 255, 0, 0), pVDev->GetPixel(Point(1, 1))); +} + +// Test and document existing behaviour +CPPUNIT_TEST_FIXTURE(VclOutdevTest, testDrawRectAlpha) +{ + Size aSize(100, 100); + ScopedVclPtrInstance<VirtualDevice> pVDev(DeviceFormat::WITH_ALPHA); + pVDev->SetOutputSizePixel(aSize); + + const Color RED_OPAQUE(ColorAlpha, 255, 255, 0, 0); // opaque red + const Color RED_TRANSPARENT(ColorAlpha, 127, 255, 0, 0); // 50% transparent red + pVDev->SetLineColor(RED_OPAQUE); + pVDev->SetFillColor(RED_TRANSPARENT); + pVDev->DrawRect(tools::Rectangle(0, 0, 100, 100)); + + CPPUNIT_ASSERT_EQUAL(RED_OPAQUE, pVDev->GetPixel(Point(0, 0))); + CPPUNIT_ASSERT_EQUAL(RED_TRANSPARENT, pVDev->GetPixel(Point(1, 1))); + + pVDev->SetLineColor(RED_TRANSPARENT); + pVDev->SetFillColor(RED_OPAQUE); + pVDev->DrawRect(tools::Rectangle(0, 0, 100, 100)); + + // existing behaviour - we drop the alpha when we draw the line for a rect + CPPUNIT_ASSERT_EQUAL(RED_OPAQUE, pVDev->GetPixel(Point(0, 0))); + CPPUNIT_ASSERT_EQUAL(RED_OPAQUE, pVDev->GetPixel(Point(1, 1))); +} + static size_t ClipGradientTest(GDIMetaFile& rMtf, size_t nIndex) { MetaAction* pAction = rMtf.GetAction(nIndex);
