[Libreoffice-commits] core.git: Branch 'aoo/trunk' - basegfx/inc basegfx/source drawinglayer/inc drawinglayer/source svgio/source svx/source vcl/source

Armin Le Grand alg at apache.org
Tue Nov 5 19:08:22 CET 2013


 basegfx/inc/basegfx/color/bcolor.hxx                                   |    6 
 basegfx/inc/basegfx/color/bcolormodifier.hxx                           |  397 ++++++++--
 basegfx/source/color/bcolormodifier.cxx                                |  336 +++++++-
 drawinglayer/inc/drawinglayer/primitive2d/graphicprimitivehelper2d.hxx |   19 
 drawinglayer/inc/drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx |   10 
 drawinglayer/inc/drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx |    8 
 drawinglayer/source/primitive2d/graphicprimitive2d.cxx                 |  204 +++--
 drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx           |  137 +++
 drawinglayer/source/primitive2d/metafileprimitive2d.cxx                |    4 
 drawinglayer/source/primitive2d/modifiedcolorprimitive2d.cxx           |   16 
 drawinglayer/source/primitive2d/shadowprimitive2d.cxx                  |    9 
 drawinglayer/source/primitive2d/texteffectprimitive2d.cxx              |   49 -
 drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx           |   16 
 drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx            |    9 
 drawinglayer/source/processor2d/vclprocessor2d.cxx                     |   11 
 drawinglayer/source/tools/converters.cxx                               |    8 
 svgio/source/svgreader/svgmasknode.cxx                                 |    6 
 svx/source/sdr/contact/viewobjectcontact.cxx                           |   11 
 svx/source/sdr/contact/viewobjectcontactofe3d.cxx                      |   11 
 svx/source/sdr/contact/viewobjectcontactofe3dscene.cxx                 |   10 
 vcl/source/gdi/bitmapex.cxx                                            |  128 ++-
 21 files changed, 1149 insertions(+), 256 deletions(-)

New commits:
commit 1e79e8da3f8042f7d7bd94b2c9f03cff7545b05c
Author: Armin Le Grand <alg at apache.org>
Date:   Tue Nov 5 16:13:12 2013 +0000

    i123500 redefined ColorModifiers and ColorModifierStack, redefined GraphicAttr to be expressed as primitives if needed, enhanced render and export quality if graphic is modified using graphic attributes

diff --git a/basegfx/inc/basegfx/color/bcolor.hxx b/basegfx/inc/basegfx/color/bcolor.hxx
index 724fe05..0319b09 100644
--- a/basegfx/inc/basegfx/color/bcolor.hxx
+++ b/basegfx/inc/basegfx/color/bcolor.hxx
@@ -193,18 +193,20 @@ namespace basegfx
         }
 
         // clamp color to [0.0..1.0] values in all three intensity components
-        void clamp()
+        BColor& clamp()
         {
             mfX = basegfx::clamp(mfX, 0.0, 1.0);
             mfY = basegfx::clamp(mfY, 0.0, 1.0);
             mfZ = basegfx::clamp(mfZ, 0.0, 1.0);
+            return *this;
         }
 
-        void invert()
+        BColor& invert()
         {
             mfX = 1.0 - mfX;
             mfY = 1.0 - mfY;
             mfZ = 1.0 - mfZ;
+            return *this;
         }
 
         static const BColor& getEmptyBColor()
diff --git a/basegfx/inc/basegfx/color/bcolormodifier.hxx b/basegfx/inc/basegfx/color/bcolormodifier.hxx
index afdc38c..4009239 100644
--- a/basegfx/inc/basegfx/color/bcolormodifier.hxx
+++ b/basegfx/inc/basegfx/color/bcolormodifier.hxx
@@ -19,77 +19,376 @@
  *
  *************************************************************/
 
-
-
 #ifndef _BGFX_COLOR_BCOLORMODIFIER_HXX
 #define _BGFX_COLOR_BCOLORMODIFIER_HXX
 
 #include <basegfx/color/bcolor.hxx>
+#include <boost/utility.hpp>
+#include <boost/shared_ptr.hpp>
 #include <vector>
 
 //////////////////////////////////////////////////////////////////////////////
 
 namespace basegfx
 {
-    /** Descriptor for type of color modification
+    /** base class to define color modifications
+
+        The basic idea is to have instances of color modifiers where each
+        of these can be asked to get a modified version of a color. This
+        can be as easy as to return a fixed color, but may also do any
+        other computation based on the given source color and the local
+        algorythm to apply.
+
+        This base implementation defines the abstract base class. Every
+        derivation offers another color blending effect, when needed with
+        parameters for that blending defined as members.
+
+        As long as aw080 is not applied, an operator== is needed to implement
+        the operator== of the primitive based on this instances.
+
+        For the exact definitions of the color blending applied refer to the
+        implementation of the method getModifiedColor
+
+        BColorModifier is not copyable (no copy constructor, no assigment
+        operator); local values cannot be changed after construction. The
+        instances are cheap and the idea is to create them on demand. To
+        be able to reuse these as much as possible, a define for a
+        ::boost::shared_ptr named BColorModifierSharedPtr exists below.
+        All usages should handle instances of BColorModifier encapsulated
+        into these shared pointers.
     */
-    enum BColorModifyMode
+    class BColorModifier : private boost::noncopyable
     {
-        BCOLORMODIFYMODE_REPLACE,               // replace all color with local color
-        BCOLORMODIFYMODE_INTERPOLATE,           // interpolate color between given and local with local value
-        BCOLORMODIFYMODE_GRAY,                  // convert color to gray
-        BCOLORMODIFYMODE_BLACKANDWHITE,         // convert color to B&W, local value is treshhold
-        BCOLORMODIFYMODE_INVERT,                // invert color
-        BCOLORMODIFYMODE_LUMINANCE_TO_ALPHA     // convert color to alpha value (used for Svg Mask)
+    private:
+    protected:
+        // noone is allowed to incarnate the abstract base class
+        // except derivations
+        BColorModifier() {}
+
+    public:
+        // noone should directly destroy it; all incarnations should be
+        // handled in a boost::shared_ptr of type BColorModifierSharedPtr
+        virtual ~BColorModifier();
+
+        // compare operator
+        virtual bool operator==(const BColorModifier& rCompare) const = 0;
+        bool operator!=(const BColorModifier& rCompare) const
+        {
+            return !(operator==(rCompare));
+        }
+
+        // compute modified color
+        virtual ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& aSourceColor) const = 0;
     };
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    /** convert color to gray
 
-    /** Class to hold a color, value and mode for a color modification. Color modification is
-        done calling the getModifiedColor() method
+        returns a color where red green and blue are replaced with the
+        luminance value calculated based on the source color by using
+        the following weights: r * 0.30, g * 0.59, b * 0.11
     */
-    class BColorModifier
+    class BColorModifier_gray : public BColorModifier
     {
+    private:
     protected:
-        ::basegfx::BColor                           maBColor;
-        double                                      mfValue;
-        BColorModifyMode                            meMode;
+    public:
+        BColorModifier_gray()
+        :   BColorModifier()
+        {
+        }
+
+        virtual ~BColorModifier_gray();
+
+        // compare operator
+        virtual bool operator==(const BColorModifier& rCompare) const;
+
+        // compute modified color
+        virtual ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& aSourceColor) const;
+    };
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
 
