basegfx/source/color/bcolormodifier.cxx                |  136 +++-----
 drawinglayer/source/primitive2d/graphicprimitive2d.cxx |   49 +--
 include/basegfx/color/bcolormodifier.hxx               |   64 +++-
 vcl/source/bitmap/BitmapEx.cxx                         |  268 ++++++++++-------
 4 files changed, 305 insertions(+), 212 deletions(-)

New commits:
commit 27829e4a6c5a4a1162599550c46b5e7f974aba91
Author:     Armin Le Grand (allotropia) <armin.le.grand.ext...@allotropia.de>
AuthorDate: Wed Jul 10 13:16:20 2024 +0200
Commit:     Armin Le Grand <armin.le.gr...@me.com>
CommitDate: Thu Jul 11 10:58:24 2024 +0200

    CairoSDPR: Improve BColorModified Bitmaps
    
    There is the complete BColorModifierStack support for
    primitives for Bitmaps, e.g. hue/saturation, etc, but
    it was slow due to not being buffered, so had to be
    re-created often. I changed this to use the common
    buffering mechanism to improve this.
    Up to now a fallback to use the old Graphic
    manipulators for that purpose was in place since this
    was faster, but had to be done every time. I have now
    changed the priority to using the primitive way to
    handle things, but kept the fallback code - just in
    case.
    Note that the new stuff is faster, but even much faster
    when the bitmap is copied and appears multiple times ->
    the same buffered instance is used, and SDPRs then use
    the system-dependent data buffered at that prepared
    data.
    Also note that this change does not only speedup
    CairoSDPR, but all PrimitiveRenderers, including the
    VCL and Metafile ones. In principle everything that
    uses BitmapEx::ModifyBitmapEx.
    Had a 2nd thought: Only the content Bitmap gets changed,
    so for this case we do not need AssociatedAlpha and
    watch for it to not have changed. Removed that.
    
    Change-Id: I2ee36cc84bdc1c723aa01f872edbfd1f51e11c2d
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/170305
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <armin.le.gr...@me.com>

diff --git a/basegfx/source/color/bcolormodifier.cxx 
b/basegfx/source/color/bcolormodifier.cxx
index 04ab3757cb45..e0e0ebbd6203 100644
--- a/basegfx/source/color/bcolormodifier.cxx
+++ b/basegfx/source/color/bcolormodifier.cxx
@@ -33,11 +33,6 @@ namespace basegfx
     {
     }
 
