diff options
Diffstat (limited to 'vcl')
-rw-r--r-- | vcl/inc/opengl/win/gdiimpl.hxx | 6 | ||||
-rw-r--r-- | vcl/inc/skia/utils.hxx | 6 | ||||
-rw-r--r-- | vcl/inc/skia/win/gdiimpl.hxx | 7 | ||||
-rw-r--r-- | vcl/inc/win/salgdi.h | 2 | ||||
-rw-r--r-- | vcl/opengl/win/gdiimpl.cxx | 6 | ||||
-rw-r--r-- | vcl/skia/win/gdiimpl.cxx | 55 |
6 files changed, 63 insertions, 19 deletions
diff --git a/vcl/inc/opengl/win/gdiimpl.hxx b/vcl/inc/opengl/win/gdiimpl.hxx index 91e55a2ca28f..dff47ef7e550 100644 --- a/vcl/inc/opengl/win/gdiimpl.hxx +++ b/vcl/inc/opengl/win/gdiimpl.hxx @@ -26,12 +26,12 @@ class OpenGLCompatibleDC : public CompatibleDC public: OpenGLCompatibleDC(SalGraphics &rGraphics, int x, int y, int width, int height); - virtual std::unique_ptr<Texture> getAsMaskTexture() override; + virtual std::unique_ptr<Texture> getAsMaskTexture() const override; // caller must delete - OpenGLTexture* getOpenGLTexture(); + OpenGLTexture* getOpenGLTexture() const; /// Copy bitmap data to the texture. Texture must be initialized and the correct size to hold the bitmap. - bool copyToTexture(Texture& aTexture); + bool copyToTexture(Texture& aTexture) const; struct Texture; }; diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx index 27ca2b1f0b72..6fd61afd0a05 100644 --- a/vcl/inc/skia/utils.hxx +++ b/vcl/inc/skia/utils.hxx @@ -44,9 +44,9 @@ inline sk_sp<SkSurface> createSkSurface(const Size& size, SkColorType type = kN3 #ifdef DBG_UTIL void prefillSurface(sk_sp<SkSurface>& surface); -void dump(const SkBitmap& bitmap, const char* file); -void dump(const sk_sp<SkImage>& image, const char* file); -void dump(const sk_sp<SkSurface>& surface, const char* file); +VCL_DLLPUBLIC void dump(const SkBitmap& bitmap, const char* file); +VCL_DLLPUBLIC void dump(const sk_sp<SkImage>& image, const char* file); +VCL_DLLPUBLIC void dump(const sk_sp<SkSurface>& surface, const char* file); #endif } // namespace diff --git a/vcl/inc/skia/win/gdiimpl.hxx b/vcl/inc/skia/win/gdiimpl.hxx index 003fac2cc65b..dabd56ad04a3 100644 --- a/vcl/inc/skia/win/gdiimpl.hxx +++ b/vcl/inc/skia/win/gdiimpl.hxx @@ -27,12 +27,13 @@ class SkiaCompatibleDC : public CompatibleDC public: SkiaCompatibleDC(SalGraphics& rGraphics, int x, int y, int width, int height); - virtual std::unique_ptr<Texture> getAsMaskTexture() override; + virtual std::unique_ptr<Texture> getAsMaskTexture() const override; virtual bool wantsTextColorWhite() const override { return true; } - sk_sp<SkImage> getAsImage(); - sk_sp<SkImage> getAsMaskImage(); + sk_sp<SkImage> getAsImage() const; + sk_sp<SkImage> getAsMaskImage() const; + sk_sp<SkImage> getAsImageDiff(const SkiaCompatibleDC& other) const; struct Texture; }; diff --git a/vcl/inc/win/salgdi.h b/vcl/inc/win/salgdi.h index eb0d428cc77f..15866800b8f4 100644 --- a/vcl/inc/win/salgdi.h +++ b/vcl/inc/win/salgdi.h @@ -140,7 +140,7 @@ public: struct Texture; /// Obtain the texture in format for WinSalGraphicsImplBase::DrawTextMask(). - virtual std::unique_ptr<Texture> getAsMaskTexture() { abort(); }; + virtual std::unique_ptr<Texture> getAsMaskTexture() const { abort(); }; /// Return true if text glyphs should be drawn as white instead of black. virtual bool wantsTextColorWhite() const { return false; } diff --git a/vcl/opengl/win/gdiimpl.cxx b/vcl/opengl/win/gdiimpl.cxx index d736cfc08972..eabfe8a090b3 100644 --- a/vcl/opengl/win/gdiimpl.cxx +++ b/vcl/opengl/win/gdiimpl.cxx @@ -769,7 +769,7 @@ OpenGLCompatibleDC::OpenGLCompatibleDC(SalGraphics &rGraphics, int x, int y, int { } -OpenGLTexture* OpenGLCompatibleDC::getOpenGLTexture() +OpenGLTexture* OpenGLCompatibleDC::getOpenGLTexture() const { if (!mpImpl) return nullptr; @@ -778,14 +778,14 @@ OpenGLTexture* OpenGLCompatibleDC::getOpenGLTexture() return new OpenGLTexture(maRects.mnSrcWidth, maRects.mnSrcHeight, GL_BGRA, GL_UNSIGNED_BYTE, mpData); } -std::unique_ptr<CompatibleDC::Texture> OpenGLCompatibleDC::getAsMaskTexture() +std::unique_ptr<CompatibleDC::Texture> OpenGLCompatibleDC::getAsMaskTexture() const { auto ret = std::make_unique<OpenGLCompatibleDC::Texture>(); ret->texture = OpenGLTexture(maRects.mnSrcWidth, maRects.mnSrcHeight, GL_BGRA, GL_UNSIGNED_BYTE, mpData); return ret; } -bool OpenGLCompatibleDC::copyToTexture(CompatibleDC::Texture& aTexture) +bool OpenGLCompatibleDC::copyToTexture(CompatibleDC::Texture& aTexture) const { if (!mpImpl) return false; diff --git a/vcl/skia/win/gdiimpl.cxx b/vcl/skia/win/gdiimpl.cxx index 09ebb0139660..b3f538bcea5b 100644 --- a/vcl/skia/win/gdiimpl.cxx +++ b/vcl/skia/win/gdiimpl.cxx @@ -104,12 +104,11 @@ bool WinSkiaSalGraphicsImpl::RenderAndCacheNativeControl(CompatibleDC& rWhite, C assert(dynamic_cast<SkiaCompatibleDC*>(&rWhite)); assert(dynamic_cast<SkiaCompatibleDC*>(&rBlack)); - sk_sp<SkImage> image = static_cast<SkiaCompatibleDC&>(rWhite).getAsImage(); + sk_sp<SkImage> image = static_cast<SkiaCompatibleDC&>(rWhite).getAsImageDiff( + static_cast<SkiaCompatibleDC&>(rBlack)); preDraw(); mSurface->getCanvas()->drawImage(image, nX, nY); postDraw(); - // TODO what is the point of the second texture? - (void)rBlack; if (!aControlCacheKey.canCacheControl()) return true; @@ -159,14 +158,14 @@ SkiaCompatibleDC::SkiaCompatibleDC(SalGraphics& rGraphics, int x, int y, int wid { } -std::unique_ptr<CompatibleDC::Texture> SkiaCompatibleDC::getAsMaskTexture() +std::unique_ptr<CompatibleDC::Texture> SkiaCompatibleDC::getAsMaskTexture() const { auto ret = std::make_unique<SkiaCompatibleDC::Texture>(); ret->image = getAsMaskImage(); return ret; } -sk_sp<SkImage> SkiaCompatibleDC::getAsMaskImage() +sk_sp<SkImage> SkiaCompatibleDC::getAsMaskImage() const { // mpData is in the BGRA format, with A unused (and set to 0), and RGB are grey, // so convert it to Skia format, then to 8bit and finally use as alpha mask @@ -208,7 +207,7 @@ sk_sp<SkImage> SkiaCompatibleDC::getAsMaskImage() return surface->makeImageSnapshot(); } -sk_sp<SkImage> SkiaCompatibleDC::getAsImage() +sk_sp<SkImage> SkiaCompatibleDC::getAsImage() const { SkBitmap tmpBitmap; if (!tmpBitmap.installPixels(SkImageInfo::Make(maRects.mnSrcWidth, maRects.mnSrcHeight, @@ -233,6 +232,50 @@ sk_sp<SkImage> SkiaCompatibleDC::getAsImage() 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) { |