+namespace basegfx
+{
+    /** invert color
+
+        returns a color where red green and blue are inverted using 1.0 - n
+    */
+    class BColorModifier_invert : public BColorModifier
+    {
+    private:
+    protected:
     public:
-        BColorModifier(
-            const ::basegfx::BColor& rBColor,
-            double fValue = 0.5,
-            BColorModifyMode eMode = BCOLORMODIFYMODE_REPLACE)
-        :   maBColor(rBColor),
-            mfValue(fValue),
-            meMode(eMode)
-        {}
-
-        // compare operator(s)
-        bool operator==(const BColorModifier& rCompare) const
+        BColorModifier_invert()
+        :   BColorModifier()
         {
-            return (maBColor == rCompare.maBColor && mfValue == rCompare.mfValue && meMode == rCompare.meMode);
         }
 
-        bool operator!=(const BColorModifier& rCompare) const
+        virtual ~BColorModifier_invert();
+
+        // compare operator
+        virtual bool operator==(const BColorModifier& rCompare) const;
+
+        // compute modified color
+        virtual ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& aSourceColor) const;
+    };
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    /** convert to alpha based on luminance
+
+        returns a color where red green and blue are first weighted and added
+        to build a luminance value which is then inverted and used for red,
+        green and blue. The weights are  r * 0.2125 + g * 0.7154 + b * 0.0721.
+        This derivation is used for the svg importer and does exactly what SVG
+        defines for this needed case.
+    */
+    class BColorModifier_luminance_to_alpha : public BColorModifier
+    {
+    private:
+    protected:
+    public:
+        BColorModifier_luminance_to_alpha()
+        :   BColorModifier()
+        {
+        }
+
+        virtual ~BColorModifier_luminance_to_alpha();
+
+        // compare operator
+        virtual bool operator==(const BColorModifier& rCompare) const;
+
+        // compute modified color
+        virtual ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& aSourceColor) const;
+    };
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    /** replace color
+
+        does not use the source color at all, but always returns the
+        given color, replacing everything. Useful e.g. for unified shadow
+        creation
+    */
+    class BColorModifier_replace : public BColorModifier
+    {
+    private:
+        ::basegfx::BColor           maBColor;
+
+    protected:
+    public:
+        BColorModifier_replace(const ::basegfx::BColor& rBColor)
+        :   BColorModifier(),
+            maBColor(rBColor)
         {
-            return !(operator==(rCompare));
         }
 
+        virtual ~BColorModifier_replace();
+
         // data access
         const ::basegfx::BColor& getBColor() const { return maBColor; }
+
+        // compare operator
+        virtual bool operator==(const BColorModifier& rCompare) const;
+
+        // compute modified color
+        virtual ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& aSourceColor) const;
+    };
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    /** interpolate color
+
+        returns an interpolated color mixed by the given value (f) in the range
+        [0.0 .. 1.0] and the given color (col) as follows:
+
+        col * (1 - f) + aSourceColor * f
+    */
+    class BColorModifier_interpolate : public BColorModifier
+    {
+    private:
+        ::basegfx::BColor           maBColor;
+        double                      mfValue;
+
+    protected:
+    public:
+        BColorModifier_interpolate(const ::basegfx::BColor& rBColor, double fValue)
+        :   BColorModifier(),
+            maBColor(rBColor),
+            mfValue(fValue)
+        {
+        }
+
+        virtual ~BColorModifier_interpolate();
+
+        // data access
+        const ::basegfx::BColor& getBColor() const { return maBColor; }
+        double getValue() const { return mfValue; }
+
+        // compare operator
+        virtual bool operator==(const BColorModifier& rCompare) const;
+
+        // compute modified color
+        virtual ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& aSourceColor) const;
+    };
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    /** convert color to black and white
+
+        returns black when the luminance of the given color is less than
+        the given treshhold value in the range [0.0 .. 1.0], else white
+    */
+    class BColorModifier_black_and_white : public BColorModifier
+    {
+    private:
+        double                      mfValue;
+
+    protected:
+    public:
+        BColorModifier_black_and_white(double fValue)
+        :   BColorModifier(),
+            mfValue(fValue)
+        {
+        }
+
+        virtual ~BColorModifier_black_and_white();
+
+        // data access
+        double getValue() const { return mfValue; }
+
+        // compare operator
+        virtual bool operator==(const BColorModifier& rCompare) const;
+
+        // compute modified color
+        virtual ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& aSourceColor) const;
+    };
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    /** gamma correction
+
+        Input is a gamma correction value in the range ]0.0 .. 10.0]; the
+        color values get correted using
+
+        col(r,g,b) = clamp(pow(col(r,g,b), 1.0 / gamma), 0.0, 1.0)
+    */
+    class BColorModifier_gamma : public BColorModifier
+    {
+    private:
+        double                      mfValue;
+        double                      mfInvValue;
+
+        /// bitfield
+        bool                        mbUseIt : 1;
+
+    protected:
+    public:
+        BColorModifier_gamma(double fValue);
+
+        virtual ~BColorModifier_gamma();
+
+        // data access
         double getValue() const { return mfValue; }
-        BColorModifyMode getMode() const { return meMode; }
+
+        // compare operator
+        virtual bool operator==(const BColorModifier& rCompare) const;
+
+        // compute modified color
+        virtual ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& aSourceColor) const;
+    };
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    /** Red, Green, Blue, Luminance and Contrast correction
+
+        Input are percent values from [-1.0 .. 1-0] which correspond to -100% to 100%
+        correction of Red, Green, Blue, Luminance or Contrast. 0.0 means no change of
+        the corresponding channel. All these are combined (but can be used single) to
+        - be able to cover a bigger change range utilizing the cmobination
+        - allow execution by a small, common, precalculated table
+    */
+    class BColorModifier_RGBLuminanceContrast : public BColorModifier
+    {
+    private:
+        double                      mfRed;
+        double                      mfGreen;
+        double                      mfBlue;
+        double                      mfLuminance;
+        double                      mfContrast;
+
+        double                      mfContrastOff;
+        double                      mfRedOff;
+        double                      mfGreenOff;
+        double                      mfBlueOff;
+
+        /// bitfield
+        bool                        mbUseIt : 1;
+
+    protected:
+    public:
+        BColorModifier_RGBLuminanceContrast(double fRed, double fGreen, double fBlue, double fLuminance, double fContrast);
+
+        virtual ~BColorModifier_RGBLuminanceContrast();
+
+        // data access
+        double getRed() const { return mfRed; }
+        double getGreen() const { return mfGreen; }
+        double getBlue() const { return mfBlue; }
+        double getLuminance() const { return mfLuminance; }
+        double getContrast() const { return mfContrast; }
+
+        // compare operator
+        virtual bool operator==(const BColorModifier& rCompare) const;
 
         // compute modified color
-        ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& aSourceColor) const;
+        virtual ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& aSourceColor) const;
     };
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    /// typedef to allow working with shared instances of BColorModifier
+    /// for the whole mechanism
+    typedef ::boost::shared_ptr< BColorModifier > BColorModifierSharedPtr;
 
-    /** Class to hold a stack of BColorModifiers and to get the modified color with
-        applying all existing entry changes
+    /** Class to hold a stack of BColorModifierSharedPtrs and to get the modified color with
+        applying all existing entry changes as defined in the stack. Instances of BColorModifier
+        can be pushed and popped to change the stack.
+
+        All references to BColorModifier members use shared pointers, thus instances of
+        BColorModifierStack can be copied by the default mechanisms if needed.
     */
     class BColorModifierStack
     {
     protected:
-        ::std::vector< BColorModifier >             maBColorModifiers;
+        ::std::vector< BColorModifierSharedPtr >        maBColorModifiers;
 
     public:
         sal_uInt32 count() const
@@ -97,33 +396,17 @@ namespace basegfx
             return maBColorModifiers.size();
         }
 
-        const BColorModifier& getBColorModifier(sal_uInt32 nIndex) const
+        const BColorModifierSharedPtr& getBColorModifier(sal_uInt32 nIndex) const
         {
             OSL_ENSURE(nIndex < count(), "BColorModifierStack: Access out of range (!)");
             return maBColorModifiers[nIndex];
         }
 
-        ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& rSource) const
-        {
-            if(count())
-            {
-                ::basegfx::BColor aRetval(rSource);
-                ::std::vector< BColorModifier >::const_iterator aEnd(maBColorModifiers.end());
-
-                while(aEnd != maBColorModifiers.begin())
-                {
-                    aRetval = (--aEnd)->getModifiedColor(aRetval);
-                }
-
-                return aRetval;
-            }
-            else
-            {
-                return rSource;
-            }
-        }
+        // get the color in it's modified form by applying all existing BColorModifiers,
+        // from back to front (the newest first)
+        ::basegfx::BColor getModifiedColor(const ::basegfx::BColor& rSource) const;
 
-        void push(const BColorModifier& rNew)
+        void push(const BColorModifierSharedPtr& rNew)
         {
             maBColorModifiers.push_back(rNew);
         }
@@ -135,6 +418,8 @@ namespace basegfx
     };
 } // end of namespace basegfx
 
+//////////////////////////////////////////////////////////////////////////////
+
 #endif // _BGFX_COLOR_BCOLORMODIFIER_HXX
 
 //////////////////////////////////////////////////////////////////////////////
diff --git a/basegfx/source/color/bcolormodifier.cxx b/basegfx/source/color/bcolormodifier.cxx
index 517fe41..67ad154 100644
--- a/basegfx/source/color/bcolormodifier.cxx
+++ b/basegfx/source/color/bcolormodifier.cxx
@@ -19,8 +19,6 @@
  *
  *************************************************************/
 
-
-
 // MARKER(update_precomp.py): autogen include statement, do not remove
 #include "precompiled_basegfx.hxx"
 
