[Libreoffice-commits] core.git: basegfx/source drawinglayer/source include/basegfx

Armin Le Grand alg at apache.org
Sun May 19 08:50:51 PDT 2013


 basegfx/source/numeric/ftools.cxx                   |   77 +++++++++
 drawinglayer/source/primitive2d/gridprimitive2d.cxx |  166 ++++++++++++--------
 include/basegfx/numeric/ftools.hxx                  |   30 +++
 3 files changed, 212 insertions(+), 61 deletions(-)

New commits:
commit 5a6ed660ec74e445a827c7aa41e4793c64a46271
Author: Armin Le Grand <alg at apache.org>
Date:   Thu Aug 23 14:03:21 2012 +0000

    Resolves: #i120596# Optimized grid primitive
    
    added some tooling to basegfx
    
    (cherry picked from commit 97fa4faaa0b09724cf98dbf22390b283ba57b41c)
    
    Conflicts:
    	basegfx/inc/basegfx/numeric/ftools.hxx
    
    Change-Id: Ib15c43cf4d5b50605ec596dab498e3a678f3734a

diff --git a/basegfx/source/numeric/ftools.cxx b/basegfx/source/numeric/ftools.cxx
index 0c9a173..1cbbe5c 100644
--- a/basegfx/source/numeric/ftools.cxx
+++ b/basegfx/source/numeric/ftools.cxx
@@ -18,11 +18,88 @@
  */
 
 #include <basegfx/numeric/ftools.hxx>
+#include <algorithm>
 
 namespace basegfx
 {
     // init static member of class fTools
     double ::basegfx::fTools::mfSmallValue = 0.000000001;
+
+    double snapToNearestMultiple(double v, const double fStep)
+    {
+        if(fTools::equalZero(fStep))
+        {
+            // with a zero step, all snaps to 0.0
+            return 0.0;
+        }
+        else
+        {
+            const double fHalfStep(fStep * 0.5);
+            const double fChange(fHalfStep - fmod(v + fHalfStep, fStep));
+
+            if(basegfx::fTools::equal(fabs(v), fabs(fChange)))
+            {
+                return 0.0;
+            }
+            else
+            {
+                return v + fChange;
+            }
+        }
+    }
+
+    double snapToZeroRange(double v, double fWidth)
+    {
+        if(fTools::equalZero(fWidth))
+        {
+            // with no range all snaps to range bound
+            return 0.0;
+        }
+        else
+        {
+            if(v < 0.0 || v > fWidth)
+            {
+                double fRetval(fmod(v, fWidth));
+
+                if(fRetval < 0.0)
+                {
+                    fRetval += fWidth;
+                }
+
+                return fRetval;
+            }
+            else
+            {
+                return v;
+            }
+        }
+    }
+
+    double snapToRange(double v, double fLow, double fHigh)
+    {
+        if(fTools::equal(fLow, fHigh))
+        {
+            // with no range all snaps to range bound
+            return 0.0;
+        }
+        else
+        {
+            if(fLow > fHigh)
+            {
+                // correct range order. Evtl. assert this (?)
+                std::swap(fLow, fHigh);
+            }
+
+            if(v < fLow || v > fHigh)
+            {
+                return snapToZeroRange(v - fLow, fHigh - fLow) + fLow;
+            }
+            else
+            {
+                return v;
+            }
+        }
+    }
 } // end of namespace basegfx
 
 /* vim:set shiftwidth=4 softtabstop=4 expandtab: */
diff --git a/drawinglayer/source/primitive2d/gridprimitive2d.cxx b/drawinglayer/source/primitive2d/gridprimitive2d.cxx
index c241738..1f7dcb1 100644
--- a/drawinglayer/source/primitive2d/gridprimitive2d.cxx
+++ b/drawinglayer/source/primitive2d/gridprimitive2d.cxx
@@ -122,95 +122,139 @@ namespace drawinglayer
                     nSmallStepsY = (sal_uInt32)(fStepY / fSmallStepY);
                 }
 
-                // prepare point vectors for point and cross markers
-                std::vector< basegfx::B2DPoint > aPositionsPoint;
-                std::vector< basegfx::B2DPoint > aPositionsCross;
+                // calculate extended viewport in which grid points may lie at all
+                basegfx::B2DRange aExtendedViewport;
 
