summaryrefslogtreecommitdiff
path: root/vcl
diff options
context:
space:
mode:
Diffstat (limited to 'vcl')
-rw-r--r--vcl/inc/opengl/win/gdiimpl.hxx6
-rw-r--r--vcl/inc/skia/utils.hxx6
-rw-r--r--vcl/inc/skia/win/gdiimpl.hxx7
-rw-r--r--vcl/inc/win/salgdi.h2
-rw-r--r--vcl/opengl/win/gdiimpl.cxx6
-rw-r--r--vcl/skia/win/gdiimpl.cxx55
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)
{