@@ -30,46 +28,314 @@
 
 namespace basegfx
 {
-    ::basegfx::BColor BColorModifier::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
+    BColorModifier::~BColorModifier()
+    {
+    }
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    BColorModifier_gray::~BColorModifier_gray()
+    {
+    }
+
+    bool BColorModifier_gray::operator==(const BColorModifier& rCompare) const
+    {
+        return 0 != dynamic_cast< const BColorModifier_gray* >(&rCompare);
+    }
+
+    ::basegfx::BColor BColorModifier_gray::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
+    {
+        const double fLuminance(aSourceColor.luminance());
+
+        return ::basegfx::BColor(fLuminance, fLuminance, fLuminance);
+    }
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    BColorModifier_invert::~BColorModifier_invert()
+    {
+    }
+
+    bool BColorModifier_invert::operator==(const BColorModifier& rCompare) const
+    {
+        return 0 != dynamic_cast< const BColorModifier_invert* >(&rCompare);
+    }
+
+    ::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());
+    }
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    BColorModifier_luminance_to_alpha::~BColorModifier_luminance_to_alpha()
+    {
+    }
+
+    bool BColorModifier_luminance_to_alpha::operator==(const BColorModifier& rCompare) const
+    {
+        return 0 != dynamic_cast< const BColorModifier_luminance_to_alpha* >(&rCompare);
+    }
+
+    ::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)));
+
+        return ::basegfx::BColor(fAlpha, fAlpha, fAlpha);
+    }
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    BColorModifier_replace::~BColorModifier_replace()
+    {
+    }
+
+    bool BColorModifier_replace::operator==(const BColorModifier& rCompare) const
     {
-        switch(meMode)
+        const BColorModifier_replace* pCompare = dynamic_cast< const BColorModifier_replace* >(&rCompare);
+
+        if(!pCompare)
         {
-            case BCOLORMODIFYMODE_INTERPOLATE :
-            {
-                return interpolate(maBColor, aSourceColor, mfValue);
-            }
-            case BCOLORMODIFYMODE_GRAY :
-            {
-                const double fLuminance(aSourceColor.luminance());
-                return ::basegfx::BColor(fLuminance, fLuminance, fLuminance);
-            }
-            case BCOLORMODIFYMODE_BLACKANDWHITE :
-            {
-                const double fLuminance(aSourceColor.luminance());
-
-                if(fLuminance < mfValue)
-                {
-                    return ::basegfx::BColor::getEmptyBColor();
-                }
-                else
-                {
-                    return ::basegfx::BColor(1.0, 1.0, 1.0);
-                }
-            }
-            case BCOLORMODIFYMODE_INVERT :
-            {
-                return ::basegfx::BColor(1.0 - aSourceColor.getRed(), 1.0 - aSourceColor.getGreen(), 1.0 - aSourceColor.getBlue());
-            }
-            case BCOLORMODIFYMODE_LUMINANCE_TO_ALPHA:
+            return false;
+        }
+
+        return getBColor() == pCompare->getBColor();
+    }
+
+    ::basegfx::BColor BColorModifier_replace::getModifiedColor(const ::basegfx::BColor& /*aSourceColor*/) const
+    {
+        return maBColor;
+    }
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    BColorModifier_interpolate::~BColorModifier_interpolate()
+    {
+    }
+
+    bool BColorModifier_interpolate::operator==(const BColorModifier& rCompare) const
+    {
+        const BColorModifier_interpolate* pCompare = dynamic_cast< const BColorModifier_interpolate* >(&rCompare);
+
+        if(!pCompare)
+        {
+            return false;
+        }
+
+        return getBColor() == pCompare->getBColor() && getValue() == pCompare->getValue();
+    }
+
+    ::basegfx::BColor BColorModifier_interpolate::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
+    {
+        return interpolate(maBColor, aSourceColor, mfValue);
+    }
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    BColorModifier_black_and_white::~BColorModifier_black_and_white()
+    {
+    }
+
+    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)
+        {
+            return false;
+        }
+
+        return getValue() == pCompare->getValue();
+    }
+
+    ::basegfx::BColor BColorModifier_black_and_white::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
+    {
+        const double fLuminance(aSourceColor.luminance());
+
+        if(fLuminance < mfValue)
+        {
+            return ::basegfx::BColor::getEmptyBColor();
+        }
+        else
+        {
+            return ::basegfx::BColor(1.0, 1.0, 1.0);
+        }
+    }
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    BColorModifier_gamma::BColorModifier_gamma(double fValue)
+    :   BColorModifier(),
+        mfValue(fValue),
+        mfInvValue(fValue),
+        mbUseIt(!basegfx::fTools::equal(fValue, 1.0) && basegfx::fTools::more(fValue, 0.0) && basegfx::fTools::lessOrEqual(fValue, 10.0))
+    {
+        if(mbUseIt)
+        {
+            mfInvValue = 1.0 / mfValue;
+        }
+    }
+
+    BColorModifier_gamma::~BColorModifier_gamma()
+    {
+    }
+
+    bool BColorModifier_gamma::operator==(const BColorModifier& rCompare) const
+    {
+        const BColorModifier_gamma* pCompare = dynamic_cast< const BColorModifier_gamma* >(&rCompare);
+
+        if(!pCompare)
+        {
+            return false;
+        }
+
+        // getValue is sufficient, mfInvValue and mbUseIt are only helper values
+        return getValue() == pCompare->getValue();
+    }
+
+    ::basegfx::BColor BColorModifier_gamma::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
+    {
+        if(mbUseIt)
+        {
+            ::basegfx::BColor aRetval(
+                pow(aSourceColor.getRed(), mfInvValue),
+                pow(aSourceColor.getGreen(), mfInvValue),
+                pow(aSourceColor.getBlue(), mfInvValue));
+
+            aRetval.clamp();
+            return aRetval;
+        }
+        else
+        {
+            return aSourceColor;
+        }
+    }
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    BColorModifier_RGBLuminanceContrast::BColorModifier_RGBLuminanceContrast(double fRed, double fGreen, double fBlue, double fLuminance, double fContrast)
+    :   BColorModifier(),
+        mfRed(basegfx::clamp(fRed, -1.0, 1.0)),
+        mfGreen(basegfx::clamp(fGreen, -1.0, 1.0)),
+        mfBlue(basegfx::clamp(fBlue, -1.0, 1.0)),
+        mfLuminance(basegfx::clamp(fLuminance, -1.0, 1.0)),
+        mfContrast(basegfx::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)
+            || !basegfx::fTools::equalZero(mfBlue)
+            || !basegfx::fTools::equalZero(mfLuminance)
+            || !basegfx::fTools::equalZero(mfContrast))
+        {
+            // calculate slope
+            if(mfContrast >= 0.0)
             {
-                const double fAlpha(1.0 - ((aSourceColor.getRed() * 0.2125) + (aSourceColor.getGreen() * 0.7154) + (aSourceColor.getBlue() * 0.0721)));
-                return ::basegfx::BColor(fAlpha, fAlpha, fAlpha);
+                mfContrastOff = 128.0 / (128.0 - (mfContrast * 127.0));
             }
-            default : // BCOLORMODIFYMODE_REPLACE
+            else
             {
-                return maBColor;
+                mfContrastOff = ( 128.0 + (mfContrast * 127.0)) / 128.0;
             }
+
+            // calculate unified contrast offset
+            const double fPreparedContrastOff((128.0 - mfContrastOff * 128.0) / 255.0);
+            const double fCombinedOffset(mfLuminance + fPreparedContrastOff);
+
+            // set full offsets
+            mfRedOff = mfRed + fCombinedOffset;
+            mfGreenOff = mfGreen + fCombinedOffset;
+            mfBlueOff = mfBlue + fCombinedOffset;
+
+            mbUseIt = true;
+        }
+    }
+
+    BColorModifier_RGBLuminanceContrast::~BColorModifier_RGBLuminanceContrast()
+    {
+    }
+
+    bool BColorModifier_RGBLuminanceContrast::operator==(const BColorModifier& rCompare) const
+    {
+        const BColorModifier_RGBLuminanceContrast* pCompare = dynamic_cast< const BColorModifier_RGBLuminanceContrast* >(&rCompare);
+
+        if(!pCompare)
+        {
+            return false;
         }
+
+        // no need to compare other values, these are just helpers
+        return getRed() == pCompare->getRed()
+            && getGreen() == pCompare->getGreen()
+            && getBlue() == pCompare->getBlue()
+            && getLuminance() == pCompare->getLuminance()
+            && getContrast() == pCompare->getContrast();
+    }
+
+    ::basegfx::BColor BColorModifier_RGBLuminanceContrast::getModifiedColor(const ::basegfx::BColor& aSourceColor) const
+    {
+        if(mbUseIt)
+        {
+            return basegfx::BColor(
+                basegfx::clamp(aSourceColor.getRed() * mfContrastOff + mfRedOff, 0.0, 1.0),
+                basegfx::clamp(aSourceColor.getGreen() * mfContrastOff + mfGreenOff, 0.0, 1.0),
+                basegfx::clamp(aSourceColor.getBlue() * mfContrastOff + mfBlueOff, 0.0, 1.0));
+        }
+        else
+        {
+            return aSourceColor;
+        }
+    }
+} // end of namespace basegfx
+
+//////////////////////////////////////////////////////////////////////////////
+
+namespace basegfx
+{
+    ::basegfx::BColor BColorModifierStack::getModifiedColor(const ::basegfx::BColor& rSource) const
+    {
+        if(maBColorModifiers.empty())
+        {
+            return rSource;
+        }
+
+        ::basegfx::BColor aRetval(rSource);
+
+        for(sal_uInt32 a(maBColorModifiers.size()); a;)
+        {
+            a--;
+            aRetval = maBColorModifiers[a]->getModifiedColor(aRetval);
+        }
+
+        return aRetval;
     }
 } // end of namespace basegfx
 
diff --git a/drawinglayer/inc/drawinglayer/primitive2d/graphicprimitivehelper2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/graphicprimitivehelper2d.hxx
index e47ad3e..3247d11 100755
--- a/drawinglayer/inc/drawinglayer/primitive2d/graphicprimitivehelper2d.hxx
+++ b/drawinglayer/inc/drawinglayer/primitive2d/graphicprimitivehelper2d.hxx
@@ -19,13 +19,12 @@
  *
  *************************************************************/
 
-
-
 #ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_GRAPHICPRIMITIVEHELPER2D_HXX
 #define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_GRAPHICPRIMITIVEHELPER2D_HXX
 
 #include <drawinglayer/drawinglayerdllapi.h>
 #include <drawinglayer/primitive2d/baseprimitive2d.hxx>
