external/skia/UnpackedTarball_skia.mk          |    1 
 external/skia/allow-no-es2restrictions.patch.1 |   13 ++
 vcl/inc/skia/gdiimpl.hxx                       |  123 ++++++++++++++-------
 vcl/inc/skia/utils.hxx                         |    5 
 vcl/inc/skia/x11/gdiimpl.hxx                   |    4 
 vcl/skia/SkiaHelper.cxx                        |   64 +++++++++++
 vcl/skia/gdiimpl.cxx                           |  143 ++++---------------------
 vcl/unx/generic/gdi/salgdi.cxx                 |    2 
 8 files changed, 193 insertions(+), 162 deletions(-)

New commits:
commit f7a628f8efe037c1fd7e594eb4b8fc6a44573384
Author:     Luboš Luňák <l.lu...@collabora.com>
AuthorDate: Fri Nov 26 09:10:57 2021 +0100
Commit:     Luboš Luňák <l.lu...@collabora.com>
CommitDate: Mon Nov 29 21:49:10 2021 +0100

    implement xor drawing directly using Skia (tdf#141090)
    
    Up until now this has been implemented like in almost all other VCL
    backends by manually xor-ing pixel values. But that required fetching
    pixel values from the GPU in Vulkan mode, which is relatively slow.
    Since some time Skia now has supported writing custom blending modes
    using the SkBlender class, so it's now possible to drop the hack
    and support xor drawing directly using a blender that does
    the operation. This should be both faster and simpler.
    
    Change-Id: Id751d0ed4034852ce68697ecf56cc6dfac95307f
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/126051
    Tested-by: Jenkins
    Reviewed-by: Luboš Luňák <l.lu...@collabora.com>

diff --git a/external/skia/UnpackedTarball_skia.mk 
b/external/skia/UnpackedTarball_skia.mk
index c6e27ecf4183..cbaa37895061 100644
--- a/external/skia/UnpackedTarball_skia.mk
+++ b/external/skia/UnpackedTarball_skia.mk
@@ -37,6 +37,7 @@ skia_patches := \
     disable-freetype-colrv1.1 \
     windows-libraries-system32.patch.1 \
     fix-graphite-ifdef.patch.1 \
+    allow-no-es2restrictions.patch.1 \
 
 $(eval $(call gb_UnpackedTarball_set_patchlevel,skia,1))
 
diff --git a/external/skia/allow-no-es2restrictions.patch.1 
b/external/skia/allow-no-es2restrictions.patch.1
new file mode 100644
index 000000000000..0195ad3d2ac8
--- /dev/null
+++ b/external/skia/allow-no-es2restrictions.patch.1
@@ -0,0 +1,13 @@
+diff --git a/include/effects/SkRuntimeEffect.h 
b/include/effects/SkRuntimeEffect.h
+index b3f21b1d58..dddc8d16dc 100644
+--- a/include/effects/SkRuntimeEffect.h
++++ b/include/effects/SkRuntimeEffect.h
+@@ -97,7 +97,7 @@ public:
+         // run the inliner directly, but they still get an inlining pass once 
they are painted.)
+         bool forceNoInline = false;
+ 
+-    private:
++//    private:
+         friend class SkRuntimeEffect;
+         friend class SkRuntimeEffectPriv;
+ 
diff --git a/vcl/inc/skia/gdiimpl.hxx b/vcl/inc/skia/gdiimpl.hxx
index cc4cda4b2ebd..2473d0918284 100644
--- a/vcl/inc/skia/gdiimpl.hxx
+++ b/vcl/inc/skia/gdiimpl.hxx
@@ -221,8 +221,8 @@ protected:
     void preDraw();
     // To be called after any drawing.
     void postDraw();
-    // The canvas to draw to. Will be diverted to a temporary for Xor mode.
-    SkCanvas* getDrawCanvas() { return mXorMode ? getXorCanvas() : 
mSurface->getCanvas(); }
+    // The canvas to draw to.
+    SkCanvas* getDrawCanvas() { return mSurface->getCanvas(); }
     // Call before makeImageSnapshot(), ensures the content is up to date.
     void flushDrawing();
 
