[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