+#include <svtools/grfmgr.hxx>
 
 //////////////////////////////////////////////////////////////////////////////
 // predefines
@@ -49,6 +48,22 @@ namespace drawinglayer
         Primitive2DSequence create2DDecompositionOfGraphic(
             const Graphic& rGraphic,
             const basegfx::B2DHomMatrix& rTransform);
+
+        /** Helper to embed given sequence of primitives to evtl. a stack
+            of ModifiedColorPrimitive2D's to get all the needed modifications
+            applied.
+        */
+        Primitive2DSequence create2DColorModifierEmbeddingsAsNeeded(
+            const Primitive2DSequence& rChildren,
+            GraphicDrawMode aGraphicDrawMode = GRAPHICDRAWMODE_STANDARD,
+            double fLuminance = 0.0,        // [-1.0 .. 1.0]
+            double fContrast = 0.0,         // [-1.0 .. 1.0]
+            double fRed = 0.0,              // [-1.0 .. 1.0]
+            double fGreen = 0.0,            // [-1.0 .. 1.0]
+            double fBlue = 0.0,             // [-1.0 .. 1.0]
+            double fGamma = 1.0,            // ]0.0 .. 10.0]
+            bool bInvert = false);
+
     } // end of namespace primitive2d
 } // end of namespace drawinglayer
 
diff --git a/drawinglayer/inc/drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx b/drawinglayer/inc/drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx
index 98d1295..3a9cd0e 100644
--- a/drawinglayer/inc/drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx
+++ b/drawinglayer/inc/drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx
@@ -19,8 +19,6 @@
  *
  *************************************************************/
 
-
-
 #ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE2D_MODIFIEDCOLORPRIMITIVE2D_HXX
 #define INCLUDED_DRAWINGLAYER_PRIMITIVE2D_MODIFIEDCOLORPRIMITIVE2D_HXX
 
@@ -45,7 +43,7 @@ namespace drawinglayer
             For the possibilities of color modifications, please refer
             to the basegfx::BColorModifier definitions in basegfx. For
             processing there is tooling in basegfx to build a stack of
-            BColorModifiers to always be able to proccess the correct
+            BColorModifierSharedPtrs to always be able to proccess the correct
             colors.
 
             If a renderer does not handle this primitive, the content will
@@ -55,16 +53,16 @@ namespace drawinglayer
         {
         private:
             /// The ColorModifier to use
-            basegfx::BColorModifier                 maColorModifier;
+            basegfx::BColorModifierSharedPtr        maColorModifier;
 
         public:
             /// constructor
             ModifiedColorPrimitive2D(
                 const Primitive2DSequence& rChildren,
-                const basegfx::BColorModifier& rColorModifier);
+                const basegfx::BColorModifierSharedPtr& rColorModifier);
 
             /// data read access
-            const basegfx::BColorModifier& getColorModifier() const { return maColorModifier; }
+            const basegfx::BColorModifierSharedPtr& getColorModifier() const { return maColorModifier; }
 
             /// compare operator
             virtual bool operator==(const BasePrimitive2D& rPrimitive) const;
diff --git a/drawinglayer/inc/drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx b/drawinglayer/inc/drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx
index f26a730..38e5abf 100644
--- a/drawinglayer/inc/drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx
+++ b/drawinglayer/inc/drawinglayer/primitive3d/modifiedcolorprimitive3d.hxx
@@ -19,8 +19,6 @@
  *
  *************************************************************/
 
-
-
 #ifndef INCLUDED_DRAWINGLAYER_PRIMITIVE3D_MODIFIEDCOLORPRIMITIVE3D_HXX
 #define INCLUDED_DRAWINGLAYER_PRIMITIVE3D_MODIFIEDCOLORPRIMITIVE3D_HXX
 
@@ -45,16 +43,16 @@ namespace drawinglayer
         {
         private:
             /// The ColorModifier to use
-            basegfx::BColorModifier                 maColorModifier;
+            basegfx::BColorModifierSharedPtr        maColorModifier;
 
         public:
             /// constructor
             ModifiedColorPrimitive3D(
                 const Primitive3DSequence& rChildren,
-                const basegfx::BColorModifier& rColorModifier);
+                const basegfx::BColorModifierSharedPtr& rColorModifier);
 
             /// data read access
-            const basegfx::BColorModifier& getColorModifier() const { return maColorModifier; }
+            const basegfx::BColorModifierSharedPtr& getColorModifier() const { return maColorModifier; }
 
             /// compare operator
             virtual bool operator==(const BasePrimitive3D& rPrimitive) const;
diff --git a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
index b19c6c8..fc51889 100644
--- a/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/graphicprimitive2d.cxx
@@ -19,8 +19,6 @@
  *
  *************************************************************/
 
-
-
 // MARKER(update_precomp.py): autogen include statement, do not remove
 #include "precompiled_drawinglayer.hxx"
 
@@ -29,6 +27,8 @@
 #include <drawinglayer/primitive2d/drawinglayer_primitivetypes2d.hxx>
 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
 #include <drawinglayer/primitive2d/graphicprimitivehelper2d.hxx>
+#include <drawinglayer/primitive2d/unifiedtransparenceprimitive2d.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
 #include <basegfx/matrix/b2dhommatrixtools.hxx>
 #include <vcl/svapp.hxx>
 #include <vcl/outdev.hxx>
@@ -49,79 +49,151 @@ namespace drawinglayer
         {
             Primitive2DSequence aRetval;
 
-            if(255L != getGraphicAttr().GetTransparency())
+            if(255L == getGraphicAttr().GetTransparency())
             {
-                // do not apply mirroring from GraphicAttr to the Metafile by calling
-                // GetTransformedGraphic, this will try to mirror the Metafile using Scale()
-                // at the Metafile. This again calls Scale at the single MetaFile actions,
-                // but this implementation never worked. I reworked that implementations,
-                // but for security reasons i will try not to use it.
-                basegfx::B2DHomMatrix aTransform(getTransform());
-
-                if(getGraphicAttr().IsMirrored())
-                {
-                    // content needs mirroring
-                    const bool bHMirr(getGraphicAttr().GetMirrorFlags() & BMP_MIRROR_HORZ);
-                    const bool bVMirr(getGraphicAttr().GetMirrorFlags() & BMP_MIRROR_VERT);
-
-                    // mirror by applying negative scale to the unit primitive and
-                    // applying the object transformation on it.
-                    aTransform = basegfx::tools::createScaleB2DHomMatrix(
-                        bHMirr ? -1.0 : 1.0,
-                        bVMirr ? -1.0 : 1.0);
-                    aTransform.translate(
-                        bHMirr ? 1.0 : 0.0,
-                        bVMirr ? 1.0 : 0.0);
-                    aTransform = getTransform() * aTransform;
-                }
+                // content is invisible, done
+                return aRetval;
+            }
+
+            // do not apply mirroring from GraphicAttr to the Metafile by calling
+            // GetTransformedGraphic, this will try to mirror the Metafile using Scale()
+            // at the Metafile. This again calls Scale at the single MetaFile actions,
+            // but this implementation never worked. I reworked that implementations,
+            // but for security reasons i will try not to use it.
+            basegfx::B2DHomMatrix aTransform(getTransform());
+
+            if(getGraphicAttr().IsMirrored())
+            {
+                // content needs mirroring
+                const bool bHMirr(getGraphicAttr().GetMirrorFlags() & BMP_MIRROR_HORZ);
+                const bool bVMirr(getGraphicAttr().GetMirrorFlags() & BMP_MIRROR_VERT);
+
+                // mirror by applying negative scale to the unit primitive and
+                // applying the object transformation on it.
+                aTransform = basegfx::tools::createScaleB2DHomMatrix(
+                    bHMirr ? -1.0 : 1.0,
+                    bVMirr ? -1.0 : 1.0);
+                aTransform.translate(
+                    bHMirr ? 1.0 : 0.0,
+                    bVMirr ? 1.0 : 0.0);
+                aTransform = getTransform() * aTransform;
+            }
+
+            // Get transformed graphic. Suppress rotation and cropping, only filtering is needed
+            // here (and may be replaced later on). Cropping is handled below as mask primitive (if set).
+            // Also need to suppress mirroring, it is part of the transformation now (see above).
+            // Also move transparency handling to embedding to a UnifiedTransparencePrimitive2D; do
+            // that by remembering original transparency and applying that later if needed
+            GraphicAttr aSuppressGraphicAttr(getGraphicAttr());
+
+            aSuppressGraphicAttr.SetCrop(0, 0, 0, 0);
+            aSuppressGraphicAttr.SetRotation(0);
+            aSuppressGraphicAttr.SetMirrorFlags(0);
+            aSuppressGraphicAttr.SetTransparency(0);
+
+            const GraphicObject& rGraphicObject = getGraphicObject();
+            Graphic aTransformedGraphic(rGraphicObject.GetGraphic());
+            const bool isBitmap(GRAPHIC_BITMAP == aTransformedGraphic.GetType() && !aTransformedGraphic.getSvgData().get());
+            const bool isAdjusted(getGraphicAttr().IsAdjusted());
+            const bool isDrawMode(GRAPHICDRAWMODE_STANDARD != getGraphicAttr().GetDrawMode());
+
+            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 explicitely want to have the
+                // pure primitive solution for this; this will allow vector graphics to stay vector
+                // geraphics, 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 loose any quality.
+                aTransformedGraphic = rGraphicObject.GetTransformedGraphic(&aSuppressGraphicAttr);
+
+                // reset GraphicAttr after use to not apply double
+                aSuppressGraphicAttr = GraphicAttr();
+            }
 
