Author: alg Date: Thu Aug 23 15:03:21 2012 New Revision: 1376528 URL: http://svn.apache.org/viewvc?rev=1376528&view=rev Log: #120596# Optimized grid primitive, added some tooling to basegfx
Modified: incubator/ooo/trunk/main/basegfx/inc/basegfx/numeric/ftools.hxx incubator/ooo/trunk/main/basegfx/source/numeric/ftools.cxx incubator/ooo/trunk/main/drawinglayer/source/primitive2d/gridprimitive2d.cxx Modified: incubator/ooo/trunk/main/basegfx/inc/basegfx/numeric/ftools.hxx URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/basegfx/inc/basegfx/numeric/ftools.hxx?rev=1376528&r1=1376527&r2=1376528&view=diff ============================================================================== --- incubator/ooo/trunk/main/basegfx/inc/basegfx/numeric/ftools.hxx (original) +++ incubator/ooo/trunk/main/basegfx/inc/basegfx/numeric/ftools.hxx Thu Aug 23 15:03:21 2012 @@ -139,8 +139,38 @@ namespace basegfx return v / M_PI_2 * 90.0; } + /** Snap v to nearest multiple of fStep, from negative and + positive side. - class fTools + 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 fTools { /// Threshold value for equalZero() static double mfSmallValue; Modified: incubator/ooo/trunk/main/basegfx/source/numeric/ftools.cxx URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/basegfx/source/numeric/ftools.cxx?rev=1376528&r1=1376527&r2=1376528&view=diff ============================================================================== --- incubator/ooo/trunk/main/basegfx/source/numeric/ftools.cxx (original) +++ incubator/ooo/trunk/main/basegfx/source/numeric/ftools.cxx Thu Aug 23 15:03:21 2012 @@ -24,11 +24,88 @@ // MARKER(update_precomp.py): autogen include statement, do not remove #include "precompiled_basegfx.hxx" #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 // eof Modified: incubator/ooo/trunk/main/drawinglayer/source/primitive2d/gridprimitive2d.cxx URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/drawinglayer/source/primitive2d/gridprimitive2d.cxx?rev=1376528&r1=1376527&r2=1376528&view=diff ============================================================================== --- incubator/ooo/trunk/main/drawinglayer/source/primitive2d/gridprimitive2d.cxx (original) +++ incubator/ooo/trunk/main/drawinglayer/source/primitive2d/gridprimitive2d.cxx Thu Aug 23 15:03:21 2012 @@ -129,97 +129,141 @@ 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) - { - const bool bXZero(basegfx::fTools::equalZero(fX)); + if(rViewInformation.getDiscreteViewport().isEmpty()) + { + // 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); - for(double fY(0.0); fY < aScale.getY(); fY += fStepY) - { - const bool bYZero(basegfx::fTools::equalZero(fY)); + // intersect with visible part + aExtendedViewport.intersect(rViewInformation.getDiscreteViewport()); - 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)) + if(!aExtendedViewport.isEmpty()) + { + // 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(!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)); + + for(double fY(aExtendedViewport.getMinY()); fY < aExtendedViewport.getMaxY(); fY += fStepY) + { + const bool bYZero(basegfx::fTools::equalZero(fY)); + + if(!bXZero && !bYZero) { - const basegfx::B2DPoint aLogicPos(rViewInformation.getInverseObjectToViewTransformation() * aViewPos); - aPositionsCross.push_back(aLogicPos); + // 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(getSubdivisionsX() && !bYZero) - { - double fF(fX + fSmallStepX); - - for(sal_uInt32 a(1L); a < nSmallStepsX && fF < aScale.getX(); 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) - { - double fF(fY + fSmallStepY); - - for(sal_uInt32 a(1L); a < nSmallStepsY && fF < aScale.getY(); a++, fF += fSmallStepY) - { - 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); + if(getSubdivisionsX() && !bYZero) + { + double fF(fX + fSmallStepX); + + 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) + { + double fF(fY + fSmallStepY); + + for(sal_uInt32 a(1); a < nSmallStepsY && fF < aExtendedViewport.getMaxY(); a++, fF += fSmallStepY) + { + 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); - - // 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()) - { - // 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())); - } - } + // add PointArrayPrimitive2D if point markers were added + if(nCountPoint) + { + aRetval[nInsertCounter++] = Primitive2DReference(new PointArrayPrimitive2D(aPositionsPoint, getBColor())); + } + + // add MarkerArrayPrimitive2D if cross markers were added + if(nCountCross) + { + 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())); + } + } + } } return aRetval;