handle weird semantics of SkRect::intersect() (tdf#131721)

If the two rectangles do not intersect, it only returns false and does
nothing, which is stupid and confusing.

Change-Id: I24de6059807c208c39db4e942ab5624dde788723
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/91471
Tested-by: Jenkins
Reviewed-by: Luboš Luňák <l.lunak@collabora.com>
diff --git a/vcl/skia/gdiimpl.cxx b/vcl/skia/gdiimpl.cxx
index 390bf52..53ccda6 100644
--- a/vcl/skia/gdiimpl.cxx
+++ b/vcl/skia/gdiimpl.cxx
@@ -324,44 +324,50 @@
        {
            // Make slightly larger, just in case (rounding, antialiasing,...).
            mXorExtents.outset(2, 2);
            mXorExtents.intersect(SkRect::MakeXYWH(0, 0, mSurface->width(), mSurface->height()));
            if (!mXorExtents.intersect(
                    SkRect::MakeXYWH(0, 0, mSurface->width(), mSurface->height())))
                mXorExtents.setEmpty();
        }
        SAL_INFO("vcl.skia.trace",
                 "applyxor(" << this << "): "
                             << tools::Rectangle(mXorExtents.left(), mXorExtents.top(),
                                                 mXorExtents.right(), mXorExtents.bottom()));
        // 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
        SkCanvas canvas(surfaceBitmap);
        canvas.drawImageRect(mSurface->makeImageSnapshot(), mXorExtents, mXorExtents, &paint);
        // xor to surfaceBitmap
        assert(surfaceBitmap.info().alphaType() == kUnpremul_SkAlphaType);
        assert(mXorBitmap.info().alphaType() == kUnpremul_SkAlphaType);
        assert(surfaceBitmap.bytesPerPixel() == 4);
        assert(mXorBitmap.bytesPerPixel() == 4);
        for (int y = mXorExtents.top(); y < mXorExtents.bottom(); ++y)
        if (!mXorExtents.isEmpty()) // the intersection above may be empty
        {
            uint8_t* data = static_cast<uint8_t*>(surfaceBitmap.getAddr(mXorExtents.x(), y));
            const uint8_t* xordata = static_cast<uint8_t*>(mXorBitmap.getAddr(mXorExtents.x(), y));
            for (int x = 0; x < mXorExtents.width(); ++x)
            // 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
            SkCanvas canvas(surfaceBitmap);
            canvas.drawImageRect(mSurface->makeImageSnapshot(), mXorExtents, mXorExtents, &paint);
            // xor to surfaceBitmap
            assert(surfaceBitmap.info().alphaType() == kUnpremul_SkAlphaType);
            assert(mXorBitmap.info().alphaType() == kUnpremul_SkAlphaType);
            assert(surfaceBitmap.bytesPerPixel() == 4);
            assert(mXorBitmap.bytesPerPixel() == 4);
            for (int y = mXorExtents.top(); y < mXorExtents.bottom(); ++y)
            {
                *data++ ^= *xordata++;
                *data++ ^= *xordata++;
                *data++ ^= *xordata++;
                // alpha is not xor-ed
                data++;
                xordata++;
                uint8_t* data = static_cast<uint8_t*>(surfaceBitmap.getAddr(mXorExtents.x(), y));
                const uint8_t* xordata
                    = static_cast<uint8_t*>(mXorBitmap.getAddr(mXorExtents.x(), y));
                for (int x = 0; x < mXorExtents.width(); ++x)
                {
                    *data++ ^= *xordata++;
                    *data++ ^= *xordata++;
                    *data++ ^= *xordata++;
                    // alpha is not xor-ed
                    data++;
                    xordata++;
                }
            }
            surfaceBitmap.notifyPixelsChanged();
            mSurface->getCanvas()->drawBitmapRect(surfaceBitmap, mXorExtents, mXorExtents, &paint);
        }
        surfaceBitmap.notifyPixelsChanged();
        mSurface->getCanvas()->drawBitmapRect(surfaceBitmap, mXorExtents, mXorExtents, &paint);
        mXorCanvas.reset();
        mXorBitmap.reset();
        mXorExtents.setEmpty();