-                // Get transformed graphic. Suppress rotation and cropping, only filtering is needed
-                // here (and may be replaced later on). Cropping is handled below as mask primitive (if set).
-                // Also need to suppress mirroring, it is part of the transformation now (see above).
-                GraphicAttr aSuppressGraphicAttr(getGraphicAttr());
-                aSuppressGraphicAttr.SetCrop(0, 0, 0, 0);
-                aSuppressGraphicAttr.SetRotation(0);
-                aSuppressGraphicAttr.SetMirrorFlags(0);
+            // create sub-content; helper takes care of correct handling of
+            // bitmap, svg or metafile content
+            aRetval = create2DDecompositionOfGraphic(
+                aTransformedGraphic,
+                aTransform);
 
-                const GraphicObject& rGraphicObject = getGraphicObject();
-                const Graphic aTransformedGraphic(rGraphicObject.GetTransformedGraphic(&aSuppressGraphicAttr));
+            if(!aRetval.getLength())
+            {
+                // content is invisible, done
+                return aRetval;
+            }
+
+            if(isAdjusted || isDrawMode)
+            {
+                // embed to needed ModifiedColorPrimitive2D's if necessary. Do this for
+                // adjustments and draw mode specials
+                aRetval = create2DColorModifierEmbeddingsAsNeeded(
+                    aRetval,
+                    aSuppressGraphicAttr.GetDrawMode(),
+                    basegfx::clamp(aSuppressGraphicAttr.GetLuminance() * 0.01, -1.0, 1.0),
+                    basegfx::clamp(aSuppressGraphicAttr.GetContrast() * 0.01, -1.0, 1.0),
+                    basegfx::clamp(aSuppressGraphicAttr.GetChannelR() * 0.01, -1.0, 1.0),
+                    basegfx::clamp(aSuppressGraphicAttr.GetChannelG() * 0.01, -1.0, 1.0),
+                    basegfx::clamp(aSuppressGraphicAttr.GetChannelB() * 0.01, -1.0, 1.0),
+                    basegfx::clamp(aSuppressGraphicAttr.GetGamma(), 0.0, 10.0),
+                    aSuppressGraphicAttr.IsInvert());
+
+                if(!aRetval.getLength())
+                {
+                    // content is invisible, done
+                    return aRetval;
+                }
+            }
 
-                aRetval = create2DDecompositionOfGraphic(
-                    aTransformedGraphic,
-                    aTransform);
+            if(getGraphicAttr().IsTransparent())
+            {
+                // check for transparency
+                const double fTransparency(basegfx::clamp(getGraphicAttr().GetTransparency() * (1.0 / 255.0), 0.0, 1.0));
 
-                if(aRetval.getLength())
+                if(!basegfx::fTools::equalZero(fTransparency))
                 {
-                    // check for cropping
-                    if(getGraphicAttr().IsCropped())
-                    {
-                        // calculate scalings between real image size and logic object size. This
-                        // is necessary since the crop values are relative to original bitmap size
-                        const basegfx::B2DVector aObjectScale(aTransform * basegfx::B2DVector(1.0, 1.0));
-                        const basegfx::B2DVector aCropScaleFactor(
-                            rGraphicObject.calculateCropScaling(
-                                aObjectScale.getX(),
-                                aObjectScale.getY(),
-                                getGraphicAttr().GetLeftCrop(),
-                                getGraphicAttr().GetTopCrop(),
-                                getGraphicAttr().GetRightCrop(),
-                                getGraphicAttr().GetBottomCrop()));
-
-                        // embed content in cropPrimitive
-                        Primitive2DReference xPrimitive(
-                            new CropPrimitive2D(
-                                aRetval,
-                                aTransform,
-                                getGraphicAttr().GetLeftCrop() * aCropScaleFactor.getX(),
-                                getGraphicAttr().GetTopCrop() * aCropScaleFactor.getY(),
-                                getGraphicAttr().GetRightCrop() * aCropScaleFactor.getX(),
-                                getGraphicAttr().GetBottomCrop() * aCropScaleFactor.getY()));
-
-                        aRetval = Primitive2DSequence(&xPrimitive, 1);
-                    }
+                    const Primitive2DReference aUnifiedTransparence(
+                        new UnifiedTransparencePrimitive2D(
+                            aRetval,
+                            fTransparency));
+
+                    aRetval = Primitive2DSequence(&aUnifiedTransparence, 1);
                 }
             }
 
+            if(getGraphicAttr().IsCropped())
+            {
+                // check for cropping
+                // calculate scalings between real image size and logic object size. This
+                // is necessary since the crop values are relative to original bitmap size
+                const basegfx::B2DVector aObjectScale(aTransform * basegfx::B2DVector(1.0, 1.0));
+                const basegfx::B2DVector aCropScaleFactor(
+                    rGraphicObject.calculateCropScaling(
+                        aObjectScale.getX(),
+                        aObjectScale.getY(),
+                        getGraphicAttr().GetLeftCrop(),
+                        getGraphicAttr().GetTopCrop(),
+                        getGraphicAttr().GetRightCrop(),
+                        getGraphicAttr().GetBottomCrop()));
+
+                // embed content in cropPrimitive
+                Primitive2DReference xPrimitive(
+                    new CropPrimitive2D(
+                        aRetval,
+                        aTransform,
+                        getGraphicAttr().GetLeftCrop() * aCropScaleFactor.getX(),
+                        getGraphicAttr().GetTopCrop() * aCropScaleFactor.getY(),
+                        getGraphicAttr().GetRightCrop() * aCropScaleFactor.getX(),
+                        getGraphicAttr().GetBottomCrop() * aCropScaleFactor.getY()));
+
+                aRetval = Primitive2DSequence(&xPrimitive, 1);
+            }
+
             return aRetval;
         }
 
diff --git a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
index 2a672f9..7bbe180 100755
--- a/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
+++ b/drawinglayer/source/primitive2d/graphicprimitivehelper2d.cxx
@@ -19,8 +19,6 @@
  *
  *************************************************************/
 
-
-
 // MARKER(update_precomp.py): autogen include statement, do not remove
 #include "precompiled_drawinglayer.hxx"
 
@@ -31,8 +29,10 @@
 #include <drawinglayer/primitive2d/metafileprimitive2d.hxx>
 #include <drawinglayer/primitive2d/transformprimitive2d.hxx>
 #include <drawinglayer/primitive2d/maskprimitive2d.hxx>
+#include <drawinglayer/primitive2d/modifiedcolorprimitive2d.hxx>
 #include <basegfx/polygon/b2dpolygon.hxx>
 #include <basegfx/polygon/b2dpolygontools.hxx>
+#include <basegfx/numeric/ftools.hxx>
 
 //////////////////////////////////////////////////////////////////////////////
 // helper class for animated graphics
@@ -783,4 +783,137 @@ namespace drawinglayer
 } // end of namespace drawinglayer
 
 //////////////////////////////////////////////////////////////////////////////