@@ -261,22 +261,10 @@ protected:
     // Get the global HiDPI scaling factor.
     virtual int getWindowScaling() const;
 
-    SkCanvas* getXorCanvas();
-    void applyXor();
-    // NOTE: This must be called before the operation does any drawing.
     void addUpdateRegion(const SkRect& rect)
     {
         // Make slightly larger, just in case (rounding, antialiasing,...).
         SkIRect addedRect = rect.makeOutset(2, 2).round();
-        if (mXorMode)
-        {
-            // Two xor operations should cancel each other out. We batch xor 
operations,
-            // but if they can overlap, apply xor now, since applyXor() does 
the operation
-            // just once.
-            if (mXorRegion.intersects(addedRect))
-                applyXor();
-            mXorRegion.op(addedRect, SkRegion::kUnion_Op);
-        }
         // Using SkIRect should be enough, SkRegion would be too slow with 
many operations
         // and swapping to the screen is not _that_slow.
         mDirtyRect.join(addedRect);
@@ -308,31 +296,22 @@ protected:
     void performDrawPolyPolygon(const basegfx::B2DPolyPolygon& polygon, double 
transparency,
                                 bool useAA);
 
+    // Create SkPaint to use when drawing to the surface. It is not to be used
+    // when doing internal drawing such as when merging two bitmaps together.
+    // This may apply some default settings to the paint as necessary.
+    SkPaint makePaintInternal() const;
     // Create SkPaint set up for drawing lines (using mLineColor etc.).
-    SkPaint makeLinePaint(double transparency = 0) const
-    {
-        assert(mLineColor != SALCOLOR_NONE);
-        SkPaint paint;
-        paint.setColor(transparency == 0
-                           ? SkiaHelper::toSkColor(mLineColor)
-                           : SkiaHelper::toSkColorWithTransparency(mLineColor, 
transparency));
-        paint.setStyle(SkPaint::kStroke_Style);
-        return paint;
-    }
+    SkPaint makeLinePaint(double transparency = 0) const;
     // Create SkPaint set up for filling (using mFillColor etc.).
-    SkPaint makeFillPaint(double transparency = 0) const
-    {
-        assert(mFillColor != SALCOLOR_NONE);
-        SkPaint paint;
-        paint.setColor(transparency == 0
-                           ? SkiaHelper::toSkColor(mFillColor)
-                           : SkiaHelper::toSkColorWithTransparency(mFillColor, 
transparency));
-        if (mLineColor == mFillColor)
-            paint.setStyle(SkPaint::kStrokeAndFill_Style);
-        else
-            paint.setStyle(SkPaint::kFill_Style);
-        return paint;
-    }
+    SkPaint makeFillPaint(double transparency = 0) const;
+    // Create SkPaint set up for bitmap drawing.
+    SkPaint makeBitmapPaint() const;
+    // Create SkPaint set up for gradient drawing.
+    SkPaint makeGradientPaint() const;
+    // Create SkPaint set up for text drawing.
+    SkPaint makeTextPaint(Color color) const;
+    // Create SkPaint for unspecified pixel drawing. Avoid if possible.
+    SkPaint makePixelPaint(Color color) const;
 
     template <typename charT, typename traits>
     friend inline std::basic_ostream<charT, traits>&
@@ -360,12 +339,15 @@ protected:
     // Note that we generally use VCL coordinates, which is not mSurface 
coordinates if mScaling!=1.
     SkIRect mDirtyRect; // The area that has been changed since the last 
performFlush().
     vcl::Region mClipRegion;
-    SkRegion mXorRegion; // The area that needs updating for the xor operation.
     Color mLineColor;
     Color mFillColor;
-    bool mXorMode;
-    SkBitmap mXorBitmap;
-    std::unique_ptr<SkCanvas> mXorCanvas;
+    enum class XorMode
+    {
+        None,
+        Invert,
+        Xor
+    };
+    XorMode mXorMode;
     std::unique_ptr<SkiaFlushIdle> mFlush;
     // Info about pending polygons to draw (we try to merge adjacent polygons 
into one).
     struct LastPolyPolygonInfo
