incubator-ooo-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From a..@apache.org
Subject svn commit: r1367054 - /incubator/ooo/trunk/main/tools/source/generic/poly.cxx
Date Mon, 30 Jul 2012 10:40:40 GMT
Author: alg
Date: Mon Jul 30 10:40:40 2012
New Revision: 1367054

URL: http://svn.apache.org/viewvc?rev=1367054&view=rev
Log:
#115917# Better conversion of C1 and C2 bezier curve points
Patch by: osnola
Review by: alg

Modified:
    incubator/ooo/trunk/main/tools/source/generic/poly.cxx

Modified: incubator/ooo/trunk/main/tools/source/generic/poly.cxx
URL: http://svn.apache.org/viewvc/incubator/ooo/trunk/main/tools/source/generic/poly.cxx?rev=1367054&r1=1367053&r2=1367054&view=diff
==============================================================================
--- incubator/ooo/trunk/main/tools/source/generic/poly.cxx (original)
+++ incubator/ooo/trunk/main/tools/source/generic/poly.cxx Mon Jul 30 10:40:40 2012
@@ -2106,7 +2106,7 @@ void Polygon::Write( SvStream& rOStream 
 }
 
 // -----------------------------------------------------------------------
-// #i74631# numerical correction method for B2DPolygon
+// numerical correction method for B2DPolygon
 void impCorrectContinuity(basegfx::B2DPolygon& roPolygon, sal_uInt32 nIndex, sal_uInt8
nCFlag)
 {
 	const sal_uInt32 nPointCount(roPolygon.count());
@@ -2116,21 +2116,49 @@ void impCorrectContinuity(basegfx::B2DPo
 	{
 		if(roPolygon.isPrevControlPointUsed(nIndex) && roPolygon.isNextControlPointUsed(nIndex))
 		{
+            // #115917# Patch from osnola (modified, thanks for showing the porblem)
+            //
+            // The correction is needed because an integer polygon with control points
+            // is converted to double precision. When C1 or C2 is used the involved vectors
+            // may not have the same directions/lengths since these come from integer coordinates
+            //  and may have been snapped to different nearest integer coordinates. The snap
error
+            // is in the range of +-1 in y and y, thus 0.0 <= error <= sqrt(2.0). Nonetheless,
+            // it needs to be corrected to be able to detect the continuity in this points
+            // correctly.
+            //
+            // We only have the integer data here (already in double precision form, but
no mantisses 
+            // used), so the best correction is to use:
+            //
+            // for C1: The longest vector since it potentially has best preserved the original
vector.
+            //         Even better the sum of the vectors, weighted by their length. This
gives the
+            //         normal vector addition to get the vector itself, lengths need to be
preserved.
+            // for C2: The mediated vector(s) since both should be the same, but mirrored
+
+            // extract the point and vectors
 			const basegfx::B2DPoint aPoint(roPolygon.getB2DPoint(nIndex));
+            const basegfx::B2DVector aNext(roPolygon.getNextControlPoint(nIndex) - aPoint);
+            const basegfx::B2DVector aPrev(aPoint - roPolygon.getPrevControlPoint(nIndex));
+
+            // calculate common direction vector, normalize
+            const basegfx::B2DVector aDirection(aNext + aPrev);
 
 			if(POLY_SMOOTH == nCFlag)
 			{
-				// C1: apply inverse direction of prev to next, keep length of next
-				const basegfx::B2DVector aOriginalNext(roPolygon.getNextControlPoint(nIndex) - aPoint);
-				basegfx::B2DVector aNewNext(aPoint - roPolygon.getPrevControlPoint(nIndex));
-
-				aNewNext.setLength(aOriginalNext.getLength());
-				roPolygon.setNextControlPoint(nIndex, basegfx::B2DPoint(aPoint + aNewNext));
+                // C1: apply common direction vector, preserve individual lengths
+                const double fInvDirectionLen(1.0 / aDirection.getLength());
+				roPolygon.setNextControlPoint(nIndex, basegfx::B2DPoint(aPoint + (aDirection * (aNext.getLength()
* fInvDirectionLen))));
+				roPolygon.setPrevControlPoint(nIndex, basegfx::B2DPoint(aPoint - (aDirection * (aPrev.getLength()
* fInvDirectionLen))));
 			}
 			else // POLY_SYMMTR
 			{
-				// C2: apply inverse control point to next
-				roPolygon.setNextControlPoint(nIndex, (2.0 * aPoint) - roPolygon.getPrevControlPoint(nIndex));
+                // C2: get mediated length. Taking half of the unnormalized direction would
be
+                // an approximation, but not correct.
+                const double fMedLength((aNext.getLength() + aPrev.getLength()) * (0.5 /
aDirection.getLength()));
+                const basegfx::B2DVector aScaledDirection(aDirection * fMedLength);
+
+                // Bring Direction to correct length and apply
+				roPolygon.setNextControlPoint(nIndex, basegfx::B2DPoint(aPoint + aScaledDirection));
+				roPolygon.setPrevControlPoint(nIndex, basegfx::B2DPoint(aPoint - aScaledDirection));
 			}
 		}
 	}



Mime
View raw message