-                for(double fX(0.0); fX < aScale.getX(); fX += fStepX)
+                if(rViewInformation.getDiscreteViewport().isEmpty())
                 {
-                    const bool bXZero(basegfx::fTools::equalZero(fX));
+                    // not set, use logic size to travel over all potentioal grid points
+                    aExtendedViewport = basegfx::B2DRange(0.0, 0.0, aScale.getX(), aScale.getY());
+                }
+                else
+                {
+                    // transform unit range to discrete view
+                    aExtendedViewport = basegfx::B2DRange(0.0, 0.0, 1.0, 1.0);
+                    basegfx::B2DHomMatrix aTrans(rViewInformation.getObjectToViewTransformation() * getTransform());
+                    aExtendedViewport.transform(aTrans);
+
+                    // intersect with visible part
+                    aExtendedViewport.intersect(rViewInformation.getDiscreteViewport());
 
-                    for(double fY(0.0); fY < aScale.getY(); fY += fStepY)
+                    if(!aExtendedViewport.isEmpty())
                     {
-                        const bool bYZero(basegfx::fTools::equalZero(fY));
+                        // convert back and apply scale
+                        aTrans.invert();
+                        aTrans.scale(aScale.getX(), aScale.getY());
+                        aExtendedViewport.transform(aTrans);
+
+                        // crop start/end in X/Y to multiples of logical step width
+                        const double fHalfCrossSize((rViewInformation.getInverseObjectToViewTransformation() * basegfx::B2DVector(3.0, 0.0)).getLength());
+                        const double fMinX(floor((aExtendedViewport.getMinX() - fHalfCrossSize) / fStepX) * fStepX);
+                        const double fMaxX(ceil((aExtendedViewport.getMaxX() + fHalfCrossSize) / fStepX) * fStepX);
+                        const double fMinY(floor((aExtendedViewport.getMinY() - fHalfCrossSize) / fStepY) * fStepY);
+                        const double fMaxY(ceil((aExtendedViewport.getMaxY() + fHalfCrossSize) / fStepY) * fStepY);
+
+                        // put to aExtendedViewport and crop on object logic size
+                        aExtendedViewport = basegfx::B2DRange(
+                            std::max(fMinX, 0.0),
+                            std::max(fMinY, 0.0),
+                            std::min(fMaxX, aScale.getX()),
+                            std::min(fMaxY, aScale.getY()));
+                    }
+                }
 
-                        if(!bXZero && !bYZero)
-                        {
-                            // get discrete position and test against 3x3 area surrounding it
-                            // since it's a cross
-                            const double fHalfCrossSize(3.0 * 0.5);
-                            const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fY));
-                            const basegfx::B2DRange aDiscreteRangeCross(
-                                aViewPos.getX() - fHalfCrossSize, aViewPos.getY() - fHalfCrossSize,
-                                aViewPos.getX() + fHalfCrossSize, aViewPos.getY() + fHalfCrossSize);
-
-                            if(rViewInformation.getDiscreteViewport().overlaps(aDiscreteRangeCross))
-                            {
-                                const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos);
-                                aPositionsCross.push_back(aLogicPos);
-                            }
-                        }
+                if(!aExtendedViewport.isEmpty())
+                {
+                    // prepare point vectors for point and cross markers
+                    std::vector< basegfx::B2DPoint > aPositionsPoint;
+                    std::vector< basegfx::B2DPoint > aPositionsCross;
+
+                    for(double fX(aExtendedViewport.getMinX()); fX < aExtendedViewport.getMaxX(); fX += fStepX)
+                    {
+                        const bool bXZero(basegfx::fTools::equalZero(fX));
 
-                        if(getSubdivisionsX() && !bYZero)
+                        for(double fY(aExtendedViewport.getMinY()); fY < aExtendedViewport.getMaxY(); fY += fStepY)
                         {
-                            double fF(fX + fSmallStepX);
+                            const bool bYZero(basegfx::fTools::equalZero(fY));
 
-                            for(sal_uInt32 a(1L); a < nSmallStepsX && fF < aScale.getX(); a++, fF += fSmallStepX)
+                            if(!bXZero && !bYZero)
                             {
-                                const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fF, fY));
-
-                                if(rViewInformation.getDiscreteViewport().isInside(aViewPos))
+                                // get discrete position and test against 3x3 area surrounding it
+                                // since it's a cross
+                                const double fHalfCrossSize(3.0 * 0.5);
+                                const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fY));
+                                const basegfx::B2DRange aDiscreteRangeCross(
+                                    aViewPos.getX() - fHalfCrossSize, aViewPos.getY() - fHalfCrossSize,
+                                    aViewPos.getX() + fHalfCrossSize, aViewPos.getY() + fHalfCrossSize);
+
+                                if(rViewInformation.getDiscreteViewport().overlaps(aDiscreteRangeCross))
                                 {
                                     const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos);
-                                    aPositionsPoint.push_back(aLogicPos);
+                                    aPositionsCross.push_back(aLogicPos);
                                 }
                             }
-                        }
 
-                        if(getSubdivisionsY() && !bXZero)
-                        {
-                            double fF(fY + fSmallStepY);
+                            if(getSubdivisionsX() && !bYZero)
+                            {
+                                double fF(fX + fSmallStepX);
 
-                            for(sal_uInt32 a(1L); a < nSmallStepsY && fF < aScale.getY(); a++, fF += fSmallStepY)
+                                for(sal_uInt32 a(1); a < nSmallStepsX && fF < aExtendedViewport.getMaxX(); a++, fF += fSmallStepX)
+                                {
+                                    const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fF, fY));
+
+                                    if(rViewInformation.getDiscreteViewport().isInside(aViewPos))
+                                    {
+                                        const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos);
+                                        aPositionsPoint.push_back(aLogicPos);
+                                    }
+                                }
+                            }
+
+                            if(getSubdivisionsY() && !bXZero)
                             {
-                                const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fF));
+                                double fF(fY + fSmallStepY);
 