@@ -379,6 +361,65 @@ protected:
     int mScaling; // The scale factor for HiDPI screens.
 };
 
+inline SkPaint SkiaSalGraphicsImpl::makePaintInternal() const
+{
+    SkPaint paint;
+    // Invert could be done using a blend mode like invert() does, but
+    // intentionally use SkBlender to make sure it's not overwritten
+    // by a blend mode set later (which would be probably a mistake),
+    // and so that the drawing color does not actually matter.
+    if (mXorMode == XorMode::Invert)
+        SkiaHelper::setBlenderInvert(&paint);
+    else if (mXorMode == XorMode::Xor)
+        SkiaHelper::setBlenderXor(&paint);
+    return paint;
+}
+
+inline SkPaint SkiaSalGraphicsImpl::makeLinePaint(double transparency) const
+{
+    assert(mLineColor != SALCOLOR_NONE);
+    SkPaint paint = makePaintInternal();
+    paint.setColor(transparency == 0
+                       ? SkiaHelper::toSkColor(mLineColor)
+                       : SkiaHelper::toSkColorWithTransparency(mLineColor, 
transparency));
+    paint.setStyle(SkPaint::kStroke_Style);
+    return paint;
+}
+
+inline SkPaint SkiaSalGraphicsImpl::makeFillPaint(double transparency) const
+{
+    assert(mFillColor != SALCOLOR_NONE);
+    SkPaint paint = makePaintInternal();
+    paint.setColor(transparency == 0
+                       ? SkiaHelper::toSkColor(mFillColor)
+                       : SkiaHelper::toSkColorWithTransparency(mFillColor, 
transparency));
+    if (mLineColor == mFillColor)
+        paint.setStyle(SkPaint::kStrokeAndFill_Style);
+    else
+        paint.setStyle(SkPaint::kFill_Style);
+    return paint;
+}
+
+inline SkPaint SkiaSalGraphicsImpl::makeBitmapPaint() const { return 
makePaintInternal(); }
+
+inline SkPaint SkiaSalGraphicsImpl::makeGradientPaint() const { return 
makePaintInternal(); }
+
+inline SkPaint SkiaSalGraphicsImpl::makeTextPaint(Color color) const
+{
+    assert(color != SALCOLOR_NONE);
+    SkPaint paint = makePaintInternal();
+    paint.setColor(SkiaHelper::toSkColor(color));
+    return paint;
+}
+
+inline SkPaint SkiaSalGraphicsImpl::makePixelPaint(Color color) const
+{
+    assert(color != SALCOLOR_NONE);
+    SkPaint paint = makePaintInternal();
+    paint.setColor(SkiaHelper::toSkColor(color));
+    return paint;
+}
+
 #endif
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/vcl/inc/skia/utils.hxx b/vcl/inc/skia/utils.hxx
index ac8a185e711e..c4d671ed6b7e 100644
--- a/vcl/inc/skia/utils.hxx
+++ b/vcl/inc/skia/utils.hxx
@@ -103,6 +103,11 @@ enum DirectImage
     No
 };
 
+// Sets SkBlender that will do an invert operation.
+void setBlenderInvert(SkPaint* paint);
+// Sets SkBlender that will do a xor operation.
+void setBlenderXor(SkPaint* paint);
+
 // Must be called in any VCL backend before any Skia functionality is used.
 // If not set, Skia will be disabled.
 VCL_DLLPUBLIC void
diff --git a/vcl/inc/skia/x11/gdiimpl.hxx b/vcl/inc/skia/x11/gdiimpl.hxx
index b7e9fe2615e0..c2cb69649dab 100644
--- a/vcl/inc/skia/x11/gdiimpl.hxx
+++ b/vcl/inc/skia/x11/gdiimpl.hxx
@@ -14,6 +14,10 @@
 
 #include <unx/salgdi.h>
 #include <unx/x11/x11gdiimpl.h>
