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 <[email protected]> AuthorDate: Fri Jan 10 19:05:20 2020 +0100 Commit: Luboš Luňák <[email protected]> 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 <[email protected]> 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) { _______________________________________________ Libreoffice-commits mailing list [email protected] https://lists.freedesktop.org/mailman/listinfo/libreoffice-commits
