basegfx/source/tools/gradienttools.cxx  |   27 ---
 drawinglayer/source/texture/texture.cxx |  253 +++++++++++++++++++-------------
 2 files changed, 159 insertions(+), 121 deletions(-)

New commits:
commit 16e728a8a88a7a04acec069512a5268ae89cf420
Author:     Armin Le Grand (allotropia) <[email protected]>
AuthorDate: Fri Feb 24 17:34:53 2023 +0100
Commit:     Armin Le Grand <[email protected]>
CommitDate: Mon Feb 27 17:43:13 2023 +0000

    MCGR: Adapted other Gradient* to make use of MCGR
    
    Added to make
      GeoTexSvxGradientElliptical
      GeoTexSvxGradientSquare
      GeoTexSvxGradientRect
    work using the MCGR. It is still 100%
    backward-compatible, so as long as there is no
    source using this it will stay invisible - by
    purpose.
    
    Tests look good with all three, see the static
    variable nUseGradientSteps.
    
    NOTE: GeoTexSvxGradientElliptical still looks not
    optimal due to texture back-mapping method
    getEllipticalGradientAlpha, see notes in
    commit "MCGR: Adapted GradientRadial to make use
    of MCGR" ac824594c577ab4880177b3411a25297b1d08074
    
    Change-Id: I56b82b867af88fe532f840dde15e0f5c299ed6a3
    Reviewed-on: https://gerrit.libreoffice.org/c/core/+/147662
    Tested-by: Jenkins
    Reviewed-by: Armin Le Grand <[email protected]>

diff --git a/basegfx/source/tools/gradienttools.cxx 
b/basegfx/source/tools/gradienttools.cxx
index 37671374262c..f35f91f5a79a 100644
--- a/basegfx/source/tools/gradienttools.cxx
+++ b/basegfx/source/tools/gradienttools.cxx
@@ -544,13 +544,6 @@ namespace basegfx
                 t = 1.0 - std::hypot(aCoor.getX(), aCoor.getY() * 
fAspectRatio);
             }
 
-            const sal_uInt32 nSteps(rGradInfo.getRequestedSteps());
-
-            if(nSteps && t < 1.0)
-            {
-                return floor(t * nSteps) / double(nSteps - 1);
-            }
-
             return t;
         }
 
@@ -571,15 +564,7 @@ namespace basegfx
                 return 0.0;
             }
 
-            const double t(1.0 - std::max(fAbsX, fAbsY));
-            const sal_uInt32 nSteps(rGradInfo.getRequestedSteps());
-
-            if(nSteps && t < 1.0)
-            {
-                return floor(t * nSteps) / double(nSteps - 1);
-            }
-
-            return t;
+            return 1.0 - std::max(fAbsX, fAbsY);
         }
 
         double getRectangularGradientAlpha(const B2DPoint& rUV, const 
ODFGradientInfo& rGradInfo)
@@ -643,15 +628,7 @@ namespace basegfx
                 fAbsY = ((fAbsY - 1) / fAspectRatio) + 1;
             }
 
-            const double t(1.0 - std::max(fAbsX, fAbsY));
-            const sal_uInt32 nSteps(rGradInfo.getRequestedSteps());
-
-            if(nSteps && t < 1.0)
-            {
-                return floor(t * nSteps) / double(nSteps - 1);
-            }
-
-            return t;
+            return 1.0 - std::max(fAbsX, fAbsY);
         }
     } // namespace utils
 } // namespace basegfx