+// X11 headers
+constexpr int XNone = None;
+#undef None
+constexpr int None = XNone;
 #include <skia/gdiimpl.hxx>
 
 class VCL_PLUGIN_PUBLIC X11SkiaSalGraphicsImpl final : public 
SkiaSalGraphicsImpl,
diff --git a/vcl/skia/SkiaHelper.cxx b/vcl/skia/SkiaHelper.cxx
index d082b6799129..5b022d51b50d 100644
--- a/vcl/skia/SkiaHelper.cxx
+++ b/vcl/skia/SkiaHelper.cxx
@@ -644,11 +644,75 @@ tools::Long maxImageCacheSize()
     return officecfg::Office::Common::Cache::Skia::ImageCacheSize::get();
 }
 
+static sk_sp<SkBlender> invertBlender;
+static sk_sp<SkBlender> xorBlender;
+
+// This does the invert operation, i.e. result = color(255-R,255-G,255-B,A).
+void setBlenderInvert(SkPaint* paint)
+{
+    if (!invertBlender)
+    {
+        // Note that the colors are premultiplied, so '1 - dst.r' must be
+        // written as 'dst.a - dst.r', since premultiplied R is in the range 
(0-A).
+        const char* const diff = R"(
+            vec4 main( vec4 src, vec4 dst )
+            {
+                return vec4( dst.a - dst.r, dst.a - dst.g, dst.a - dst.b, 
dst.a );
+            }
+        )";
+        auto effect = SkRuntimeEffect::MakeForBlender(SkString(diff));
+        if (!effect.effect)
+        {
+            SAL_WARN("vcl.skia",
+                     "SKRuntimeEffect::MakeForBlender failed: " << 
effect.errorText.c_str());
+            abort();
+        }
+        invertBlender = effect.effect->makeBlender(nullptr);
+    }
+    paint->setBlender(invertBlender);
+}
+
+// This does the xor operation, i.e. bitwise xor of RGB values of both colors.
+void setBlenderXor(SkPaint* paint)
+{
+    if (!xorBlender)
+    {
+        // Note that the colors are premultiplied, converting to 0-255 range
+        // must also unpremultiply.
+        const char* const diff = R"(
+            vec4 main( vec4 src, vec4 dst )
+            {
+                return vec4(
+                    float(int(src.r * src.a * 255.0) ^ int(dst.r * dst.a * 
255.0)) / 255.0 / dst.a,
+                    float(int(src.g * src.a * 255.0) ^ int(dst.g * dst.a * 
255.0)) / 255.0 / dst.a,
+                    float(int(src.b * src.a * 255.0) ^ int(dst.b * dst.a * 
255.0)) / 255.0 / dst.a,
+                    dst.a );
+            }
+        )";
+        SkRuntimeEffect::Options opts;
+        // Skia does not allow binary operators in the default ES2Strict mode, 
but that's only
+        // because of OpenGL support. We don't use OpenGL, and it's safe for 
all modes that we do use.
+        // 
https://groups.google.com/g/skia-discuss/c/EPLuQbg64Kc/m/2uDXFIGhAwAJ
+        opts.enforceES2Restrictions = false;
+        auto effect = SkRuntimeEffect::MakeForBlender(SkString(diff), opts);
+        if (!effect.effect)
+        {
+            SAL_WARN("vcl.skia",
+                     "SKRuntimeEffect::MakeForBlender failed: " << 
effect.errorText.c_str());
+            abort();
+        }
+        xorBlender = effect.effect->makeBlender(nullptr);
+    }
+    paint->setBlender(xorBlender);
+}
+
 void cleanup()
 {
     sharedWindowContext.reset();
     imageCache.clear();
     imageCacheSize = 0;
+    invertBlender.reset();
+    xorBlender.reset();
 }
 
 static SkSurfaceProps commonSurfaceProps;
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 63d588aa913e..f1670e8c6db5 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -263,7 +263,7 @@ SkiaSalGraphicsImpl::SkiaSalGraphicsImpl(SalGraphics& 
rParent, SalGeometryProvid
     , mIsGPU(false)
     , mLineColor(SALCOLOR_NONE)
     , mFillColor(SALCOLOR_NONE)
-    , mXorMode(false)
+    , mXorMode(XorMode::None)
     , mFlush(new SkiaFlushIdle(this))
     , mPendingOperationsToFlush(0)
     , mScaling(1)
@@ -540,8 +540,6 @@ void SkiaSalGraphicsImpl::flushDrawing()
     if (!mSurface)
         return;
     checkPendingDrawing();
-    if (mXorMode)
-        applyXor();
     mSurface->flushAndSubmit();
     mPendingOperationsToFlush = 0;
 }
