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

Luboš Luňák (via logerrit) logerrit at kemper.freedesktop.org
Sun Jan 12 15:49:03 UTC 2020


 vcl/inc/skia/win/gdiimpl.hxx |    3 -
 vcl/skia/win/gdiimpl.cxx     |   69 +++++++++----------------------------------
 2 files changed, 17 insertions(+), 55 deletions(-)

New commits:
commit 202146901b6fbab923042d30f62b19992bf5179b
Author:     Luboš Luňák <l.lunak at collabora.com>
AuthorDate: Fri Jan 10 19:05:20 2020 +0100
Commit:     Luboš Luňák <l.lunak at collabora.com>
CommitDate: Sun Jan 12 16:48:28 2020 +0100

    finally fix Skia Windows widget drawing (tdf#129416)
    
    So much time wasted just because c6b66646870cb2bf couldn't be bothered
    spending a minute or two explaining the weird black/white alpha hack
    that it turns out is not even necessary as the resulting image
    is incidentally in the premultiplied alpha format.
    
    Change-Id: I810458a670b2c0c8047118f55f58bf588a37f9f1
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86569
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lunak at collabora.com>

diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx
index dabd56ad04a3..daf41e8e06d0 100644
--- a/vcl/inc/skia/win/gdiimpl.hxx
+++ b/vcl/inc/skia/win/gdiimpl.hxx
@@ -31,9 +31,8 @@ public:
 
     virtual bool wantsTextColorWhite() const override { return true; }
 
-    sk_sp<SkImage> getAsImage() const;
+    sk_sp<SkImage> getAsImage(bool fromPremultiplied = false) const;
     sk_sp<SkImage> getAsMaskImage() const;
-    sk_sp<SkImage> getAsImageDiff(const SkiaCompatibleDC& other) const;
 
     struct Texture;
 };
diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx
index b3f538bcea5b..437e7c7d1e3f 100644
--- a/vcl/skia/win/gdiimpl.cxx
+++ b/vcl/skia/win/gdiimpl.cxx
@@ -97,15 +97,21 @@ bool WinSkiaSalGraphicsImpl::TryRenderCachedNativeControl(ControlCacheKey const&
     return true;
 }
 
-bool WinSkiaSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& rWhite, CompatibleDC& rBlack,
-                                                         int nX, int nY,
+bool WinSkiaSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& /*rWhite*/,
+                                                         CompatibleDC& rBlack, int nX, int nY,
                                                          ControlCacheKey& aControlCacheKey)
 {
-    assert(dynamic_cast<SkiaCompatibleDC*>(&rWhite));
+    // assert(dynamic_cast<SkiaCompatibleDC*>(&rWhite));
     assert(dynamic_cast<SkiaCompatibleDC*>(&rBlack));
 
-    sk_sp<SkImage> image = static_cast<SkiaCompatibleDC&>(rWhite).getAsImageDiff(
-        static_cast<SkiaCompatibleDC&>(rBlack));
+    // Native widgets are drawn twice on black/white background, which comes from an OpenGL
+    // commit c6b66646870cb2bffaa73565affcf80bf74e0b5c, where it is used to synthetize alpha.
+    // But getting the Windows theming API to draw into an empty area (fully transparent)
+    // actually results in the widget being in the premultiplied alpha format (and I have no
+    // idea why the OpenGL code uses the weird undocumented pixel diffing it does, probably
+    // the author did not realize this). Simply use the black variant as premultiplied data.
+    // TODO Remove the white variant completely once OpenGL code is removed.
+    sk_sp<SkImage> image = static_cast<SkiaCompatibleDC&>(rBlack).getAsImage(true);
     preDraw();
     mSurface->getCanvas()->drawImage(image, nX, nY);
     postDraw();
@@ -207,12 +213,13 @@ sk_sp<SkImage> SkiaCompatibleDC::getAsMaskImage() const
     return surface->makeImageSnapshot();
 }
 
-sk_sp<SkImage> SkiaCompatibleDC::getAsImage() const
+sk_sp<SkImage> SkiaCompatibleDC::getAsImage(bool fromPremultiplied) const
 {
     SkBitmap tmpBitmap;
-    if (!tmpBitmap.installPixels(SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight,
-                                                   kBGRA_8888_SkColorType, kUnpremul_SkAlphaType),
-                                 mpData, maRects.mnSrcWidth * 4))
+    if (!tmpBitmap.installPixels(
+            SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight, kBGRA_8888_SkColorType,
+                              fromPremultiplied ? kPremul_SkAlphaType : kUnpremul_SkAlphaType),
+            mpData, maRects.mnSrcWidth * 4))
         abort();
     tmpBitmap.setImmutable();
     sk_sp<SkSurface> surface = SkiaHelper::createSkSurface(tmpBitmap.width(), tmpBitmap.height());
@@ -232,50 +239,6 @@ sk_sp<SkImage> SkiaCompatibleDC::getAsImage() const
     return surface->makeImageSnapshot();
 }
 
-sk_sp<SkImage> SkiaCompatibleDC::getAsImageDiff(const SkiaCompatibleDC& other) const
-{
-    assert(maRects.mnSrcWidth == other.maRects.mnSrcWidth
-           || maRects.mnSrcHeight == other.maRects.mnSrcHeight);
-    SkBitmap tmpBitmap;
-    if (!tmpBitmap.tryAllocPixels(SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight,
-                                                    kBGRA_8888_SkColorType, kUnpremul_SkAlphaType),
-                                  maRects.mnSrcWidth * 4))
-        abort();
-    // Native widgets are drawn twice on black/white background to synthetize alpha
-    // (commit c6b66646870cb2bffaa73565affcf80bf74e0b5c).
-    // Alpha is computed as "alpha = 1.0 - abs(black.red - white.red)".
-    // TODO I doubt this can be done using Skia, so do it manually here. Fortunately
-    // the bitmaps should be fairly small and are cached.
-    uint32_t* dest = tmpBitmap.getAddr32(0, 0);
-    assert(dest == tmpBitmap.getPixels());
-    const sal_uInt32* src = mpData;
-    const sal_uInt32* otherSrc = other.mpData;
-    uint32_t* end = dest + tmpBitmap.width() * tmpBitmap.height();
-    while (dest < end)
-    {
-        uint32_t alpha = 255 - abs(int(*src >> 24) - int(*otherSrc >> 24));
-        *dest = (*src & 0x00ffffff) | (alpha << 24);
-        ++dest;
-        ++src;
-        ++otherSrc;
-    }
-    tmpBitmap.notifyPixelsChanged();
-    tmpBitmap.setImmutable();
-    sk_sp<SkSurface> surface = SkiaHelper::createSkSurface(tmpBitmap.width(), tmpBitmap.height());
-    SkPaint paint;
-    paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha
-    SkCanvas* canvas = surface->getCanvas();
-    canvas->save();
-    // The data we got is upside-down.
-    SkMatrix matrix;
-    matrix.preTranslate(0, tmpBitmap.height());
-    matrix.setConcat(matrix, SkMatrix::MakeScale(1, -1));
-    canvas->concat(matrix);
-    canvas->drawBitmap(tmpBitmap, 0, 0, &paint);
-    canvas->restore();
-    return surface->makeImageSnapshot();
-}
-
 SkiaControlsCache::SkiaControlsCache()
     : cache(200)
 {


More information about the Libreoffice-commits mailing list