+
+namespace drawinglayer
+{
+    namespace primitive2d
+    {
+        Primitive2DSequence create2DColorModifierEmbeddingsAsNeeded(
+            const Primitive2DSequence& rChildren,
+            GraphicDrawMode aGraphicDrawMode,
+            double fLuminance,
+            double fContrast,
+            double fRed,
+            double fGreen,
+            double fBlue,
+            double fGamma,
+            bool bInvert)
+        {
+            Primitive2DSequence aRetval;
+
+            if(!rChildren.getLength())
+            {
+                // no child content, done
+                return aRetval;
+            }
+
+            // set child content as retval; that is what will be used as child content in all
+            // embeddings from here
+            aRetval = rChildren;
+
+            if(GRAPHICDRAWMODE_WATERMARK == aGraphicDrawMode)
+            {
+                // this is solved by applying fixed values additionally to luminance
+                // and contrast, do it here and reset DrawMode to GRAPHICDRAWMODE_STANDARD
+                // original in svtools uses:
+                // #define WATERMARK_LUM_OFFSET        50
+                // #define WATERMARK_CON_OFFSET        -70
+                fLuminance = basegfx::clamp(fLuminance + 0.5, -1.0, 1.0);
+                fContrast = basegfx::clamp(fContrast - 0.7, -1.0, 1.0);
+                aGraphicDrawMode = GRAPHICDRAWMODE_STANDARD;
+            }
+
+            // DrawMode (GRAPHICDRAWMODE_WATERMARK already handled)
+            switch(aGraphicDrawMode)
+            {
+                case GRAPHICDRAWMODE_GREYS:
+                {
+                    // convert to grey
+                    const Primitive2DReference aPrimitiveGrey(
+                        new ModifiedColorPrimitive2D(
+                            aRetval,
+                            basegfx::BColorModifierSharedPtr(
+                                new basegfx::BColorModifier_gray())));
+
+                    aRetval = Primitive2DSequence(&aPrimitiveGrey, 1);
+                    break;
+                }
+                case GRAPHICDRAWMODE_MONO:
+                {
+                    // convert to mono (black/white with threshold 0.5)
+                    const Primitive2DReference aPrimitiveBlackAndWhite(
+                        new ModifiedColorPrimitive2D(
+                            aRetval,
+                            basegfx::BColorModifierSharedPtr(
+                                new basegfx::BColorModifier_black_and_white(0.5))));
+
+                    aRetval = Primitive2DSequence(&aPrimitiveBlackAndWhite, 1);
+                    break;
+                }
+                case GRAPHICDRAWMODE_WATERMARK:
+                {
+                    OSL_ENSURE(false, "OOps, GRAPHICDRAWMODE_WATERMARK should already be handled (see above)");
+                    // fallthrough intended
+                }
+                default: // case GRAPHICDRAWMODE_STANDARD:
+                {
+                    // nothing to do
+                    break;
+                }
+            }
+
+            // mnContPercent, mnLumPercent, mnRPercent, mnGPercent, mnBPercent
+            // handled in a single call
+            if(!basegfx::fTools::equalZero(fLuminance)
+                || !basegfx::fTools::equalZero(fContrast)
+                || !basegfx::fTools::equalZero(fRed)
+                || !basegfx::fTools::equalZero(fGreen)
+                || !basegfx::fTools::equalZero(fBlue))
+            {
+                const Primitive2DReference aPrimitiveRGBLuminannceContrast(
+                    new ModifiedColorPrimitive2D(
+                        aRetval,
+                        basegfx::BColorModifierSharedPtr(
+                            new basegfx::BColorModifier_RGBLuminanceContrast(
+                                fRed,
+                                fGreen,
+                                fBlue,
+                                fLuminance,
+                                fContrast))));
+
+                aRetval = Primitive2DSequence(&aPrimitiveRGBLuminannceContrast, 1);
+            }
+
+            // gamma (boolean)
+            if(!basegfx::fTools::equal(fGamma, 1.0))
+            {
+                const Primitive2DReference aPrimitiveGamma(
+                    new ModifiedColorPrimitive2D(
+                        aRetval,
+                        basegfx::BColorModifierSharedPtr(
+                            new basegfx::BColorModifier_gamma(
+                                fGamma))));
+
+                aRetval = Primitive2DSequence(&aPrimitiveGamma, 1);
+            }
+
+            // invert (boolean)
+            if(bInvert)
+            {
+                const Primitive2DReference aPrimitiveInvert(
+                    new ModifiedColorPrimitive2D(
+                        aRetval,
+                        basegfx::BColorModifierSharedPtr(
+                            new basegfx::BColorModifier_invert())));
+
+                aRetval = Primitive2DSequence(&aPrimitiveInvert, 1);
+            }
+
+            return aRetval;
+        }
+
+    } // end of namespace primitive2d
+} // end of namespace drawinglayer
+
+//////////////////////////////////////////////////////////////////////////////
 // eof