@@ -553,7 +551,7 @@ void SkiaSalGraphicsImpl::setCanvasScalingAndClipping()
     // If HiDPI scaling is active, simply set a scaling matrix for the canvas. 
This means
     // that all painting can use VCL coordinates and they'll be automatically 
translated to mSurface
     // scaled coordinates. If that is not wanted, the scale() state needs to 
be temporarily unset.
-    // State such as mDirtyRect and mXorRegion is not scaled, the scaling 
matrix applies to clipping too,
+    // State such as mDirtyRect is not scaled, the scaling matrix applies to 
clipping too,
     // and the rest needs to be handled explicitly.
     // When reading mSurface contents there's no automatic scaling and it 
needs to be handled explicitly.
     canvas->save(); // keep the original state without any scaling
@@ -645,109 +643,14 @@ void SkiaSalGraphicsImpl::SetFillColor(Color nColor)
     mFillColor = nColor;
 }
 
-void SkiaSalGraphicsImpl::SetXORMode(bool set, bool)
+void SkiaSalGraphicsImpl::SetXORMode(bool set, bool invert)
 {
-    if (mXorMode == set)
+    XorMode newMode = set ? (invert ? XorMode::Invert : XorMode::Xor) : 
XorMode::None;
+    if (newMode == mXorMode)
         return;
     checkPendingDrawing();
-    SAL_INFO("vcl.skia.trace", "setxormode(" << this << "): " << set);
-    if (set)
-        mXorRegion.setEmpty();
-    else
-        applyXor();
-    mXorMode = set;
-}
-
-SkCanvas* SkiaSalGraphicsImpl::getXorCanvas()
-{
-    SkiaZone zone;
-    assert(mXorMode);
-    // Skia does not implement xor drawing, so we need to handle it manually 
by redirecting
-    // to a temporary SkBitmap and then doing the xor operation on the data 
ourselves.
-    // There's no point in using SkSurface for GPU, we'd immediately need to 
get the pixels back.
-    if (!mXorCanvas)
-    {
-        // Use unpremultiplied alpha (see xor applying in applyXor()).
-        if 
(!mXorBitmap.tryAllocPixels(mSurface->imageInfo().makeAlphaType(kUnpremul_SkAlphaType)))
-            abort();
-        mXorBitmap.eraseARGB(0, 0, 0, 0);
-        mXorCanvas = std::make_unique<SkCanvas>(mXorBitmap);
-        if (mScaling != 1)
-            mXorCanvas->scale(mScaling, mScaling);
-        setCanvasClipRegion(mXorCanvas.get(), mClipRegion);
-    }
-    return mXorCanvas.get();
-}
-
-void SkiaSalGraphicsImpl::applyXor()
-{
-    // Apply the result from the temporary bitmap manually. This is indeed
-    // slow, but it doesn't seem to be needed often and is optimized
-    // in each operation by extending mXorRegion with the area that should be
-    // updated.
-    assert(mXorMode);
-    if (mScaling != 1 && !mXorRegion.isEmpty())
-    {
-        // Scale mXorRegion to mSurface coordinates if needed.
-        std::vector<SkIRect> rects;
-        for (SkRegion::Iterator it(mXorRegion); !it.done(); it.next())
-            rects.push_back(scaleRect(it.rect(), mScaling));
-        mXorRegion.setRects(rects.data(), rects.size());
-    }
-    if (!mSurface || !mXorCanvas
-        || !mXorRegion.op(SkIRect::MakeXYWH(0, 0, mSurface->width(), 
mSurface->height()),
-                          SkRegion::kIntersect_Op))
-    {
-        mXorRegion.setEmpty();
-        return;
-    }
-    SAL_INFO("vcl.skia.trace", "applyxor(" << this << "): " << mXorRegion);
-    // Copy the surface contents to another pixmap.
-    SkBitmap surfaceBitmap;
-    // Use unpremultiplied alpha format, so that we do not have to do the 
conversions to get
-    // the RGB and back (Skia will do it when converting, but it'll be 
presumably faster at it).
-    if 
(!surfaceBitmap.tryAllocPixels(mSurface->imageInfo().makeAlphaType(kUnpremul_SkAlphaType)))
-        abort();
-    SkPaint paint;
-    paint.setBlendMode(SkBlendMode::kSrc); // copy as is
-    SkRect area = SkRect::Make(mXorRegion.getBounds());
-    {
-        SkCanvas canvas(surfaceBitmap);
-        canvas.drawImageRect(makeCheckedImageSnapshot(mSurface), area, area, 
SkSamplingOptions(),
-                             &paint, SkCanvas::kFast_SrcRectConstraint);
-    }
-    // xor to surfaceBitmap
-    assert(surfaceBitmap.info().alphaType() == kUnpremul_SkAlphaType);
-    assert(mXorBitmap.info().alphaType() == kUnpremul_SkAlphaType);
-    assert(surfaceBitmap.bytesPerPixel() == 4);
-    assert(mXorBitmap.bytesPerPixel() == 4);
-    for (SkRegion::Iterator it(mXorRegion); !it.done(); it.next())
-    {
-        for (int y = it.rect().top(); y < it.rect().bottom(); ++y)
-        {
-            uint8_t* data = 
static_cast<uint8_t*>(surfaceBitmap.getAddr(it.rect().x(), y));
-            const uint8_t* xordata = 
static_cast<uint8_t*>(mXorBitmap.getAddr(it.rect().x(), y));
-            for (int x = 0; x < it.rect().width(); ++x)
-            {
-                *data++ ^= *xordata++;
-                *data++ ^= *xordata++;
-                *data++ ^= *xordata++;
-                // alpha is not xor-ed
-                data++;
-                xordata++;
-            }
-        }
-    }
-    surfaceBitmap.notifyPixelsChanged();
-    surfaceBitmap.setImmutable();
-    // Copy without any clipping or scaling.
-    resetCanvasScalingAndClipping();
-    mSurface->getCanvas()->drawImageRect(surfaceBitmap.asImage(), area, area, 
SkSamplingOptions(),
-                                         &paint, 
SkCanvas::kFast_SrcRectConstraint);
-    setCanvasScalingAndClipping();
-    mXorCanvas.reset();
-    mXorBitmap.reset();
-    mXorRegion.setEmpty();
+    SAL_INFO("vcl.skia.trace", "setxormode(" << this << "): " << set << "/" << 
invert);
+    mXorMode = newMode;
 }
 
 void SkiaSalGraphicsImpl::SetROPLineColor(SalROPColor nROPColor)
