tdf#129845 vcl: avoid expensive system caching of trivial lines & polygons

Interestingly the cache map lookup is rather expensive; why:

polyline output for some trivial impress edits:
	count	# of polylines
	2	2134
	3	141
	4	41
	9	4

polypolygon output for some trivial impress edits:

	count	# of polypolygons	geometry.
	3	54    all single polygon
	4	583   ~all single
	9	52    ~ all paired with a 4 node polygon
	13	2     both single
	32	22    all single

Change-Id: I15c0053a84399eaf153b2119b2c28d1f168f16b1
Reviewed-on: https://gerrit.libreoffice.org/c/core/+/86314
Tested-by: Jenkins
Reviewed-by: Michael Meeks <michael.meeks@collabora.com>
diff --git a/vcl/headless/svpgdi.cxx b/vcl/headless/svpgdi.cxx
index 1bd5510..c792bb9 100644
--- a/vcl/headless/svpgdi.cxx
+++ b/vcl/headless/svpgdi.cxx
@@ -119,6 +119,18 @@
        aDamageRect.intersect(getClipBox(cr));
        return aDamageRect;
    }

    // The caching logic is surprsingly expensive - so avoid it sometimes.
    inline bool isTrivial(const basegfx::B2DPolyPolygon& rPolyPolygon)
    {
        return rPolyPolygon.count() == 1 && rPolyPolygon.begin()->count() <= 4;
    }

    // The caching logic is surprsingly expensive - so avoid it sometimes.
    inline bool isTrivial(const basegfx::B2DPolygon& rPolyLine)
    {
        return rPolyLine.count() <= 4;
    }
}

bool SvpSalGraphics::blendBitmap( const SalTwoRect&, const SalBitmap& /*rBitmap*/ )
@@ -1279,29 +1291,37 @@
    cairo_set_line_width(cr, aLineWidths.getX());
    cairo_set_miter_limit(cr, fMiterLimit);

    // try to access buffered data
    std::shared_ptr<SystemDependentData_CairoPath> pSystemDependentData_CairoPath(
        rPolyLine.getSystemDependentData<SystemDependentData_CairoPath>());
    bool bDone = false;
    bool bIsTrivial = isTrivial(rPolyLine);

    if(pSystemDependentData_CairoPath)
    if (!bIsTrivial)
    {
        // check data validity
        if(nullptr == pSystemDependentData_CairoPath->getCairoPath()
            || pSystemDependentData_CairoPath->getNoJoin() != bNoJoin
            || pSystemDependentData_CairoPath->getAntiAliasB2DDraw() != bAntiAliasB2DDraw
            || bPixelSnapHairline /*tdf#124700*/ )
        // try to access buffered data
        std::shared_ptr<SystemDependentData_CairoPath> pSystemDependentData_CairoPath(
            rPolyLine.getSystemDependentData<SystemDependentData_CairoPath>());

        if(pSystemDependentData_CairoPath)
        {
            // data invalid, forget
            pSystemDependentData_CairoPath.reset();
            // check data validity
            if(nullptr == pSystemDependentData_CairoPath->getCairoPath()
               || pSystemDependentData_CairoPath->getNoJoin() != bNoJoin
               || pSystemDependentData_CairoPath->getAntiAliasB2DDraw() != bAntiAliasB2DDraw
               || bPixelSnapHairline /*tdf#124700*/ )
            {
                // data invalid, forget
                pSystemDependentData_CairoPath.reset();
            }
        }

        if(pSystemDependentData_CairoPath)
        {
            // re-use data
            cairo_append_path(cr, pSystemDependentData_CairoPath->getCairoPath());
            bDone = true;
        }
    }

    if(pSystemDependentData_CairoPath)
    {
        // re-use data
        cairo_append_path(cr, pSystemDependentData_CairoPath->getCairoPath());
    }
    else
    if (!bDone)
    {
        // create data
        if (!bNoJoin)
@@ -1344,9 +1364,9 @@
        }

        // copy and add to buffering mechanism
        if (!bPixelSnapHairline /*tdf#124700*/)
        if (!bIsTrivial && !bPixelSnapHairline /*tdf#124700*/)
        {
            pSystemDependentData_CairoPath = rPolyLine.addOrReplaceSystemDependentData<SystemDependentData_CairoPath>(
            rPolyLine.addOrReplaceSystemDependentData<SystemDependentData_CairoPath>(
                ImplGetSystemDependentDataManager(),
                cairo_copy_path(cr),
                bNoJoin,
@@ -1397,16 +1417,24 @@
{
    void add_polygon_path(cairo_t* cr, const basegfx::B2DPolyPolygon& rPolyPolygon, const basegfx::B2DHomMatrix& rObjectToDevice, bool bPixelSnap)
    {
        // try to access buffered data
        std::shared_ptr<SystemDependentData_CairoPath> pSystemDependentData_CairoPath(
            rPolyPolygon.getSystemDependentData<SystemDependentData_CairoPath>());
        bool bDone = false;
        bool bIsTrivial = isTrivial(rPolyPolygon);

        if(pSystemDependentData_CairoPath)
        if (!bIsTrivial)
        {
            // re-use data
            cairo_append_path(cr, pSystemDependentData_CairoPath->getCairoPath());
            // try to access buffered data
            std::shared_ptr<SystemDependentData_CairoPath> pSystemDependentData_CairoPath(
                rPolyPolygon.getSystemDependentData<SystemDependentData_CairoPath>());

            if(pSystemDependentData_CairoPath)
            {
                // re-use data
                cairo_append_path(cr, pSystemDependentData_CairoPath->getCairoPath());
                bDone = true;
            }
        }
        else

        if (!bDone)
        {
            // create data
            for (const auto & rPoly : rPolyPolygon)
@@ -1421,13 +1449,16 @@
                    false);
            }

            // copy and add to buffering mechanism
            // for decisions how/what to buffer, see Note in WinSalGraphicsImpl::drawPolyPolygon
            pSystemDependentData_CairoPath = rPolyPolygon.addOrReplaceSystemDependentData<SystemDependentData_CairoPath>(
                ImplGetSystemDependentDataManager(),
                cairo_copy_path(cr),
                false,
                false);
            if (!bIsTrivial)
            {
                // copy and add to buffering mechanism
                // for decisions how/what to buffer, see Note in WinSalGraphicsImpl::drawPolyPolygon
                rPolyPolygon.addOrReplaceSystemDependentData<SystemDependentData_CairoPath>(
                    ImplGetSystemDependentDataManager(),
                    cairo_copy_path(cr),
                    false,
                    false);
            }
        }
    }
}