diff --git a/drawinglayer/source/texture/texture.cxx 
b/drawinglayer/source/texture/texture.cxx
index e3ed2780af4e..22f56f33b8bd 100644
--- a/drawinglayer/source/texture/texture.cxx
+++ b/drawinglayer/source/texture/texture.cxx
@@ -455,60 +455,79 @@ namespace drawinglayer::texture
             std::vector< B2DHomMatrixAndBColor >& rEntries,
             basegfx::BColor& rOuterColor)
         {
-            if(mnColorSteps.size() <= 1)
+            // no color at all, done
+            if (mnColorSteps.empty())
                 return;
 
-            const basegfx::BColor maStart(mnColorSteps.front().getColor());
-            const basegfx::BColor maEnd(mnColorSteps.back().getColor());
-            const sal_uInt32 nSteps(basegfx::utils::calculateNumberOfSteps(
-                maGradientInfo.getRequestedSteps(), maStart, maEnd));
+            // fill in return parameter rOuterColor before returning
+            rOuterColor = mnColorSteps.front().getColor();
 
-            rOuterColor = maStart;
-            double fWidth(1.0);
-            double fHeight(1.0);
-            double fIncrementX(0.0);
-            double fIncrementY(0.0);
+            // only one color, done
+            if (mnColorSteps.size() < 2)
+                return;
 
-            if(maGradientInfo.getAspectRatio() > 1.0)
-            {
-                fIncrementY = fHeight / nSteps;
-                fIncrementX = fIncrementY / maGradientInfo.getAspectRatio();
-            }
-            else
+            // need to start with the offsets *outside* of all loops, these 
will
+            // get modified non-linear below, now in more than one gradient 
section,
+            // but *constantly* over the whole range
+            double fAllWidth(0.0);
+            double fAllHeight(0.0);
+
+            // outer loop over ColorSteps, each is from cs_l to cs_r
+            for (auto cs_l(mnColorSteps.begin()), cs_r(cs_l + 1); cs_r != 
mnColorSteps.end(); cs_l++, cs_r++)
             {
-                fIncrementX = fWidth / nSteps;
-                fIncrementY = fIncrementX * maGradientInfo.getAspectRatio();
-            }
+                // get colors & calculate steps
+                const basegfx::BColor aCStart(cs_l->getColor());
+                const basegfx::BColor aCEnd(cs_r->getColor());
+                const sal_uInt32 nSteps(basegfx::utils::calculateNumberOfSteps(
+                    maGradientInfo.getRequestedSteps(), aCStart, aCEnd));
 
-            B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
+                // get offsets & calculate StripeWidth
+                const double fOffsetStart(cs_l->getOffset());
+                const double fOffsetEnd(cs_r->getOffset());
+                const double fStripeWidth((fOffsetEnd - fOffsetStart) / 
nSteps);
 
-            for(sal_uInt32 a(1); a < nSteps; a++)
-            {
-                // next step
-                fWidth -= fIncrementX;
-                fHeight -= fIncrementY;
+                // prepare individual increments for X/Y dependent on aspect 
ratio
+                const double fAR(maGradientInfo.getAspectRatio());
+                const bool bMTO(fAR > 1.0);
+                const double fIncrementX(bMTO ? fStripeWidth / fAR : 
fStripeWidth);
+                const double fIncrementY(bMTO ? fStripeWidth : fStripeWidth * 
fAR);
+
+                // get correct start for innner loop (see above)
+                const sal_uInt32 nStartInnerLoop(cs_l == mnColorSteps.begin() 
? 1 : 0);
+
+                for (sal_uInt32 innerLoop(nStartInnerLoop); innerLoop < 
nSteps; innerLoop++)
+                {
+                    // next step, actively adapt outer-loop w/h values
+                    fAllWidth += fIncrementX;
+                    fAllHeight += fIncrementY;
+
+                    // set and add at target
+                    B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
 
-                aB2DHomMatrixAndBColor.maB2DHomMatrix = 
maGradientInfo.getTextureTransform() * 
basegfx::utils::createScaleB2DHomMatrix(fWidth, fHeight);
-                aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, 
double(a) / double(nSteps - 1));
-                rEntries.push_back(aB2DHomMatrixAndBColor);
+                    aB2DHomMatrixAndBColor.maB2DHomMatrix = 
maGradientInfo.getTextureTransform()
+                        * basegfx::utils::createScaleB2DHomMatrix(1.0 - 
fAllWidth, 1.0 - fAllHeight);
+                    aB2DHomMatrixAndBColor.maBColor = interpolate(aCStart, 
aCEnd, double(innerLoop) / double(nSteps - 1));
+                    rEntries.push_back(aB2DHomMatrixAndBColor);
+                }
             }
         }
 
         void GeoTexSvxGradientElliptical::modifyBColor(const 
basegfx::B2DPoint& rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
         {
-            if(mnColorSteps.size() <= 1)
+            // no color at all, done
+            if (mnColorSteps.empty())
+                return;
+
+            // just single color, done
+            if (mnColorSteps.size() < 2)
             {
                 rBColor = mnColorSteps.front().getColor();
+                return;
             }
-            else
-            {
-                const double 
fScaler(basegfx::utils::getEllipticalGradientAlpha(rUV, maGradientInfo));
-
-                const basegfx::BColor maStart(mnColorSteps.front().getColor());
-                const basegfx::BColor maEnd(mnColorSteps.back().getColor());
 
-                rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
-            }
+            // texture-back-transform X/Y -> t [0.0..1.0] and determine color
+            const double 
fScaler(basegfx::utils::getEllipticalGradientAlpha(rUV, maGradientInfo));
+            rBColor = basegfx::utils::modifyBColor(mnColorSteps, fScaler, 
mnRequestedSteps);
         }
 
 
@@ -538,42 +557,65 @@ namespace drawinglayer::texture
             std::vector< B2DHomMatrixAndBColor >& rEntries,
             basegfx::BColor& rOuterColor)
         {
-            if(mnColorSteps.size() <= 1)
+            // no color at all, done
+            if (mnColorSteps.empty())
                 return;
 
-            const basegfx::BColor maStart(mnColorSteps.front().getColor());
-            const basegfx::BColor maEnd(mnColorSteps.back().getColor());
-            const sal_uInt32 nSteps(basegfx::utils::calculateNumberOfSteps(
-                maGradientInfo.getRequestedSteps(), maStart, maEnd));
+            // fill in return parameter rOuterColor before returning
+            rOuterColor = mnColorSteps.front().getColor();
 
-            rOuterColor = maStart;
-            const double fStepSize(1.0 / nSteps);
-            B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
+            // only one color, done
+            if (mnColorSteps.size() < 2)
+                return;
 
-            for(sal_uInt32 a(1); a < nSteps; a++)
+            // outer loop over ColorSteps, each is from cs_l to cs_r
+            for (auto cs_l(mnColorSteps.begin()), cs_r(cs_l + 1); cs_r != 
mnColorSteps.end(); cs_l++, cs_r++)
             {
-                const double fSize(1.0 - (fStepSize * a));
-                aB2DHomMatrixAndBColor.maB2DHomMatrix = 
maGradientInfo.getTextureTransform() * 
basegfx::utils::createScaleB2DHomMatrix(fSize, fSize);
-                aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, 
double(a) / double(nSteps - 1));
-                rEntries.push_back(aB2DHomMatrixAndBColor);
+                // get colors & calculate steps
+                const basegfx::BColor aCStart(cs_l->getColor());
+                const basegfx::BColor aCEnd(cs_r->getColor());
+                const sal_uInt32 nSteps(basegfx::utils::calculateNumberOfSteps(
+                    maGradientInfo.getRequestedSteps(), aCStart, aCEnd));
+
+                // get offsets & calculate StripeWidth
+                const double fOffsetStart(cs_l->getOffset());
+                const double fOffsetEnd(cs_r->getOffset());
+                const double fStripeWidth((fOffsetEnd - fOffsetStart) / 
nSteps);
+
+                // get correct start for innner loop (see above)
+                const sal_uInt32 nStartInnerLoop(cs_l == mnColorSteps.begin() 
? 1 : 0);
+
+                for (sal_uInt32 innerLoop(nStartInnerLoop); innerLoop < 
nSteps; innerLoop++)
+                {
+                    // calculate size/radius
+                    const double fSize(1.0 - (fOffsetStart + (fStripeWidth * 
innerLoop)));
+
+                    // set and add at target
+                    B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
+
+                    aB2DHomMatrixAndBColor.maB2DHomMatrix = 
maGradientInfo.getTextureTransform() * 
basegfx::utils::createScaleB2DHomMatrix(fSize, fSize);
+                    aB2DHomMatrixAndBColor.maBColor = interpolate(aCStart, 
aCEnd, double(innerLoop) / double(nSteps - 1));
+                    rEntries.push_back(aB2DHomMatrixAndBColor);
+                }
             }
         }
 
         void GeoTexSvxGradientSquare::modifyBColor(const basegfx::B2DPoint& 
rUV, basegfx::BColor& rBColor, double& /*rfOpacity*/) const
         {
-            if(mnColorSteps.size() <= 1)
+            // no color at all, done
+            if (mnColorSteps.empty())
+                return;
+
+            // just single color, done
+            if (mnColorSteps.size() < 2)
             {
                 rBColor = mnColorSteps.front().getColor();
+                return;
             }
-            else
-            {
-                const double 
fScaler(basegfx::utils::getSquareGradientAlpha(rUV, maGradientInfo));
-
-                const basegfx::BColor maStart(mnColorSteps.front().getColor());
-                const basegfx::BColor maEnd(mnColorSteps.back().getColor());
 
-                rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
-            }
+            // texture-back-transform X/Y -> t [0.0..1.0] and determine color
+            const double fScaler(basegfx::utils::getSquareGradientAlpha(rUV, 
maGradientInfo));
+            rBColor = basegfx::utils::modifyBColor(mnColorSteps, fScaler, 
mnRequestedSteps);
         }
 
 