-                                if(rViewInformation.getDiscreteViewport().isInside(aViewPos))
+                                for(sal_uInt32 a(1); a < nSmallStepsY && fF < aExtendedViewport.getMaxY(); a++, fF += fSmallStepY)
                                 {
-                                    const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos);
-                                    aPositionsPoint.push_back(aLogicPos);
+                                    const basegfx::B2DPoint aViewPos(aRST * basegfx::B2DPoint(fX, fF));
+
+                                    if(rViewInformation.getDiscreteViewport().isInside(aViewPos))
+                                    {
+                                        const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos);
+                                        aPositionsPoint.push_back(aLogicPos);
+                                    }
                                 }
                             }
                         }
                     }
-                }
-
-                // prepare return value
-                const sal_uInt32 nCountPoint(aPositionsPoint.size());
-                const sal_uInt32 nCountCross(aPositionsCross.size());
-                const sal_uInt32 nRetvalCount((nCountPoint ? 1 : 0) + (nCountCross ? 1 : 0));
-                sal_uInt32 nInsertCounter(0);
 
-                aRetval.realloc(nRetvalCount);
+                    // prepare return value
+                    const sal_uInt32 nCountPoint(aPositionsPoint.size());
+                    const sal_uInt32 nCountCross(aPositionsCross.size());
+                    const sal_uInt32 nRetvalCount((nCountPoint ? 1 : 0) + (nCountCross ? 1 : 0));
+                    sal_uInt32 nInsertCounter(0);
 
-                // add PointArrayPrimitive2D if point markers were added
-                if(nCountPoint)
-                {
-                    aRetval[nInsertCounter++] = Primitive2DReference(new PointArrayPrimitive2D(aPositionsPoint, getBColor()));
-                }
+                    aRetval.realloc(nRetvalCount);
 
-                // add MarkerArrayPrimitive2D if cross markers were added
-                if(nCountCross)
-                {
-                    if(!getSubdivisionsX() && !getSubdivisionsY())
+                    // add PointArrayPrimitive2D if point markers were added
+                    if(nCountPoint)
                     {
-                        // no subdivisions, so fall back to points at grid positions, no need to
-                        // visualize a difference between divisions and sub-divisions
-                        aRetval[nInsertCounter++] = Primitive2DReference(new PointArrayPrimitive2D(aPositionsCross, getBColor()));
+                        aRetval[nInsertCounter++] = Primitive2DReference(new PointArrayPrimitive2D(aPositionsPoint, getBColor()));
                     }
-                    else
+
+                    // add MarkerArrayPrimitive2D if cross markers were added
+                    if(nCountCross)
                     {
-                        aRetval[nInsertCounter++] = Primitive2DReference(new MarkerArrayPrimitive2D(aPositionsCross, getCrossMarker()));
+                        if(!getSubdivisionsX() && !getSubdivisionsY())
+                        {
+                            // no subdivisions, so fall back to points at grid positions, no need to
+                            // visualize a difference between divisions and sub-divisions
+                            aRetval[nInsertCounter++] = Primitive2DReference(new PointArrayPrimitive2D(aPositionsCross, getBColor()));
+                        }
+                        else
+                        {
+                            aRetval[nInsertCounter++] = Primitive2DReference(new MarkerArrayPrimitive2D(aPositionsCross, getCrossMarker()));
+                        }
                     }
                 }
             }
diff --git a/include/basegfx/numeric/ftools.hxx b/include/basegfx/numeric/ftools.hxx
index 70dcabe..75e24b0 100644
--- a/include/basegfx/numeric/ftools.hxx
+++ b/include/basegfx/numeric/ftools.hxx
@@ -136,6 +136,36 @@ namespace basegfx
         return v / M_PI_2 * 90.0;
     }
 
+    /** Snap v to nearest multiple of fStep, from negative and
+        positive side.
+
+        Examples:
+
+        snapToNearestMultiple(-0.1, 0.5) = 0.0
+        snapToNearestMultiple(0.1, 0.5) = 0.0
+        snapToNearestMultiple(0.25, 0.5) = 0.0
+        snapToNearestMultiple(0.26, 0.5) = 0.5
+     */
+    double snapToNearestMultiple(double v, const double fStep);
+
+    /** Snap v to the range [0.0 .. fWidth] using modulo
+     */
+    double snapToZeroRange(double v, double fWidth);
+
+    /** Snap v to the range [fLow .. fHigh] using modulo
+     */
+    double snapToRange(double v, double fLow, double fHigh);
+
+    /** return fValue with the sign of fSignCarrier, thus evtl. changed
+    */
+    inline double copySign(double fValue, double fSignCarrier)
+    {
+#ifdef WNT
+        return _copysign(fValue, fSignCarrier);
+#else
+        return copysign(fValue, fSignCarrier);
+#endif
+    }
 
     class BASEGFX_DLLPUBLIC fTools
     {


More information about the Libreoffice-commits mailing list