-    bool BColorModifier_gray::operator==(const BColorModifier& rCompare) const
-    {
-        return dynamic_cast< const BColorModifier_gray* >(&rCompare) != 
nullptr;
-    }
-
     ::basegfx::BColor BColorModifier_gray::getModifiedColor(const 
::basegfx::BColor& aSourceColor) const
     {
         const double fLuminance(aSourceColor.luminance());
@@ -54,11 +49,6 @@ namespace basegfx
     {
     }
 
-    bool BColorModifier_invert::operator==(const BColorModifier& rCompare) 
const
-    {
-        return dynamic_cast< const BColorModifier_invert* >(&rCompare) != 
nullptr;
-    }
-
     ::basegfx::BColor BColorModifier_invert::getModifiedColor(const 
::basegfx::BColor& aSourceColor) const
     {
         return ::basegfx::BColor(1.0 - aSourceColor.getRed(), 1.0 - 
aSourceColor.getGreen(), 1.0 - aSourceColor.getBlue());
@@ -73,11 +63,6 @@ namespace basegfx
     {
     }
 
-    bool BColorModifier_luminance_to_alpha::operator==(const BColorModifier& 
rCompare) const
-    {
-        return dynamic_cast< const BColorModifier_luminance_to_alpha* 
>(&rCompare) != nullptr;
-    }
-
     ::basegfx::BColor 
BColorModifier_luminance_to_alpha::getModifiedColor(const ::basegfx::BColor& 
aSourceColor) const
     {
         const double fAlpha(1.0 - ((aSourceColor.getRed() * 0.2125) + 
(aSourceColor.getGreen() * 0.7154) + (aSourceColor.getBlue() * 0.0721)));
@@ -96,13 +81,10 @@ namespace basegfx
 
     bool BColorModifier_replace::operator==(const BColorModifier& rCompare) 
const
     {
-        const BColorModifier_replace* pCompare = dynamic_cast< const 
BColorModifier_replace* >(&rCompare);
-
-        if(!pCompare)
-        {
+        if (!BColorModifier::operator==(rCompare))
             return false;
-        }
 
+        const BColorModifier_replace* pCompare(static_cast< const 
BColorModifier_replace* >(&rCompare));
         return getBColor() == pCompare->getBColor();
     }
 
@@ -122,13 +104,10 @@ namespace basegfx
 
     bool BColorModifier_interpolate::operator==(const BColorModifier& 
rCompare) const
     {
-        const BColorModifier_interpolate* pCompare = dynamic_cast< const 
BColorModifier_interpolate* >(&rCompare);
-
-        if(!pCompare)
-        {
+        if (!BColorModifier::operator==(rCompare))
             return false;
-        }
 
+        const BColorModifier_interpolate* pCompare(static_cast< const 
BColorModifier_interpolate* >(&rCompare));
         return maBColor == pCompare->maBColor && mfValue == pCompare->mfValue;
     }
 
@@ -148,13 +127,10 @@ namespace basegfx
 
     bool BColorModifier_matrix::operator==(const BColorModifier& rCompare) 
const
     {
-        const BColorModifier_matrix* pCompare = dynamic_cast< const 
BColorModifier_matrix* >(&rCompare);
-
-        if(!pCompare)
-        {
+        if (!BColorModifier::operator==(rCompare))
             return false;
-        }
 
+        const BColorModifier_matrix* pCompare(static_cast< const 
BColorModifier_matrix* >(&rCompare));
         return maVector == pCompare->maVector;
     }
 
@@ -198,6 +174,7 @@ namespace basegfx
     }
 
     BColorModifier_saturate::BColorModifier_saturate(double fValue)
+    : BColorModifier(basegfx::BColorModifierType::BCMType_saturate)
     {
         maSatMatrix.set(0, 0, 0.213 + 0.787 * fValue);
         maSatMatrix.set(0, 1, 0.715 - 0.715 * fValue);
@@ -216,13 +193,10 @@ namespace basegfx
 
     bool BColorModifier_saturate::operator==(const BColorModifier& rCompare) 
const
     {
-        const BColorModifier_saturate* pCompare = dynamic_cast< const 
BColorModifier_saturate* >(&rCompare);
-
-        if(!pCompare)
-        {
+        if (!BColorModifier::operator==(rCompare))
             return false;
-        }
 
+        const BColorModifier_saturate* pCompare(static_cast< const 
BColorModifier_saturate* >(&rCompare));
         return maSatMatrix == pCompare->maSatMatrix;
     }
 
@@ -243,6 +217,7 @@ namespace basegfx
     }
 
     BColorModifier_hueRotate::BColorModifier_hueRotate(double fRad)
+    : BColorModifier(basegfx::BColorModifierType::BCMType_hueRotate)
     {
         const double fCos = cos(fRad);
         const double fSin = sin(fRad);
@@ -264,13 +239,10 @@ namespace basegfx
 
     bool BColorModifier_hueRotate::operator==(const BColorModifier& rCompare) 
const
     {
-        const BColorModifier_hueRotate* pCompare = dynamic_cast< const 
BColorModifier_hueRotate* >(&rCompare);
-
-        if(!pCompare)
-        {
+        if (!BColorModifier::operator==(rCompare))
             return false;
-        }
 
+        const BColorModifier_hueRotate* pCompare(static_cast< const 
BColorModifier_hueRotate* >(&rCompare));
         return maHueMatrix == pCompare->maHueMatrix;
     }
 
@@ -299,13 +271,10 @@ namespace basegfx
 
     bool BColorModifier_black_and_white::operator==(const BColorModifier& 
rCompare) const
     {
-        const BColorModifier_black_and_white* pCompare = dynamic_cast< const 
BColorModifier_black_and_white* >(&rCompare);
-
-        if(!pCompare)
-        {
+        if (!BColorModifier::operator==(rCompare))
             return false;
-        }
 
+        const BColorModifier_black_and_white* pCompare(static_cast< const 
BColorModifier_black_and_white* >(&rCompare));
         return mfValue == pCompare->mfValue;
     }
 
@@ -329,9 +298,10 @@ namespace basegfx
     }
 
     BColorModifier_gamma::BColorModifier_gamma(double fValue)
-    :   mfValue(fValue),
-        mfInvValue(fValue),
-        mbUseIt(!basegfx::fTools::equal(fValue, 1.0) && fValue > 0.0 && 
basegfx::fTools::lessOrEqual(fValue, 10.0))
+    : BColorModifier(basegfx::BColorModifierType::BCMType_gamma)
+    , mfValue(fValue)
+    , mfInvValue(fValue)
+    , mbUseIt(!basegfx::fTools::equal(fValue, 1.0) && fValue > 0.0 && 
basegfx::fTools::lessOrEqual(fValue, 10.0))
     {
         if(mbUseIt)
         {
@@ -345,14 +315,12 @@ namespace basegfx
 
     bool BColorModifier_gamma::operator==(const BColorModifier& rCompare) const
     {
-        const BColorModifier_gamma* pCompare = dynamic_cast< const 
BColorModifier_gamma* >(&rCompare);
-
-        if(!pCompare)
-        {
+        if (!BColorModifier::operator==(rCompare))
             return false;
-        }
 
-        // getValue is sufficient, mfInvValue and mbUseIt are only helper 
values
+        const BColorModifier_gamma* pCompare(static_cast< const 
BColorModifier_gamma* >(&rCompare));
+
+        // mfValue is sufficient, mfInvValue and mbUseIt are only helper values
         return mfValue == pCompare->mfValue;
     }
 
@@ -380,16 +348,17 @@ namespace basegfx
     }
 
     
BColorModifier_RGBLuminanceContrast::BColorModifier_RGBLuminanceContrast(double 
fRed, double fGreen, double fBlue, double fLuminance, double fContrast)
-    :   mfRed(std::clamp(fRed, -1.0, 1.0)),
-        mfGreen(std::clamp(fGreen, -1.0, 1.0)),
-        mfBlue(std::clamp(fBlue, -1.0, 1.0)),
-        mfLuminance(std::clamp(fLuminance, -1.0, 1.0)),
-        mfContrast(std::clamp(fContrast, -1.0, 1.0)),
-        mfContrastOff(1.0),
-        mfRedOff(0.0),
-        mfGreenOff(0.0),
-        mfBlueOff(0.0),
-        mbUseIt(false)
+    : BColorModifier(basegfx::BColorModifierType::BCMType_RGBLuminanceContrast)
+    , mfRed(std::clamp(fRed, -1.0, 1.0))
+    , mfGreen(std::clamp(fGreen, -1.0, 1.0))
+    , mfBlue(std::clamp(fBlue, -1.0, 1.0))
+    , mfLuminance(std::clamp(fLuminance, -1.0, 1.0))
+    , mfContrast(std::clamp(fContrast, -1.0, 1.0))
+    , mfContrastOff(1.0)
+    , mfRedOff(0.0)
+    , mfGreenOff(0.0)
+    , mfBlueOff(0.0)
+    , mbUseIt(false)
     {
         if(basegfx::fTools::equalZero(mfRed)
             && basegfx::fTools::equalZero(mfGreen)
@@ -426,12 +395,10 @@ namespace basegfx
 
     bool BColorModifier_RGBLuminanceContrast::operator==(const BColorModifier& 
rCompare) const
     {
-        const BColorModifier_RGBLuminanceContrast* pCompare = dynamic_cast< 
const BColorModifier_RGBLuminanceContrast* >(&rCompare);
-
-        if(!pCompare)
-        {
+        if (!BColorModifier::operator==(rCompare))
             return false;
-        }
+
+        const BColorModifier_RGBLuminanceContrast* pCompare(static_cast< const 
BColorModifier_RGBLuminanceContrast* >(&rCompare));
 
         // no need to compare other values, these are just helpers
         return mfRed == pCompare->mfRed
@@ -462,7 +429,8 @@ namespace basegfx
     }
 
     BColorModifier_randomize::BColorModifier_randomize(double fRandomPart)
-    : mfRandomPart(fRandomPart)
+    : BColorModifier(basegfx::BColorModifierType::BCMType_randomize)
+    , mfRandomPart(fRandomPart)
     {
     }
 
@@ -473,13 +441,10 @@ namespace basegfx
     // compare operator
     bool BColorModifier_randomize::operator==(const BColorModifier& rCompare) 
const
     {
-        const BColorModifier_randomize* pCompare = dynamic_cast< const 
BColorModifier_randomize* >(&rCompare);
-
-        if(!pCompare)
-        {
+        if (!BColorModifier::operator==(rCompare))
             return false;
-        }
 
+        const BColorModifier_randomize* pCompare(static_cast< const 
BColorModifier_randomize* >(&rCompare));
         return mfRandomPart == pCompare->mfRandomPart;
     }
 
@@ -534,6 +499,27 @@ namespace basegfx
 
         return aRetval;
     }
+
+    bool BColorModifierStack::operator==(const BColorModifierStack& rComp) 
const
+    {
+        if (count() != rComp.count())
+            return false;
+
+        if (0 == count())
+            return true;
+
+        for (sal_uInt32 a(0); a < count(); a++)
+        {
+            // nullptrs are not allowed/expected
+            assert(maBColorModifiers[a] != nullptr);
+            assert(rComp.maBColorModifiers[a] != nullptr);
+
+            if (!(*maBColorModifiers[a] == *rComp.maBColorModifiers[a]))
+                return false;
+        }
+
+        return true;
+    }
 } // end of namespace basegfx
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx 
b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
index 0f228c528a0e..2c97c809f4ff 100644
--- a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
@@ -75,28 +75,41 @@ GraphicPrimitive2D::create2DDecomposition(const 
geometry::ViewInformation2D&) co
 
     const GraphicObject& rGraphicObject = getGraphicObject();
     Graphic aTransformedGraphic(rGraphicObject.GetGraphic());
-    const bool isBitmap(GraphicType::Bitmap == aTransformedGraphic.GetType()
-                        && !aTransformedGraphic.getVectorGraphicData());
     const bool isAdjusted(getGraphicAttr().IsAdjusted());
     const bool isDrawMode(GraphicDrawMode::Standard != 
getGraphicAttr().GetDrawMode());
 
-    if (isBitmap && (isAdjusted || isDrawMode))
+    // I have now added buffering BColorModifierStack-adapted Bitmaps,
+    // see BitmapEx::ModifyBitmapEx, thus the primitive case is fast now.
+    // It buffers the adapted bitmap and at that the SDPRs can then buffer
+    // the system-dependent represetation.
+    // I keep the code below (adding a static switch). It modifies the
+    // Graphic and is a reliable fallback - just in case. Remember that
+    // it does *not* buffer and has to modify again at each re-use...
+    static bool bUseOldModification(false);
+
+    if (bUseOldModification)
     {
-        // the pure primitive solution with the color modifiers works well, 
too, but when
-        // it is a bitmap graphic the old modification currently is faster; so 
use it here
-        // instead of creating all as in 
create2DColorModifierEmbeddingsAsNeeded (see below).
-        // Still, crop, rotation, mirroring and transparency is handled by 
primitives already
-        // (see above).
-        // This could even be done when vector graphic, but we explicitly want 
to have the
-        // pure primitive solution for this; this will allow vector graphics 
to stay vector
-        // graphics, independent from the color filtering stuff. This will 
enhance e.g.
-        // SVG and print quality while reducing data size at the same time.
-        // The other way around the old modifications when only used on 
already bitmap objects
-        // will not lose any quality.
-        aTransformedGraphic = 
rGraphicObject.GetTransformedGraphic(&aSuppressGraphicAttr);
-
-        // reset GraphicAttr after use to not apply double
-        aSuppressGraphicAttr = GraphicAttr();
+        const bool isBitmap(GraphicType::Bitmap == 
aTransformedGraphic.GetType()
+                            && !aTransformedGraphic.getVectorGraphicData());
+
+        if (isBitmap && (isAdjusted || isDrawMode))
+        {
+            // the pure primitive solution with the color modifiers works 
well, too, but when
+            // it is a bitmap graphic the old modification currently is 
faster; so use it here
+            // instead of creating all as in 
create2DColorModifierEmbeddingsAsNeeded (see below).
+            // Still, crop, rotation, mirroring and transparency is handled by 
primitives already
+            // (see above).
+            // This could even be done when vector graphic, but we explicitly 
want to have the
+            // pure primitive solution for this; this will allow vector 
graphics to stay vector
+            // graphics, independent from the color filtering stuff. This will 
enhance e.g.
+            // SVG and print quality while reducing data size at the same time.
+            // The other way around the old modifications when only used on 
already bitmap objects
+            // will not lose any quality.
+            aTransformedGraphic = 
rGraphicObject.GetTransformedGraphic(&aSuppressGraphicAttr);
+
+            // reset GraphicAttr after use to not apply double
+            aSuppressGraphicAttr = GraphicAttr();
+        }
     }
 
     // create sub-content; helper takes care of correct handling of
diff --git a/include/basegfx/color/bcolormodifier.hxx 
b/include/basegfx/color/bcolormodifier.hxx
index 59f277555c30..e74d6b43726e 100644
--- a/include/basegfx/color/bcolormodifier.hxx
+++ b/include/basegfx/color/bcolormodifier.hxx
@@ -32,6 +32,21 @@
 
 namespace basegfx
 {
+    enum class BColorModifierType : sal_uInt16 {
+        BCMType_gray,
+        BCMType_invert,
+        BCMType_luminance_to_alpha,
+        BCMType_replace,
+        BCMType_interpolate,
+        BCMType_saturate,
+        BCMType_matrix,
+        BCMType_hueRotate,
+        BCMType_black_and_white,
+        BCMType_gamma,
+        BCMType_RGBLuminanceContrast,
+        BCMType_randomize
+    };
+
     /** base class to define color modifications
 
         The basic idea is to have instances of color modifiers where each
@@ -61,12 +76,16 @@ namespace basegfx
     class SAL_WARN_UNUSED BASEGFX_DLLPUBLIC BColorModifier
     {
     private:
+        BColorModifierType  maType;
         BColorModifier(const BColorModifier&) = delete;
         BColorModifier& operator=(const BColorModifier&) = delete;
     protected:
         // no one is allowed to incarnate the abstract base class
         // except derivations
-        BColorModifier() {}
+        BColorModifier(BColorModifierType aType)
+        : maType(aType)
+        {
+        }
 
     public:
         // no one should directly destroy it; all incarnations should be
@@ -74,9 +93,19 @@ namespace basegfx
         virtual ~BColorModifier();
 
         // compare operator
-        virtual bool operator==(const BColorModifier& rCompare) const = 0;
+        virtual bool operator==(const BColorModifier& rCompare) const
+        {
+            if (maType != rCompare.maType)
+                return false;
+
+            return true;
+        }
+
         bool operator!=(const BColorModifier& rCompare) const
         {
+            if (maType != rCompare.maType)
+                return true;
+
             return !(operator==(rCompare));
         }
 
@@ -84,6 +113,9 @@ namespace basegfx
         virtual ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& 
aSourceColor) const = 0;
 
         virtual OUString getModifierName() const = 0;
+
+        // return type
+        BColorModifierType getBColorModifierType() const { return maType; }
     };
 
     /** convert color to gray
@@ -92,14 +124,12 @@ namespace basegfx
     {
     public:
         BColorModifier_gray()
+        : BColorModifier(basegfx::BColorModifierType::BCMType_gray)
         {
         }
 
         virtual ~BColorModifier_gray() override;
 
-        // compare operator
-        SAL_DLLPRIVATE virtual bool operator==(const BColorModifier& rCompare) 
const override;
-
         // compute modified color
         SAL_DLLPRIVATE virtual ::basegfx::BColor getModifiedColor(const 
::basegfx::BColor& aSourceColor) const override;
         SAL_DLLPRIVATE virtual OUString getModifierName() const override;
@@ -113,14 +143,12 @@ namespace basegfx
     {
     public:
         BColorModifier_invert()
+        : BColorModifier(basegfx::BColorModifierType::BCMType_invert)
         {
         }
 
         virtual ~BColorModifier_invert() override;
 
-        // compare operator
-        SAL_DLLPRIVATE virtual bool operator==(const BColorModifier& rCompare) 
const override;
-
         // compute modified color
         SAL_DLLPRIVATE virtual ::basegfx::BColor getModifiedColor(const 
::basegfx::BColor& aSourceColor) const override;
         SAL_DLLPRIVATE virtual OUString getModifierName() const override;
@@ -138,14 +166,12 @@ namespace basegfx
     {
     public:
         BColorModifier_luminance_to_alpha()
+        : 
BColorModifier(basegfx::BColorModifierType::BCMType_luminance_to_alpha)
         {
         }
 
         virtual ~BColorModifier_luminance_to_alpha() override;
 
-        // compare operator
-        SAL_DLLPRIVATE virtual bool operator==(const BColorModifier& rCompare) 
const override;
-
         // compute modified color
         SAL_DLLPRIVATE virtual ::basegfx::BColor getModifiedColor(const 
::basegfx::BColor& aSourceColor) const override;
         SAL_DLLPRIVATE virtual OUString getModifierName() const override;
@@ -164,7 +190,8 @@ namespace basegfx
 
     public:
         BColorModifier_replace(const ::basegfx::BColor& rBColor)
-        :   maBColor(rBColor)
+        : BColorModifier(basegfx::BColorModifierType::BCMType_replace)
+        , maBColor(rBColor)
         {
         }
 
@@ -196,8 +223,9 @@ namespace basegfx
 
     public:
         BColorModifier_interpolate(const ::basegfx::BColor& rBColor, double 
fValue)
-        :   maBColor(rBColor),
-            mfValue(fValue)
+        : BColorModifier(basegfx::BColorModifierType::BCMType_interpolate)
+        , maBColor(rBColor)
+        , mfValue(fValue)
         {
         }
 
@@ -250,7 +278,8 @@ namespace basegfx
 
     public:
         BColorModifier_matrix(std::vector<double> aVector)
-            : maVector(std::move(aVector))
+        : BColorModifier(basegfx::BColorModifierType::BCMType_matrix)
+        , maVector(std::move(aVector))
         {
         }
 
@@ -300,7 +329,8 @@ namespace basegfx
 
     public:
         BColorModifier_black_and_white(double fValue)
-        :   mfValue(fValue)
+        : BColorModifier(basegfx::BColorModifierType::BCMType_black_and_white)
+        , mfValue(fValue)
         {
         }
 
@@ -441,6 +471,8 @@ namespace basegfx
         {
             maBColorModifiers.pop_back();
         }
+
+        bool operator==(const BColorModifierStack& rComp) const;
     };
 } // end of namespace basegfx
 
diff --git a/vcl/source/bitmap/BitmapEx.cxx b/vcl/source/bitmap/BitmapEx.cxx
index f00eff75ab9e..3c6679df6795 100644
--- a/vcl/source/bitmap/BitmapEx.cxx
+++ b/vcl/source/bitmap/BitmapEx.cxx
@@ -837,148 +837,210 @@ BitmapEx BitmapEx::getTransformed(
     return aRetval;
 }
 
+namespace
+{
+class BufferedData_ModifiedBitmapEx : public basegfx::SystemDependentData
+{
+    Bitmap maChangedBitmap;
+    basegfx::BColorModifierStack maBColorModifierStack;
+
+public:
+    BufferedData_ModifiedBitmapEx(
+        const Bitmap& rChangedBitmap,
+        const basegfx::BColorModifierStack& rBColorModifierStack)
+    : 
basegfx::SystemDependentData(Application::GetSystemDependentDataManager())
+    , maChangedBitmap(rChangedBitmap)
+    , maBColorModifierStack(rBColorModifierStack)
+    {
+    }
+
+    const Bitmap& getChangedBitmap() const { return maChangedBitmap; }
+    const basegfx::BColorModifierStack& getBColorModifierStack() const { 
return maBColorModifierStack; }
+
+    virtual sal_Int64 estimateUsageInBytes() const override;
+};
+
+sal_Int64 BufferedData_ModifiedBitmapEx::estimateUsageInBytes() const
+{
+    return maChangedBitmap.GetSizeBytes();
+}
+}
+
 BitmapEx BitmapEx::ModifyBitmapEx(const basegfx::BColorModifierStack& 
rBColorModifierStack) const
 {
-    Bitmap aChangedBitmap(GetBitmap());
-    bool bDone(false);
+    if (0 == rBColorModifierStack.count())
+    {
+        // no modifiers, done
+        return *this;
+    }
 
-    for(sal_uInt32 a(rBColorModifierStack.count()); a && !bDone; )
+    // check for BColorModifier_replace at the top of the stack
+    const basegfx::BColorModifierSharedPtr& 
rLastModifier(rBColorModifierStack.getBColorModifier(rBColorModifierStack.count()
 - 1));
+    const basegfx::BColorModifier_replace* 
pLastModifierReplace(dynamic_cast<const 
basegfx::BColorModifier_replace*>(rLastModifier.get()));
+
+    if (nullptr != pLastModifierReplace && !IsAlpha())
     {
-        const basegfx::BColorModifierSharedPtr& rModifier = 
rBColorModifierStack.getBColorModifier(--a);
-        const basegfx::BColorModifier_replace* pReplace = dynamic_cast< const 
basegfx::BColorModifier_replace* >(rModifier.get());
+        // at the top of the stack we have a BColorModifier_replace -> no 
Bitmap needed,
+        // representation can be replaced by filled colored polygon. signal 
the caller
+        // about that by returning empty BitmapEx
+        return BitmapEx();
+    }
 
-        if(pReplace)
+    const basegfx::SystemDependentDataHolder* 
pHolder(GetBitmap().accessSystemDependentDataHolder());
+    std::shared_ptr<BufferedData_ModifiedBitmapEx> 
pBufferedData_ModifiedBitmapEx;
+
+    if (nullptr != pHolder)
+    {
+        // try to access SystemDependentDataHolder and buffered data
+        pBufferedData_ModifiedBitmapEx = 
std::static_pointer_cast<BufferedData_ModifiedBitmapEx>(
+            pHolder->getSystemDependentData(
+                typeid(BufferedData_ModifiedBitmapEx).hash_code()));
+
+        if (nullptr != pBufferedData_ModifiedBitmapEx
+            && !(pBufferedData_ModifiedBitmapEx->getBColorModifierStack() == 
rBColorModifierStack))
         {
-            // complete replace
+            // BColorModifierStack is different -> data invalid
+            pBufferedData_ModifiedBitmapEx = nullptr;
+        }
+
+        if (nullptr != pBufferedData_ModifiedBitmapEx)
+        {
+            // found existing instance of modified Bitmap, return 
reused/buffered result
             if(IsAlpha())
-            {
-                // clear bitmap with dest color
-                if (vcl::isPalettePixelFormat(aChangedBitmap.getPixelFormat()))
-                {
-                    // For e.g. 8bit Bitmaps, the nearest color to the given 
erase color is
-                    // determined and used -> this may be different from what 
is wanted here.
-                    // Better create a new bitmap with the needed color 
explicitly.
-                    BitmapScopedReadAccess xReadAccess(aChangedBitmap);
-                    OSL_ENSURE(xReadAccess, "Got no Bitmap ReadAccess ?!?");
+                return 
BitmapEx(pBufferedData_ModifiedBitmapEx->getChangedBitmap(), GetAlphaMask());
+            return 
BitmapEx(pBufferedData_ModifiedBitmapEx->getChangedBitmap());
+        }
+    }
 
-                    if(xReadAccess)
-                    {
-                        BitmapPalette aNewPalette(xReadAccess->GetPalette());
-                        aNewPalette[0] = 
BitmapColor(Color(pReplace->getBColor()));
-                        aChangedBitmap = Bitmap(
-                            aChangedBitmap.GetSizePixel(),
-                            aChangedBitmap.getPixelFormat(),
-                            &aNewPalette);
-                    }
-                }
-                aChangedBitmap.Erase(Color(pReplace->getBColor()));
-            }
-            else
+    // have to create modified Bitmap
+    Bitmap aChangedBitmap(GetBitmap());
+
+    if (nullptr != pLastModifierReplace)
+    {
+        // special case -> we have BColorModifier_replace but Alpha channel
+        if (vcl::isPalettePixelFormat(aChangedBitmap.getPixelFormat()))
+        {
+            // For e.g. 8bit Bitmaps, the nearest color to the given erase 
color is
+            // determined and used -> this may be different from what is 
wanted here.
+            // Better create a new bitmap with the needed color explicitly.
+            BitmapScopedReadAccess xReadAccess(aChangedBitmap);
+            OSL_ENSURE(xReadAccess, "Got no Bitmap ReadAccess ?!?");
+
+            if(xReadAccess)
             {
-                // erase bitmap, caller will know to paint direct
-                aChangedBitmap.SetEmpty();
+                BitmapPalette aNewPalette(xReadAccess->GetPalette());
+                aNewPalette[0] = 
BitmapColor(Color(pLastModifierReplace->getBColor()));
+                aChangedBitmap = Bitmap(
+                    aChangedBitmap.GetSizePixel(),
+                    aChangedBitmap.getPixelFormat(),
+                    &aNewPalette);
             }
-
-            bDone = true;
         }
         else
         {
-            BitmapScopedWriteAccess xContent(aChangedBitmap);
+            // clear bitmap with dest color
+            aChangedBitmap.Erase(Color(pLastModifierReplace->getBColor()));
+        }
+    }
+    else
+    {
+        BitmapScopedWriteAccess xContent(aChangedBitmap);
+
+        if(xContent)
+        {
+            const double fConvertColor(1.0 / 255.0);
 
-            if(xContent)
+            if(xContent->HasPalette())
             {
-                const double fConvertColor(1.0 / 255.0);
+                const sal_uInt16 nCount(xContent->GetPaletteEntryCount());
 
-                if(xContent->HasPalette())
+                for(sal_uInt16 b(0); b < nCount; b++)
+                {
+                    const BitmapColor& rCol = xContent->GetPaletteColor(b);
+                    const basegfx::BColor aBSource(
+                        rCol.GetRed() * fConvertColor,
+                        rCol.GetGreen() * fConvertColor,
+                        rCol.GetBlue() * fConvertColor);
+                    const basegfx::BColor 
aBDest(rBColorModifierStack.getModifiedColor(aBSource));
+                    xContent->SetPaletteColor(b, BitmapColor(Color(aBDest)));
+                }
+            }
+            else if(ScanlineFormat::N24BitTcBgr == 
xContent->GetScanlineFormat())
+            {
+                for(tools::Long y(0); y < xContent->Height(); y++)
                 {
-                    const sal_uInt16 nCount(xContent->GetPaletteEntryCount());
+                    Scanline pScan = xContent->GetScanline(y);
 
-                    for(sal_uInt16 b(0); b < nCount; b++)
+                    for(tools::Long x(0); x < xContent->Width(); x++)
                     {
-                        const BitmapColor& rCol = xContent->GetPaletteColor(b);
                         const basegfx::BColor aBSource(
-                            rCol.GetRed() * fConvertColor,
-                            rCol.GetGreen() * fConvertColor,
-                            rCol.GetBlue() * fConvertColor);
-                        const basegfx::BColor 
aBDest(rModifier->getModifiedColor(aBSource));
-                        xContent->SetPaletteColor(b, 
BitmapColor(Color(aBDest)));
+                            *(pScan + 2)* fConvertColor,
+                            *(pScan + 1) * fConvertColor,
+                            *pScan * fConvertColor);
+                        const basegfx::BColor 
aBDest(rBColorModifierStack.getModifiedColor(aBSource));
+                        *pScan++ = static_cast< sal_uInt8 >(aBDest.getBlue() * 
255.0);
+                        *pScan++ = static_cast< sal_uInt8 >(aBDest.getGreen() 
* 255.0);
+                        *pScan++ = static_cast< sal_uInt8 >(aBDest.getRed() * 
255.0);
                     }
                 }
-                else if(ScanlineFormat::N24BitTcBgr == 
xContent->GetScanlineFormat())
+            }
+            else if(ScanlineFormat::N24BitTcRgb == 
xContent->GetScanlineFormat())
+            {
+                for(tools::Long y(0); y < xContent->Height(); y++)
                 {
-                    for(tools::Long y(0); y < xContent->Height(); y++)
-                    {
-                        Scanline pScan = xContent->GetScanline(y);
+                    Scanline pScan = xContent->GetScanline(y);
 
-                        for(tools::Long x(0); x < xContent->Width(); x++)
-                        {
-                            const basegfx::BColor aBSource(
-                                *(pScan + 2)* fConvertColor,
-                                *(pScan + 1) * fConvertColor,
-                                *pScan * fConvertColor);
-                            const basegfx::BColor 
aBDest(rModifier->getModifiedColor(aBSource));
-                            *pScan++ = static_cast< sal_uInt8 
>(aBDest.getBlue() * 255.0);
-                            *pScan++ = static_cast< sal_uInt8 
>(aBDest.getGreen() * 255.0);
-                            *pScan++ = static_cast< sal_uInt8 
>(aBDest.getRed() * 255.0);
-                        }
-                    }
-                }
-                else if(ScanlineFormat::N24BitTcRgb == 
xContent->GetScanlineFormat())
-                {
-                    for(tools::Long y(0); y < xContent->Height(); y++)
+                    for(tools::Long x(0); x < xContent->Width(); x++)
                     {
-                        Scanline pScan = xContent->GetScanline(y);
-
-                        for(tools::Long x(0); x < xContent->Width(); x++)
-                        {
-                            const basegfx::BColor aBSource(
-                                *pScan * fConvertColor,
-                                *(pScan + 1) * fConvertColor,
-                                *(pScan + 2) * fConvertColor);
-                            const basegfx::BColor 
aBDest(rModifier->getModifiedColor(aBSource));
-                            *pScan++ = static_cast< sal_uInt8 
>(aBDest.getRed() * 255.0);
-                            *pScan++ = static_cast< sal_uInt8 
>(aBDest.getGreen() * 255.0);
-                            *pScan++ = static_cast< sal_uInt8 
>(aBDest.getBlue() * 255.0);
-                        }
+                        const basegfx::BColor aBSource(
+                            *pScan * fConvertColor,
+                            *(pScan + 1) * fConvertColor,
+                            *(pScan + 2) * fConvertColor);
+                        const basegfx::BColor 
aBDest(rBColorModifierStack.getModifiedColor(aBSource));
+                        *pScan++ = static_cast< sal_uInt8 >(aBDest.getRed() * 
255.0);
+                        *pScan++ = static_cast< sal_uInt8 >(aBDest.getGreen() 
* 255.0);
+                        *pScan++ = static_cast< sal_uInt8 >(aBDest.getBlue() * 
255.0);
                     }
                 }
-                else
+            }
+            else
+            {
+                for(tools::Long y(0); y < xContent->Height(); y++)
                 {
-                    for(tools::Long y(0); y < xContent->Height(); y++)
+                    Scanline pScanline = xContent->GetScanline( y );
+                    for(tools::Long x(0); x < xContent->Width(); x++)
                     {
-                        Scanline pScanline = xContent->GetScanline( y );
-                        for(tools::Long x(0); x < xContent->Width(); x++)
-                        {
-                            const BitmapColor aBMCol(xContent->GetColor(y, x));
-                            const basegfx::BColor aBSource(
-                                static_cast<double>(aBMCol.GetRed()) * 
fConvertColor,
-                                static_cast<double>(aBMCol.GetGreen()) * 
fConvertColor,
-                                static_cast<double>(aBMCol.GetBlue()) * 
fConvertColor);
-                            const basegfx::BColor 
aBDest(rModifier->getModifiedColor(aBSource));
-
-                            xContent->SetPixelOnData(pScanline, x, 
BitmapColor(Color(aBDest)));
-                        }
+                        const BitmapColor aBMCol(xContent->GetColor(y, x));
+                        const basegfx::BColor aBSource(
+                            static_cast<double>(aBMCol.GetRed()) * 
fConvertColor,
+                            static_cast<double>(aBMCol.GetGreen()) * 
fConvertColor,
+                            static_cast<double>(aBMCol.GetBlue()) * 
fConvertColor);
+                        const basegfx::BColor 
aBDest(rBColorModifierStack.getModifiedColor(aBSource));
+
+                        xContent->SetPixelOnData(pScanline, x, 
BitmapColor(Color(aBDest)));
                     }
                 }
             }
         }
     }
 
-    if(aChangedBitmap.IsEmpty())
+    if (nullptr != pHolder)
     {
-        return BitmapEx();
-    }
-    else
-    {
-        if(IsAlpha())
+        // create new BufferedData_ModifiedBitmapEx (should be nullptr here)
+        if (nullptr == pBufferedData_ModifiedBitmapEx)
         {
-            return BitmapEx(aChangedBitmap, GetAlphaMask());
-        }
-        else
-        {
-            return BitmapEx(aChangedBitmap);
+            pBufferedData_ModifiedBitmapEx = 
std::make_shared<BufferedData_ModifiedBitmapEx>(aChangedBitmap, 
rBColorModifierStack);
         }
+
+        // register it, evtl. it's a new one
+        basegfx::SystemDependentData_SharedPtr 
r2(pBufferedData_ModifiedBitmapEx);
+        
const_cast<basegfx::SystemDependentDataHolder*>(pHolder)->addOrReplaceSystemDependentData(r2);
     }
+
+    // return result
+    if(IsAlpha())
+        return BitmapEx(aChangedBitmap, GetAlphaMask());
+    return BitmapEx(aChangedBitmap);
 }
 
 BitmapEx createBlendFrame(

Reply via email to