diff --git a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
index 5cc78f1..de67a51 100644
--- a/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/metafileprimitive2d.cxx
@@ -1063,7 +1063,9 @@ namespace
                     rTargetHolders.Current().append(
                         new drawinglayer::primitive2d::ModifiedColorPrimitive2D(
                             aSubContent,
-                            basegfx::BColorModifier(basegfx::BColor(0.0, 0.0, 0.0))));
+                            basegfx::BColorModifierSharedPtr(
+                                new basegfx::BColorModifier_replace(
+                                    basegfx::BColor(0.0, 0.0, 0.0)))));
                 }
                 else // if(rPropertyHolders.Current().isRasterOpInvert())
                 {
diff --git a/drawinglayer/source/primitive2d/modifiedcolorprimitive2d.cxx b/drawinglayer/source/primitive2d/modifiedcolorprimitive2d.cxx
index 87058e2..d575e1c 100644
--- a/drawinglayer/source/primitive2d/modifiedcolorprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/modifiedcolorprimitive2d.cxx
@@ -19,8 +19,6 @@
  *
  *************************************************************/
 
-
-
 // MARKER(update_precomp.py): autogen include statement, do not remove
 #include "precompiled_drawinglayer.hxx"
 
@@ -39,7 +37,7 @@ namespace drawinglayer
     {
         ModifiedColorPrimitive2D::ModifiedColorPrimitive2D(
             const Primitive2DSequence& rChildren,
-            const basegfx::BColorModifier& rColorModifier)
+            const basegfx::BColorModifierSharedPtr& rColorModifier)
         :   GroupPrimitive2D(rChildren),
             maColorModifier(rColorModifier)
         {
@@ -51,7 +49,17 @@ namespace drawinglayer
             {
                 const ModifiedColorPrimitive2D& rCompare = (ModifiedColorPrimitive2D&)rPrimitive;
 
-                return (getColorModifier() == rCompare.getColorModifier());
+                if(getColorModifier().get() == rCompare.getColorModifier().get())
+                {
+                    return true;
+                }
+
+                if(!getColorModifier().get() || !rCompare.getColorModifier().get())
+                {
+                    return false;
+                }
+
+                return *getColorModifier().get() == *rCompare.getColorModifier().get();
             }
 
             return false;
diff --git a/drawinglayer/source/primitive2d/shadowprimitive2d.cxx b/drawinglayer/source/primitive2d/shadowprimitive2d.cxx
index ef94387..27f9e3b 100644
--- a/drawinglayer/source/primitive2d/shadowprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/shadowprimitive2d.cxx
@@ -80,8 +80,13 @@ namespace drawinglayer
             if(getChildren().hasElements())
             {
                 // create a modifiedColorPrimitive containing the shadow color and the content
-                const basegfx::BColorModifier aBColorModifier(getShadowColor());
-                const Primitive2DReference xRefA(new ModifiedColorPrimitive2D(getChildren(), aBColorModifier));
+                const basegfx::BColorModifierSharedPtr aBColorModifier(
+                    new basegfx::BColorModifier_replace(
+                        getShadowColor()));
+                const Primitive2DReference xRefA(
+                    new ModifiedColorPrimitive2D(
+                        getChildren(),
+                        aBColorModifier));
                 const Primitive2DSequence aSequenceB(&xRefA, 1L);
 
                 // build transformed primitiveVector with shadow offset and add to target
diff --git a/drawinglayer/source/primitive2d/texteffectprimitive2d.cxx b/drawinglayer/source/primitive2d/texteffectprimitive2d.cxx
index ef9fbf6..e9f9ca6 100644
--- a/drawinglayer/source/primitive2d/texteffectprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/texteffectprimitive2d.cxx
@@ -91,20 +91,44 @@ namespace drawinglayer
                     if(bDefaultTextColor)
                     {
                         // emboss/engrave in black, original forced to white
-                        const basegfx::BColorModifier aBColorModifierToGray(basegfx::BColor(0.0));
-                        const Primitive2DReference xModifiedColor(new ModifiedColorPrimitive2D(getTextContent(), aBColorModifierToGray));
-                        aRetval[0] = Primitive2DReference(new TransformPrimitive2D(aTransform, Primitive2DSequence(&xModifiedColor, 1)));
+                        const basegfx::BColorModifierSharedPtr aBColorModifierToGray(
+                            new basegfx::BColorModifier_replace(
+                                basegfx::BColor(0.0)));
+                        const Primitive2DReference xModifiedColor(
+                            new ModifiedColorPrimitive2D(
+                                getTextContent(),
+                                aBColorModifierToGray));
+
+                        aRetval[0] = Primitive2DReference(
+                            new TransformPrimitive2D(
+                                aTransform,
+                                Primitive2DSequence(&xModifiedColor, 1)));
 
                         // add original, too
-                        const basegfx::BColorModifier aBColorModifierToWhite(basegfx::BColor(1.0));
-                        aRetval[1] = Primitive2DReference(new ModifiedColorPrimitive2D(getTextContent(), aBColorModifierToWhite));
+                        const basegfx::BColorModifierSharedPtr aBColorModifierToWhite(
+                            new basegfx::BColorModifier_replace(
+                                basegfx::BColor(1.0)));
+
+                        aRetval[1] = Primitive2DReference(
+                            new ModifiedColorPrimitive2D(
+                                getTextContent(),
+                                aBColorModifierToWhite));
                     }
                     else
                     {
                         // emboss/engrave in gray, keep original's color
-                        const basegfx::BColorModifier aBColorModifierToGray(basegfx::BColor(0.75)); // 192
-                        const Primitive2DReference xModifiedColor(new ModifiedColorPrimitive2D(getTextContent(), aBColorModifierToGray));
-                        aRetval[0] = Primitive2DReference(new TransformPrimitive2D(aTransform, Primitive2DSequence(&xModifiedColor, 1)));
+                        const basegfx::BColorModifierSharedPtr aBColorModifierToGray(
+                            new basegfx::BColorModifier_replace(
+                                basegfx::BColor(0.75))); // 192
+                        const Primitive2DReference xModifiedColor(
+                            new ModifiedColorPrimitive2D(
+                                getTextContent(),
+                                aBColorModifierToGray));
+
+                        aRetval[0] = Primitive2DReference(
+                            new TransformPrimitive2D(
+                                aTransform,
+                                Primitive2DSequence(&xModifiedColor, 1)));
 
                         // add original, too
                         aRetval[1] = Primitive2DReference(new GroupPrimitive2D(getTextContent()));
@@ -151,8 +175,13 @@ namespace drawinglayer
                     aRetval[7] = Primitive2DReference(new TransformPrimitive2D(aTransform, getTextContent()));
 
                     // at last, place original over it, but force to white
-                    const basegfx::BColorModifier aBColorModifierToWhite(basegfx::BColor(1.0, 1.0, 1.0));
-                    aRetval[8] = Primitive2DReference(new ModifiedColorPrimitive2D(getTextContent(), aBColorModifierToWhite));
+                    const basegfx::BColorModifierSharedPtr aBColorModifierToWhite(
+                        new basegfx::BColorModifier_replace(
+                            basegfx::BColor(1.0, 1.0, 1.0)));
+                    aRetval[8] = Primitive2DReference(
+                        new ModifiedColorPrimitive2D(
+                            getTextContent(),
+                            aBColorModifierToWhite));
 
                     break;
                 }
diff --git a/drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx b/drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx
index 6d59f2e..d56908b 100644
--- a/drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx
+++ b/drawinglayer/source/primitive3d/modifiedcolorprimitive3d.cxx
@@ -19,8 +19,6 @@
  *
  *************************************************************/
 
-
-
 // MARKER(update_precomp.py): autogen include statement, do not remove
 #include "precompiled_drawinglayer.hxx"
 
@@ -39,7 +37,7 @@ namespace drawinglayer
     {
         ModifiedColorPrimitive3D::ModifiedColorPrimitive3D(
             const Primitive3DSequence& rChildren,
-            const basegfx::BColorModifier& rColorModifier)
+            const basegfx::BColorModifierSharedPtr& rColorModifier)
         :   GroupPrimitive3D(rChildren),
             maColorModifier(rColorModifier)
         {
@@ -51,7 +49,17 @@ namespace drawinglayer
             {
                 const ModifiedColorPrimitive3D& rCompare = (ModifiedColorPrimitive3D&)rPrimitive;
 
-                return (maColorModifier == rCompare.maColorModifier);
+                if(getColorModifier().get() == rCompare.getColorModifier().get())
+                {
+                    return true;
+                }
+
+                if(!getColorModifier().get() || !rCompare.getColorModifier().get())
+                {
+                    return false;
+                }
+
+                return *getColorModifier().get() == *rCompare.getColorModifier().get();
             }
 
             return false;
diff --git a/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx b/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx
index 3152efa..76597b4 100644
--- a/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx
+++ b/drawinglayer/source/primitive3d/sdrdecompositiontools3d.cxx
@@ -254,8 +254,13 @@ namespace drawinglayer
                     if(::com::sun::star::drawing::TextureKind2_LUMINANCE == aSdr3DObjectAttribute.getTextureKind())
                     {
                         // use modified color primitive to force textures to gray
-                        const basegfx::BColorModifier aBColorModifier(basegfx::BColor(), 0.0, basegfx::BCOLORMODIFYMODE_GRAY);
-                        const Primitive3DReference xRef2(new ModifiedColorPrimitive3D(aRetval, aBColorModifier));
+                        const basegfx::BColorModifierSharedPtr aBColorModifier(
+                            new basegfx::BColorModifier_gray());
+                        const Primitive3DReference xRef2(
+                            new ModifiedColorPrimitive3D(
+                                aRetval,
+                                aBColorModifier));
+
                         aRetval = Primitive3DSequence(&xRef2, 1L);
                     }
                 }
diff --git a/drawinglayer/source/processor2d/vclprocessor2d.cxx b/drawinglayer/source/processor2d/vclprocessor2d.cxx
index b14fdc6..f820b0f 100644
--- a/drawinglayer/source/processor2d/vclprocessor2d.cxx
+++ b/drawinglayer/source/processor2d/vclprocessor2d.cxx
@@ -662,7 +662,7 @@ namespace drawinglayer
                 {
                     case GRAPHIC_GDIMETAFILE:
                     {
-                        // metafiles are potentially transparent, cannot optimize´, not done
+                        // metafiles are potentially transparent, cannot optimize, not done
                         break;
                     }
                     case GRAPHIC_BITMAP:
@@ -674,9 +674,10 @@ namespace drawinglayer
 
                             if(nBColorModifierStackCount)
                             {
-                                const basegfx::BColorModifier& rTopmostModifier = maBColorModifierStack.getBColorModifier(nBColorModifierStackCount - 1);
+                                const basegfx::BColorModifierSharedPtr& rTopmostModifier = maBColorModifierStack.getBColorModifier(nBColorModifierStackCount - 1);
+                                const basegfx::BColorModifier_replace* pReplacer = dynamic_cast< const basegfx::BColorModifier_replace* >(rTopmostModifier.get());
 
-                                if(basegfx::BCOLORMODIFYMODE_REPLACE == rTopmostModifier.getMode())
+                                if(pReplacer)
                                 {
                                     // the bitmap fill is in unified color, so we can replace it with
                                     // a single polygon fill. The form of the fill depends on tiling
@@ -687,7 +688,7 @@ namespace drawinglayer
 
                                         aLocalPolyPolygon.transform(maCurrentTransformation);
                                         mpOutputDevice->SetLineColor();
-                                        mpOutputDevice->SetFillColor(Color(rTopmostModifier.getBColor()));
+                                        mpOutputDevice->SetFillColor(Color(pReplacer->getBColor()));
                                         mpOutputDevice->DrawPolyPolygon(aLocalPolyPolygon);
                                     }
                                     else
@@ -719,7 +720,7 @@ namespace drawinglayer
                                         {
                                             aTarget.transform(maCurrentTransformation);
                                             mpOutputDevice->SetLineColor();
-                                            mpOutputDevice->SetFillColor(Color(rTopmostModifier.getBColor()));
+                                            mpOutputDevice->SetFillColor(Color(pReplacer->getBColor()));
                                             mpOutputDevice->DrawPolyPolygon(aTarget);
                                         }
                                     }
diff --git a/drawinglayer/source/tools/converters.cxx b/drawinglayer/source/tools/converters.cxx
index 9faef97..9ce189c 100644
--- a/drawinglayer/source/tools/converters.cxx
+++ b/drawinglayer/source/tools/converters.cxx
@@ -120,14 +120,12 @@ namespace drawinglayer
                     maContent.Erase();
 
                     // embed primitives to paint them black
-                    static basegfx::BColorModifyMode aMode = basegfx::BCOLORMODIFYMODE_REPLACE;
                     const primitive2d::Primitive2DReference xRef(
                         new primitive2d::ModifiedColorPrimitive2D(
                             aSequence,
-                            basegfx::BColorModifier(
-                                basegfx::BColor(0.0, 0.0, 0.0),
-                                0.5,
-                                aMode)));
+                            basegfx::BColorModifierSharedPtr(
+                                new basegfx::BColorModifier_replace(
+                                    basegfx::BColor(0.0, 0.0, 0.0)))));
                     const primitive2d::Primitive2DSequence xSeq(&xRef, 1);
 
                     // render
diff --git a/svgio/source/svgreader/svgmasknode.cxx b/svgio/source/svgreader/svgmasknode.cxx
index 9cc726e..26e28f5 100644
--- a/svgio/source/svgreader/svgmasknode.cxx
+++ b/svgio/source/svgreader/svgmasknode.cxx
@@ -266,10 +266,8 @@ namespace svgio
                             const drawinglayer::primitive2d::Primitive2DReference xInverseMask(
                                 new drawinglayer::primitive2d::ModifiedColorPrimitive2D(
                                     aMaskTarget,
-                                    basegfx::BColorModifier(
-                                        basegfx::BColor(0.0, 0.0, 0.0),
-                                        0.5,
-                                        basegfx::BCOLORMODIFYMODE_LUMINANCE_TO_ALPHA)));
+                                    basegfx::BColorModifierSharedPtr(
+                                        new basegfx::BColorModifier_luminance_to_alpha())));
 
                             aMaskTarget = drawinglayer::primitive2d::Primitive2DSequence(&xInverseMask, 1);
                         }
diff --git a/svx/source/sdr/contact/viewobjectcontact.cxx b/svx/source/sdr/contact/viewobjectcontact.cxx
index 255cd49..a11940ad 100644
--- a/svx/source/sdr/contact/viewobjectcontact.cxx
+++ b/svx/source/sdr/contact/viewobjectcontact.cxx
@@ -335,8 +335,15 @@ namespace sdr
                 if(isPrimitiveGhosted(rDisplayInfo))
                 {
                     const basegfx::BColor aRGBWhite(1.0, 1.0, 1.0);
-                    const basegfx::BColorModifier aBColorModifier(aRGBWhite, 0.5, basegfx::BCOLORMODIFYMODE_INTERPOLATE);
-                    const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::ModifiedColorPrimitive2D(xRetval, aBColorModifier));
+                    const basegfx::BColorModifierSharedPtr aBColorModifier(
+                        new basegfx::BColorModifier_interpolate(
+                            aRGBWhite,
+                            0.5));
+                    const drawinglayer::primitive2d::Primitive2DReference xReference(
+                        new drawinglayer::primitive2d::ModifiedColorPrimitive2D(
+                            xRetval,
+                            aBColorModifier));
+
                     xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
                 }
             }
