[Libreoffice-commits] core.git: vcl/qa vcl/skia

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Wed Sep 2 10:44:12 UTC 2020


 vcl/qa/cppunit/BackendTest.cxx |   26 ++++++++++++++++++++++++++
 vcl/skia/salbmp.cxx            |   19 +++++++++++++++----
 2 files changed, 41 insertions(+), 4 deletions(-)

New commits:
commit 2e3111838b7fc27065138850cafbb0f0e606d6f3
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Tue Sep 1 21:59:50 2020 +0200
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Wed Sep 2 12:43:25 2020 +0200

    handle properly cleared bitmap used as alpha for Skia (tdf#136171)
    
    Change-Id: I2c9e5d58247d5fd85aac539728fa857462785090
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/101895
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lunak at collabora.com>

diff --git a/vcl/qa/cppunit/BackendTest.cxx b/vcl/qa/cppunit/BackendTest.cxx
index 7a9cf89fceaf..45793434dd1b 100644
--- a/vcl/qa/cppunit/BackendTest.cxx
+++ b/vcl/qa/cppunit/BackendTest.cxx
@@ -549,6 +549,31 @@ public:
         CPPUNIT_ASSERT_EQUAL(COL_WHITE, device->GetPixel(Point(51, 20)));
     }
 
+    void testTdf136171()
+    {
+        // Create virtual device with alpha.
+        ScopedVclPtr<VirtualDevice> device
+            = VclPtr<VirtualDevice>::Create(DeviceFormat::DEFAULT, DeviceFormat::DEFAULT);
+        device->SetOutputSizePixel(Size(10, 10));
+        device->SetBackground(Wallpaper(COL_WHITE));
+        device->Erase();
+        Bitmap bitmap(Size(10, 10), 24);
+        bitmap.Erase(COL_BLUE);
+        basegfx::B2DHomMatrix matrix;
+        matrix.scale(bitmap.GetSizePixel().Width(),
+                     bitmap.GetSizePixel().Height()); // draw as 10x10
+        // Draw a blue bitmap to the device. The bug was that there was no alpha, but OutputDevice::DrawTransformBitmapExDirect()
+        // supplied a fully opaque alpha done with Erase() on the alpha bitmap, and Skia backend didn't handle such alpha correctly.
+        device->DrawTransformedBitmapEx(matrix, BitmapEx(bitmap));
+        exportDevice("/tmp/tdf136171.png", device);
+        // The whole virtual device content now should be blue.
+        CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(0, 0)));
+        CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(9, 0)));
+        CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(0, 9)));
+        CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(9, 9)));
+        CPPUNIT_ASSERT_EQUAL(COL_BLUE, device->GetPixel(Point(4, 4)));
+    }
+
     CPPUNIT_TEST_SUITE(BackendTest);
     CPPUNIT_TEST(testDrawRectWithRectangle);
     CPPUNIT_TEST(testDrawRectWithPixel);
@@ -602,6 +627,7 @@ public:
     CPPUNIT_TEST(testDashedLine);
 
     CPPUNIT_TEST(testTdf124848);
+    CPPUNIT_TEST(testTdf136171);
 
     CPPUNIT_TEST_SUITE_END();
 };
diff --git a/vcl/skia/salbmp.cxx b/vcl/skia/salbmp.cxx
index 0da11b1c57d8..378f5557de4e 100644
--- a/vcl/skia/salbmp.cxx
+++ b/vcl/skia/salbmp.cxx
@@ -565,6 +565,17 @@ static SkColor toSkColor(Color color)
                           color.GetBlue());
 }
 
+// If mEraseColor is set, this is the color to use when the bitmap is used as alpha bitmap.
+// E.g. COL_BLACK actually means fully opaque and COL_WHITE means fully transparent.
+// This is because the alpha value is set as the color itself, not the alpha of the color.
+// Additionally VCL actually uses transparency and not opacity, so we should use "255 - value",
+// but we account for this by doing SkBlendMode::kDstOut when using alpha images (which
+// basically does another "255 - alpha"), so do not do it here.
+static SkColor fromEraseColorToAlphaImageColor(Color color)
+{
+    return SkColorSetARGB(color.GetBlue(), 0, 0, 0);
+}
+
 const sk_sp<SkImage>& SkiaSalBitmap::GetSkImage() const
 {
 #ifdef DBG_UTIL
@@ -655,7 +666,7 @@ const sk_sp<SkImage>& SkiaSalBitmap::GetAlphaSkImage() const
         SkiaZone zone;
         sk_sp<SkSurface> surface = SkiaHelper::createSkSurface(mSize, kAlpha_8_SkColorType);
         assert(surface);
-        surface->getCanvas()->clear(SkColorSetARGB(255 - mEraseColor.GetBlue(), 0, 0, 0));
+        surface->getCanvas()->clear(fromEraseColorToAlphaImageColor(mEraseColor));
         SkiaSalBitmap* thisPtr = const_cast<SkiaSalBitmap*>(this);
         thisPtr->mAlphaImage = surface->makeImageSnapshot();
         SAL_INFO("vcl.skia.trace",
@@ -758,7 +769,7 @@ sk_sp<SkShader> SkiaSalBitmap::GetSkShader() const
 sk_sp<SkShader> SkiaSalBitmap::GetAlphaSkShader() const
 {
     if (mEraseColorSet)
-        return SkShaders::Color(toSkColor(mEraseColor));
+        return SkShaders::Color(fromEraseColorToAlphaImageColor(mEraseColor));
     return GetAlphaSkImage()->makeShader();
 }
 
@@ -999,8 +1010,8 @@ OString SkiaSalBitmap::GetAlphaImageKey() const
     if (mEraseColorSet)
     {
         std::stringstream ss;
-        ss << std::hex << std::setfill('0') << std::setw(2) << (255 - mEraseColor.GetTransparency())
-           << std::setw(6) << sal_uInt32(mEraseColor.GetRGBColor());
+        ss << std::hex << std::setfill('0') << std::setw(2)
+           << (255 - SkColorGetA(fromEraseColorToAlphaImageColor(mEraseColor)));
         return OStringLiteral("E") + ss.str().c_str();
     }
     return OStringLiteral("I") + OString::number(GetAlphaSkImage()->uniqueID());


More information about the Libreoffice-commits mailing list