@@ -796,8 +699,7 @@ void SkiaSalGraphicsImpl::drawPixel(tools::Long nX, 
tools::Long nY, Color nColor
     preDraw();
     SAL_INFO("vcl.skia.trace", "drawpixel(" << this << "): " << Point(nX, nY) 
<< ":" << nColor);
     addUpdateRegion(SkRect::MakeXYWH(nX, nY, 1, 1));
-    SkPaint paint;
-    paint.setColor(toSkColor(nColor));
+    SkPaint paint = makePixelPaint(nColor);
     // Apparently drawPixel() is actually expected to set the pixel and not 
draw it.
     paint.setBlendMode(SkBlendMode::kSrc); // set as is, including alpha
     if (mScaling != 1 && isUnitTestRunning())
@@ -1290,7 +1192,7 @@ void SkiaSalGraphicsImpl::copyBits(const SalTwoRect& 
rPosAry, SalGraphics* pSrcG
     else
     {
         src = this;
-        assert(!mXorMode);
+        assert(mXorMode == XorMode::None);
     }
     auto srcDebug = [&]() -> std::string {
         if (src == this)
@@ -1309,7 +1211,7 @@ void SkiaSalGraphicsImpl::copyBits(const SalTwoRect& 
rPosAry, SalGraphics* pSrcG
 
 void SkiaSalGraphicsImpl::privateCopyBits(const SalTwoRect& rPosAry, 
SkiaSalGraphicsImpl* src)
 {
-    assert(!mXorMode);
+    assert(mXorMode == XorMode::None);
     addUpdateRegion(SkRect::MakeXYWH(rPosAry.mnDestX, rPosAry.mnDestY, 
rPosAry.mnDestWidth,
                                      rPosAry.mnDestHeight));
     SkPaint paint;
@@ -1499,7 +1401,7 @@ void SkiaSalGraphicsImpl::invert(basegfx::B2DPolygon 
const& rPoly, SalInvert eFl
 {
     preDraw();
     SAL_INFO("vcl.skia.trace", "invert(" << this << "): " << rPoly << ":" << 
int(eFlags));
-    assert(!mXorMode);
+    assert(mXorMode == XorMode::None);
     SkPath aPath;
     aPath.incReserve(rPoly.count());
     addPolygonToPath(rPoly, aPath);
@@ -1847,7 +1749,7 @@ void SkiaSalGraphicsImpl::drawImage(const SalTwoRect& 
rPosAry, const sk_sp<SkIma
     SkRect aDestinationRect = SkRect::MakeXYWH(rPosAry.mnDestX, 
rPosAry.mnDestY,
                                                rPosAry.mnDestWidth, 
rPosAry.mnDestHeight);
 
-    SkPaint aPaint;
+    SkPaint aPaint = makeBitmapPaint();
     aPaint.setBlendMode(eBlendMode);
 
     preDraw();
@@ -1871,7 +1773,7 @@ void SkiaSalGraphicsImpl::drawShader(const SalTwoRect& 
rPosAry, const sk_sp<SkSh
     SkRect destinationRect = SkRect::MakeXYWH(rPosAry.mnDestX, 
rPosAry.mnDestY, rPosAry.mnDestWidth,
                                               rPosAry.mnDestHeight);
     addUpdateRegion(destinationRect);
-    SkPaint paint;
+    SkPaint paint = makeBitmapPaint();
     paint.setBlendMode(blendMode);
     paint.setShader(shader);
     SkCanvas* canvas = getDrawCanvas();
@@ -1994,12 +1896,13 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const 
basegfx::B2DPoint& rNull,
             // Specify sizes to scale the image size back if needed (because 
of mScaling).
             SkRect dstRect = SkRect::MakeWH(imageSize.Width(), 
imageSize.Height());
             SkRect srcRect = SkRect::MakeWH(imageToDraw->width(), 
imageToDraw->height());
-            canvas->drawImageRect(imageToDraw, srcRect, dstRect, 
samplingOptions, nullptr,
+            SkPaint paint = makeBitmapPaint();
+            canvas->drawImageRect(imageToDraw, srcRect, dstRect, 
samplingOptions, &paint,
                                   SkCanvas::kFast_SrcRectConstraint);
         }
         else
         {
-            SkPaint paint;
+            SkPaint paint = makeBitmapPaint();
             // Scale the image size back if needed.
             SkMatrix scale = SkMatrix::Scale(1.0 / mScaling, 1.0 / mScaling);
             paint.setShader(SkShaders::Blend(
@@ -2026,7 +1929,7 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const 
basegfx::B2DPoint& rNull,
             samplingOptions = makeSamplingOptions(BmpScaleFlag::BestQuality, 
matrix, mScaling);
         if (pSkiaAlphaBitmap)
         {
-            SkPaint paint;
+            SkPaint paint = makeBitmapPaint();
             paint.setShader(SkShaders::Blend(SkBlendMode::kDstOut, // VCL 
alpha is one-minus-alpha.
                                              
rSkiaBitmap.GetSkShader(samplingOptions),
                                              
pSkiaAlphaBitmap->GetAlphaSkShader(samplingOptions)));
@@ -2038,7 +1941,7 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const 
basegfx::B2DPoint& rNull,
         }
         else if (rSkiaBitmap.PreferSkShader() || fAlpha != 1.0)
         {
-            SkPaint paint;
+            SkPaint paint = makeBitmapPaint();
             paint.setShader(rSkiaBitmap.GetSkShader(samplingOptions));
             if (fAlpha != 1.0)
                 paint.setShader(
@@ -2048,7 +1951,8 @@ bool SkiaSalGraphicsImpl::drawTransformedBitmap(const 
basegfx::B2DPoint& rNull,
         }
         else
         {
-            canvas->drawImage(rSkiaBitmap.GetSkImage(), 0, 0, samplingOptions);
+            SkPaint paint = makeBitmapPaint();
+            canvas->drawImage(rSkiaBitmap.GetSkImage(), 0, 0, samplingOptions, 
&paint);
         }
     }
     postDraw();
@@ -2135,7 +2039,7 @@ bool SkiaSalGraphicsImpl::drawGradient(const 
tools::PolyPolygon& rPolyPolygon,
         shader = SkGradientShader::MakeRadial(center, radius, colors, pos, 2, 
SkTileMode::kClamp);
     }
 
-    SkPaint paint;
+    SkPaint paint = makeGradientPaint();
     paint.setAntiAlias(mParent.getAntiAlias());
     paint.setShader(shader);
     getDrawCanvas()->drawPath(path, paint);
@@ -2168,7 +2072,7 @@ bool SkiaSalGraphicsImpl::implDrawGradient(const 
basegfx::B2DPolyPolygon& rPolyP
     }
     sk_sp<SkShader> shader = SkGradientShader::MakeLinear(points, 
colors.data(), pos.data(),
                                                           colors.size(), 
SkTileMode::kDecal);
-    SkPaint paint;
+    SkPaint paint = makeGradientPaint();
     paint.setAntiAlias(mParent.getAntiAlias());
     paint.setShader(shader);
     getDrawCanvas()->drawPath(path, paint);
@@ -2229,8 +2133,7 @@ void SkiaSalGraphicsImpl::drawGenericLayout(const 
GenericSalLayout& layout, Colo
             glyphIds.data() + index, count * sizeof(SkGlyphID), 
glyphForms.data() + index,
             verticalRun ? verticalFont : font, SkTextEncoding::kGlyphID);
         addUpdateRegion(textBlob->bounds());
-        SkPaint paint;
-        paint.setColor(toSkColor(textColor));
+        SkPaint paint = makeTextPaint(textColor);
         getDrawCanvas()->drawTextBlob(textBlob, 0, 0, paint);
         pos = rangeEnd;
     }
diff --git a/vcl/unx/generic/gdi/salgdi.cxx b/vcl/unx/generic/gdi/salgdi.cxx
index 43198c579bae..fd930bd10cfd 100644
--- a/vcl/unx/generic/gdi/salgdi.cxx
+++ b/vcl/unx/generic/gdi/salgdi.cxx
@@ -105,7 +105,7 @@ void X11SalGraphics::freeResources()
     if( mpClipRegion )
     {
         XDestroyRegion( mpClipRegion );
-        mpClipRegion = None;
+        mpClipRegion = nullptr;
     }
 
     mxImpl->freeResources();

Reply via email to