@@ -603,60 +645,79 @@ namespace drawinglayer::texture
             std::vector< B2DHomMatrixAndBColor >& rEntries,
             basegfx::BColor& rOuterColor)
         {
-            if(mnColorSteps.size() <= 1)
+            // no color at all, done
+            if (mnColorSteps.empty())
                 return;
 
-            const basegfx::BColor maStart(mnColorSteps.front().getColor());
-            const basegfx::BColor maEnd(mnColorSteps.back().getColor());
-            const sal_uInt32 nSteps(basegfx::utils::calculateNumberOfSteps(
-                maGradientInfo.getRequestedSteps(), maStart, maEnd));
+            // fill in return parameter rOuterColor before returning
+            rOuterColor = mnColorSteps.front().getColor();
+
+            // only one color, done
+            if (mnColorSteps.size() < 2)
+                return;
 
-            rOuterColor = maStart;
-            double fWidth(1.0);
-            double fHeight(1.0);
-            double fIncrementX(0.0);
-            double fIncrementY(0.0);
+            // need to start with the offsets *outside* of all loops, these 
will
+            // get modified non-linear below, now in more than one gradient 
section,
+            // but *constantly* over the whole range
+            double fAllWidth(0.0);
+            double fAllHeight(0.0);
 
-            if(maGradientInfo.getAspectRatio() > 1.0)
-            {
-                fIncrementY = fHeight / nSteps;
-                fIncrementX = fIncrementY / maGradientInfo.getAspectRatio();
-            }
-            else
+            // outer loop over ColorSteps, each is from cs_l to cs_r
+            for (auto cs_l(mnColorSteps.begin()), cs_r(cs_l + 1); cs_r != 
mnColorSteps.end(); cs_l++, cs_r++)
             {
-                fIncrementX = fWidth / nSteps;
-                fIncrementY = fIncrementX * maGradientInfo.getAspectRatio();
-            }
+                // get colors & calculate steps
+                const basegfx::BColor aCStart(cs_l->getColor());
+                const basegfx::BColor aCEnd(cs_r->getColor());
+                const sal_uInt32 nSteps(basegfx::utils::calculateNumberOfSteps(
+                    maGradientInfo.getRequestedSteps(), aCStart, aCEnd));
+
+                // get offsets & calculate StripeWidth
+                const double fOffsetStart(cs_l->getOffset());
+                const double fOffsetEnd(cs_r->getOffset());
+                const double fStripeWidth((fOffsetEnd - fOffsetStart) / 
nSteps);
 
-            B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
+                // prepare individual increments for X/Y dependent on aspect 
ratio
+                const double fAR(maGradientInfo.getAspectRatio());
+                const bool bMTO(fAR > 1.0);
+                const double fIncrementX(bMTO ? fStripeWidth / fAR : 
fStripeWidth);
+                const double fIncrementY(bMTO ? fStripeWidth : fStripeWidth * 
fAR);
 
-            for(sal_uInt32 a(1); a < nSteps; a++)
-            {
-                // next step
-                fWidth -= fIncrementX;
-                fHeight -= fIncrementY;
+                // get correct start for innner loop (see above)
+                const sal_uInt32 nStartInnerLoop(cs_l == mnColorSteps.begin() 
? 1 : 0);
 
-                aB2DHomMatrixAndBColor.maB2DHomMatrix = 
maGradientInfo.getTextureTransform() * 
basegfx::utils::createScaleB2DHomMatrix(fWidth, fHeight);
-                aB2DHomMatrixAndBColor.maBColor = interpolate(maStart, maEnd, 
double(a) / double(nSteps - 1));
-                rEntries.push_back(aB2DHomMatrixAndBColor);
+                for (sal_uInt32 innerLoop(nStartInnerLoop); innerLoop < 
nSteps; innerLoop++)
+                {
+                    // next step, actively adapt outer-loop w/h values
+                    fAllWidth += fIncrementX;
+                    fAllHeight += fIncrementY;
+
+                    // set and add at target
+                    B2DHomMatrixAndBColor aB2DHomMatrixAndBColor;
+
+                    aB2DHomMatrixAndBColor.maB2DHomMatrix = 
maGradientInfo.getTextureTransform()
+                        * basegfx::utils::createScaleB2DHomMatrix(1.0 - 
fAllWidth, 1.0 - fAllHeight);
+                    aB2DHomMatrixAndBColor.maBColor = interpolate(aCStart, 
aCEnd, double(innerLoop) / double(nSteps - 1));
+                    rEntries.push_back(aB2DHomMatrixAndBColor);
+                }
             }
         }
 
         void GeoTexSvxGradientRect::modifyBColor(const basegfx::B2DPoint& rUV, 
basegfx::BColor& rBColor, double& /*rfOpacity*/) const
         {
-            if(mnColorSteps.size() <= 1)
+            // no color at all, done
+            if (mnColorSteps.empty())
+                return;
+
+            // just single color, done
+            if (mnColorSteps.size() < 2)
             {
                 rBColor = mnColorSteps.front().getColor();
+                return;
             }
-            else
-            {
-                const double 
fScaler(basegfx::utils::getRectangularGradientAlpha(rUV, maGradientInfo));
 
-                const basegfx::BColor maStart(mnColorSteps.front().getColor());
-                const basegfx::BColor maEnd(mnColorSteps.back().getColor());
-
-                rBColor = basegfx::interpolate(maStart, maEnd, fScaler);
-            }
+            // texture-back-transform X/Y -> t [0.0..1.0] and determine color
+            const double 
fScaler(basegfx::utils::getRectangularGradientAlpha(rUV, maGradientInfo));
+            rBColor = basegfx::utils::modifyBColor(mnColorSteps, fScaler, 
mnRequestedSteps);
         }
 
 

Reply via email to