basegfx/source/tools/gradienttools.cxx             |   38 +++++++++++++++++
 include/basegfx/utils/gradienttools.hxx            |   15 +++++++
 svx/source/sdr/primitive2d/sdrattributecreator.cxx |   45 +++++++++++++--------
 3 files changed, 81 insertions(+), 17 deletions(-)

New commits:
commit 64007cb308ead90ba6ffa2963c5de8ef89cec5ce
Author:     Armin Le Grand (allotropia) <armin.le.grand.ext...@allotropia.de>
AuthorDate: Mon Apr 3 12:09:16 2023 +0200
Commit:     Armin Le Grand <armin.le.gr...@me.com>
CommitDate: Mon Apr 3 17:16:48 2023 +0200

    MCGR: Unify Gradient intensity handling in tooling
    
    Moved the Gradient intensity handling to tooling since
    it is also needed for TransparencyGradients. Added
    missing use of GradientStepCount for transparency.
    
    Change-Id: I63ae6683fa0131be7faadc8572e19f5c43bf27e3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/149957
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <armin.le.gr...@me.com>

diff --git a/basegfx/source/tools/gradienttools.cxx 
b/basegfx/source/tools/gradienttools.cxx
index 49cf831da262..d1b5874e5b77 100644
--- a/basegfx/source/tools/gradienttools.cxx
+++ b/basegfx/source/tools/gradienttools.cxx
@@ -264,6 +264,44 @@ namespace basegfx
 
     namespace utils
     {
+        /* Tooling method to linearly blend the Colors contained in
+           a given ColorStop vector against a given Color using the
+           given intensity values.
+           The intensity values fStartIntensity, fEndIntensity are
+           in the range of [0.0 .. 1.0] and describe how much the
+           blend is supposed to be done at the start color position
+           and the end color position resprectively, where 0.0 means
+           to fully use the given BlendColor, 1.0 means to not change
+           the existing color in the ColorStop.
+           Every color entry in the given ColorStop is blended
+           relative to it's StopPosition, interpolating the
+           given intensities with the range [0.0 .. 1.0] to do so.
+        */
+        void blendColorStopsToIntensity(ColorStops& rColorStops, double 
fStartIntensity, double fEndIntensity, const basegfx::BColor& rBlendColor)
+        {
+            // no entries, done
+            if (rColorStops.empty())
+                return;
+
+            // correct intensities (maybe assert when input was wrong)
+            fStartIntensity = std::max(std::min(1.0, fStartIntensity), 0.0);
+            fEndIntensity = std::max(std::min(1.0, fEndIntensity), 0.0);
+
+            // all 100%, no real blend, done
+            if (basegfx::fTools::equal(fStartIntensity, 1.0) && 
basegfx::fTools::equal(fEndIntensity, 1.0))
+                return;
+
+            // blend relative to StopOffset position
+            for (auto& candidate : rColorStops)
+            {
+                const double fOffset(candidate.getStopOffset());
+                const double fIntensity((fStartIntensity * (1.0 - fOffset)) + 
(fEndIntensity * fOffset));
+                candidate = basegfx::ColorStop(
+                    fOffset,
+                    basegfx::interpolate(rBlendColor, 
candidate.getStopColor(), fIntensity));
+            }
+        }
+
         /* Tooling method to check if a ColorStop vector is defined
            by a single color. It returns true if this is the case.
            If true is returned, rSingleColor contains that single
diff --git a/include/basegfx/utils/gradienttools.hxx 
b/include/basegfx/utils/gradienttools.hxx
index c7123bc81db3..dfa1f35b38c4 100644
--- a/include/basegfx/utils/gradienttools.hxx
+++ b/include/basegfx/utils/gradienttools.hxx
@@ -196,6 +196,21 @@ namespace basegfx
 
     namespace utils
     {
+        /* Tooling method to linearly blend the Colors contained in
+           a given ColorStop vector against a given Color using the
+           given intensity values.
+           The intensity values fStartIntensity, fEndIntensity are
+           in the range of [0.0 .. 1.0] and describe how much the
+           blend is supposed to be done at the start color position
+           and the end color position resprectively, where 0.0 means
+           to fully use the given BlendColor, 1.0 means to not change
+           the existing color in the ColorStop.
+           Every color entry in the given ColorStop is blended
+           relative to it's StopPosition, interpolating the
+           given intensities with the range [0.0 .. 1.0] to do so.
+        */
+        BASEGFX_DLLPUBLIC void blendColorStopsToIntensity(ColorStops& 
rColorStops, double fStartIntensity, double fEndIntensity, const 
basegfx::BColor& rBlendColor);
+
         /* Tooling method to check if a ColorStop vector is defined
            by a single color. It returns true if this is the case.
            If true is returned, rSingleColor contains that single
diff --git a/svx/source/sdr/primitive2d/sdrattributecreator.cxx 
b/svx/source/sdr/primitive2d/sdrattributecreator.cxx
index 813c9884bc9b..89493e4d5a45 100644
--- a/svx/source/sdr/primitive2d/sdrattributecreator.cxx
+++ b/svx/source/sdr/primitive2d/sdrattributecreator.cxx
@@ -756,23 +756,16 @@ namespace drawinglayer::primitive2d
                                 }
                             }
 
-                            if(aXGradient.GetStartIntens() != 100 || 
aXGradient.GetEndIntens() != 100)
+                            if (aXGradient.GetStartIntens() != 100 || 
aXGradient.GetEndIntens() != 100)
                             {
                                 // Need to do the (old, crazy) blend against 
black for a
                                 // used intensity, but now for all ColorStops 
relative to their
                                 // offsets, where 0 means black and 100 means 
original color
-                                const double 
fStartIntensity(aXGradient.GetStartIntens() * 0.01);
-                                const double 
fEndIntensity(aXGradient.GetEndIntens() * 0.01);
-                                const basegfx::BColor aBlack;
-
-                                for (auto& candidate : aColorStops)
-                                {
-                                    const double 
fOffset(candidate.getStopOffset());
-                                    const double fIntensity((fStartIntensity * 
(1.0 - fOffset)) + (fEndIntensity * fOffset));
-                                    candidate = basegfx::ColorStop(
-                                        fOffset,
-                                        basegfx::interpolate(aBlack, 
candidate.getStopColor(), fIntensity));
-                                }
+                                basegfx::utils::blendColorStopsToIntensity(
+                                    aColorStops,
+                                    aXGradient.GetStartIntens() * 0.01,
+                                    aXGradient.GetEndIntens() * 0.01,
+                                    basegfx::BColor()); // COL_BLACK
                             }
 
                             aGradient = attribute::FillGradientAttribute(
@@ -919,8 +912,8 @@ namespace drawinglayer::primitive2d
             if((pGradientItem = rSet.GetItemIfSet(XATTR_FILLFLOATTRANSPARENCE))
                 && pGradientItem->IsEnabled())
             {
-                // test if float transparence is completely transparent
-                const XGradient& rGradient = pGradientItem->GetGradientValue();
+                // test if float transparency is completely transparent
+                const XGradient& rGradient(pGradientItem->GetGradientValue());
                 basegfx::BColor aSingleColor;
                 const bool 
bSingleColor(basegfx::utils::isSingleColor(rGradient.GetColorStops(), 
aSingleColor));
                 const bool bCompletelyTransparent(bSingleColor && 
basegfx::fTools::equal(aSingleColor.luminance(), 1.0));
@@ -930,15 +923,33 @@ namespace drawinglayer::primitive2d
                 // normal fill attributes, XFILL_NONE will be used.
                 // create nothing when not transparent: use normal fill, no 
need t create a FillGradientAttribute.
                 // Both cases are optimizations, always creating 
FillGradientAttribute will work, too
-                if(!bNotTransparent && !bCompletelyTransparent)
+                if (!bNotTransparent && !bCompletelyTransparent)
                 {
+                    basegfx::ColorStops aColorStops(rGradient.GetColorStops());
+
+                    if (rGradient.GetStartIntens() != 100 || 
rGradient.GetEndIntens() != 100)
+                    {
+                        // this may also be set for transparence, so need to 
take care of it
+                        basegfx::utils::blendColorStopsToIntensity(
+                            aColorStops,
+                            rGradient.GetStartIntens() * 0.01,
+                            rGradient.GetEndIntens() * 0.01,
+                            basegfx::BColor()); // COL_BLACK
+                    }
+
                     return attribute::FillGradientAttribute(
                         
XGradientStyleToGradientStyle(rGradient.GetGradientStyle()),
                         static_cast<double>(rGradient.GetBorder()) * 0.01,
                         static_cast<double>(rGradient.GetXOffset()) * 0.01,
                         static_cast<double>(rGradient.GetYOffset()) * 0.01,
                         toRadians(rGradient.GetAngle()),
-                        rGradient.GetColorStops());
+                        aColorStops,
+                        // oops - the gradientStepCount was missing here. If 
we want to use
+                        // a combination of gradient & transparencyGradient to 
represent
+                        // imported gradients of formats which do originally 
support transparency
+                        // in gradients, then the gradient has to be exactly 
defined the same,
+                        // including the (evtl. used) gradientStepCount
+                        rSet.Get(XATTR_GRADIENTSTEPCOUNT).GetValue());
                 }
             }
 

Reply via email to