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.lu...@collabora.com>
AuthorDate: Tue Sep 1 21:59:50 2020 +0200
Commit:     Luboš Luňák <l.lu...@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.lu...@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());
_______________________________________________
Libreoffice-commits mailing list
libreoffice-comm...@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits

Reply via email to