diff --git a/svx/source/sdr/contact/viewobjectcontactofe3d.cxx b/svx/source/sdr/contact/viewobjectcontactofe3d.cxx
index bf56f55..3304af8 100644
--- a/svx/source/sdr/contact/viewobjectcontactofe3d.cxx
+++ b/svx/source/sdr/contact/viewobjectcontactofe3d.cxx
@@ -60,8 +60,15 @@ namespace sdr
             if(isPrimitiveGhosted(rDisplayInfo))
             {
                 const ::basegfx::BColor aRGBWhite(1.0, 1.0, 1.0);
-                const ::basegfx::BColorModifier aBColorModifier(aRGBWhite, 0.5, ::basegfx::BCOLORMODIFYMODE_INTERPOLATE);
-                const drawinglayer::primitive3d::Primitive3DReference xReference(new drawinglayer::primitive3d::ModifiedColorPrimitive3D(xRetval, aBColorModifier));
+                const ::basegfx::BColorModifierSharedPtr aBColorModifier(
+                    new basegfx::BColorModifier_interpolate(
+                        aRGBWhite,
+                        0.5));
+                const drawinglayer::primitive3d::Primitive3DReference xReference(
+                    new drawinglayer::primitive3d::ModifiedColorPrimitive3D(
+                        xRetval,
+                        aBColorModifier));
+
                 xRetval = drawinglayer::primitive3d::Primitive3DSequence(&xReference, 1);
             }
 
diff --git a/svx/source/sdr/contact/viewobjectcontactofe3dscene.cxx b/svx/source/sdr/contact/viewobjectcontactofe3dscene.cxx
index 2a8cb7d..ad821d8 100644
--- a/svx/source/sdr/contact/viewobjectcontactofe3dscene.cxx
+++ b/svx/source/sdr/contact/viewobjectcontactofe3dscene.cxx
@@ -114,8 +114,14 @@ namespace sdr
                 if(isPrimitiveGhosted(rDisplayInfo))
                 {
                     const ::basegfx::BColor aRGBWhite(1.0, 1.0, 1.0);
-                    const ::basegfx::BColorModifier aBColorModifier(aRGBWhite, 0.5, ::basegfx::BCOLORMODIFYMODE_INTERPOLATE);
-                    const drawinglayer::primitive2d::Primitive2DReference xReference(new drawinglayer::primitive2d::ModifiedColorPrimitive2D(xRetval, aBColorModifier));
+                    const ::basegfx::BColorModifierSharedPtr aBColorModifier(
+                        new basegfx::BColorModifier_interpolate(
+                            aRGBWhite,
+                            0.5));
+                    const drawinglayer::primitive2d::Primitive2DReference xReference(
+                        new drawinglayer::primitive2d::ModifiedColorPrimitive2D(
+                            xRetval,
+                            aBColorModifier));
 
                     xRetval = drawinglayer::primitive2d::Primitive2DSequence(&xReference, 1);
                 }
diff --git a/vcl/source/gdi/bitmapex.cxx b/vcl/source/gdi/bitmapex.cxx
index 5e34624b..d23946e 100644
--- a/vcl/source/gdi/bitmapex.cxx
+++ b/vcl/source/gdi/bitmapex.cxx
@@ -1023,58 +1023,110 @@ BitmapEx BitmapEx::ModifyBitmapEx(const basegfx::BColorModifierStack& rBColorMod
 
     for(sal_uInt32 a(rBColorModifierStack.count()); a && !bDone; )
     {
-        const basegfx::BColorModifier& rModifier = rBColorModifierStack.getBColorModifier(--a);
+        const basegfx::BColorModifierSharedPtr& rModifier = rBColorModifierStack.getBColorModifier(--a);
+        const basegfx::BColorModifier_replace* pReplace = dynamic_cast< const basegfx::BColorModifier_replace* >(rModifier.get());
 
-        switch(rModifier.getMode())
+        if(pReplace)
         {
-            case basegfx::BCOLORMODIFYMODE_REPLACE :
+            // complete replace
+            if(IsTransparent())
             {
-                // complete replace
-                if(IsTransparent())
+                // clear bitmap with dest color
+                if(aChangedBitmap.GetBitCount() <= 8)
                 {
-                    // clear bitmap with dest color
-                    if(aChangedBitmap.GetBitCount() <= 8)
-                    {
-                        // do NOT use erase; 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 explicitely
-                        BitmapReadAccess* pReadAccess = aChangedBitmap.AcquireReadAccess();
-                        OSL_ENSURE(pReadAccess, "Got no Bitmap ReadAccess ?!?");
+                    // do NOT use erase; 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 explicitely
+                    BitmapReadAccess* pReadAccess = aChangedBitmap.AcquireReadAccess();
+                    OSL_ENSURE(pReadAccess, "Got no Bitmap ReadAccess ?!?");
 
-                        if(pReadAccess)
-                        {
-                            BitmapPalette aNewPalette(pReadAccess->GetPalette());
-                            aNewPalette[0] = BitmapColor(Color(rModifier.getBColor()));
-                            aChangedBitmap = Bitmap(
-                                aChangedBitmap.GetSizePixel(),
-                                aChangedBitmap.GetBitCount(),
-                                &aNewPalette);
-                            delete pReadAccess;
-                        }
-                    }
-                    else
+                    if(pReadAccess)
                     {
-                        aChangedBitmap.Erase(Color(rModifier.getBColor()));
+                        BitmapPalette aNewPalette(pReadAccess->GetPalette());
+                        aNewPalette[0] = BitmapColor(Color(pReplace->getBColor()));
+                        aChangedBitmap = Bitmap(
+                            aChangedBitmap.GetSizePixel(),
+                            aChangedBitmap.GetBitCount(),
+                            &aNewPalette);
+                        delete pReadAccess;
                     }
                 }
                 else
                 {
-                    // erase bitmap, caller will know to paint direct
-                    aChangedBitmap.SetEmpty();
+                    aChangedBitmap.Erase(Color(pReplace->getBColor()));
                 }
-
-                bDone = true;
-                break;
             }
+            else
+            {
+                // erase bitmap, caller will know to paint direct
+                aChangedBitmap.SetEmpty();
+            }
+
+            bDone = true;
+        }
+        else
+        {
+            BitmapWriteAccess* pContent = aChangedBitmap.AcquireWriteAccess();
 
-            default : // BCOLORMODIFYMODE_INTERPOLATE, BCOLORMODIFYMODE_GRAY, BCOLORMODIFYMODE_BLACKANDWHITE
+            if(pContent)
             {
-                BitmapWriteAccess* pContent = aChangedBitmap.AcquireWriteAccess();
+                const double fConvertColor(1.0 / 255.0);
+
+                if(pContent->HasPalette())
+                {
+                    const sal_uInt16 nCount(pContent->GetPaletteEntryCount());
+
+                    for(sal_uInt16 a(0); a < nCount; a++)
+                    {
+                        const BitmapColor& rCol = pContent->GetPaletteColor(a);
+                        const basegfx::BColor aBSource(
+                            rCol.GetRed() * fConvertColor,
+                            rCol.GetGreen() * fConvertColor,
+                            rCol.GetBlue() * fConvertColor);
+                        const basegfx::BColor aBDest(rModifier->getModifiedColor(aBSource));
+                        pContent->SetPaletteColor(a, BitmapColor(Color(aBDest)));
+                    }
+                }
+                else if(BMP_FORMAT_24BIT_TC_BGR == pContent->GetScanlineFormat())
+                {
+                    for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
+                    {
+                        Scanline pScan = pContent->GetScanline(y);
 
-                if(pContent)
+                        for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->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(BMP_FORMAT_24BIT_TC_RGB == pContent->GetScanlineFormat())
                 {
-                    const double fConvertColor(1.0 / 255.0);
+                    for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
+                    {
+                        Scanline pScan = pContent->GetScanline(y);
 
+                        for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->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);
+                        }
+                    }
+                }
+                else
+                {
                     for(sal_uInt32 y(0L); y < (sal_uInt32)pContent->Height(); y++)
                     {
                         for(sal_uInt32 x(0L); x < (sal_uInt32)pContent->Width(); x++)
@@ -1084,16 +1136,14 @@ BitmapEx BitmapEx::ModifyBitmapEx(const basegfx::BColorModifierStack& rBColorMod
                                 (double)aBMCol.GetRed() * fConvertColor,
                                 (double)aBMCol.GetGreen() * fConvertColor,
                                 (double)aBMCol.GetBlue() * fConvertColor);
-                            const basegfx::BColor aBDest(rModifier.getModifiedColor(aBSource));
+                            const basegfx::BColor aBDest(rModifier->getModifiedColor(aBSource));
 
                             pContent->SetPixel(y, x, BitmapColor(Color(aBDest)));
                         }
                     }
-
-                    delete pContent;
                 }
 
-                break;
+                delete pContent;
             }
         }
     }


More information about the Libreoffice-commits mailing list