summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAlvin Penner <penner@vaxxine.com>2014-01-26 20:09:05 +0000
committerapenner <penner@vaxxine.com>2014-01-26 20:09:05 +0000
commit99a8b0ae7da4f776f7ec85862ab52c29a4abb164 (patch)
tree219644bb547e8aea49805cf0360d623d8c970e45 /src
parentCheck file existance and clean up memory issues thanks to KK and Johan (diff)
downloadinkscape-99a8b0ae7da4f776f7ec85862ab52c29a4abb164.tar.gz
inkscape-99a8b0ae7da4f776f7ec85862ab52c29a4abb164.zip
sbasis-to-bezier : add support for case where Bezier control arm length is zero (Bug 1272119)
Fixed bugs: - https://launchpad.net/bugs/1272119 (bzr r12980)
Diffstat (limited to 'src')
-rw-r--r--src/2geom/sbasis-to-bezier.cpp29
1 files changed, 21 insertions, 8 deletions
diff --git a/src/2geom/sbasis-to-bezier.cpp b/src/2geom/sbasis-to-bezier.cpp
index bd88f93c0..0525be04b 100644
--- a/src/2geom/sbasis-to-bezier.cpp
+++ b/src/2geom/sbasis-to-bezier.cpp
@@ -242,24 +242,38 @@ void sbasis_to_cubic_bezier (std::vector<Point> & bz, D2<SBasis> const& sb)
// calculate Bezier control arms
- if (std::abs(xprime[1]*yprime[0] - yprime[1]*xprime[0]) > 1.e-5) { // general case : fit mid fxn value
+ if ((std::abs(xprime[0]) < EPSILON) && (std::abs(yprime[0]) < EPSILON)
+ && ((std::abs(xprime[1]) > EPSILON) || (std::abs(yprime[1]) > EPSILON))) { // degenerate handle at 0 : use distance of closest approach
+ numer = midx*xprime[1] + midy*yprime[1];
+ denom = 3.0*(xprime[1]*xprime[1] + yprime[1]*yprime[1]);
+ delx[0] = 0;
+ dely[0] = 0;
+ delx[1] = -xprime[1]*numer/denom;
+ dely[1] = -yprime[1]*numer/denom;
+ } else if ((std::abs(xprime[1]) < EPSILON) && (std::abs(yprime[1]) < EPSILON)
+ && ((std::abs(xprime[0]) > EPSILON) || (std::abs(yprime[0]) > EPSILON))) { // degenerate handle at 1 : ditto
+ numer = midx*xprime[0] + midy*yprime[0];
+ denom = 3.0*(xprime[0]*xprime[0] + yprime[0]*yprime[0]);
+ delx[0] = xprime[0]*numer/denom;
+ dely[0] = yprime[0]*numer/denom;
+ delx[1] = 0;
+ dely[1] = 0;
+ } else if (std::abs(xprime[1]*yprime[0] - yprime[1]*xprime[0]) > EPSILON) { // general case : fit mid fxn value
denom = xprime[1]*yprime[0] - yprime[1]*xprime[0];
for (int i = 0; i < 2; ++i) {
numer = xprime[1 - i]*midy - yprime[1 - i]*midx;
delx[i] = xprime[i]*numer/denom/3;
dely[i] = yprime[i]*numer/denom/3;
}
- }
- else if ((xprime[0]*xprime[1] < 0) || (yprime[0]*yprime[1] < 0)) { // symmetric case : use distance of closest approach
+ } else if ((xprime[0]*xprime[1] < 0) || (yprime[0]*yprime[1] < 0)) { // symmetric case : use distance of closest approach
numer = midx*xprime[0] + midy*yprime[0];
denom = 6.0*(xprime[0]*xprime[0] + yprime[0]*yprime[0]);
delx[0] = xprime[0]*numer/denom;
dely[0] = yprime[0]*numer/denom;
delx[1] = -delx[0];
dely[1] = -dely[0];
- }
- else { // anti-symmetric case : fit mid slope
- // calculate slope at t = 0.5
+ } else { // anti-symmetric case : fit mid slope
+ // calculate slope at t = 0.5
midx = 0;
div = 1;
for (size_t i = 0; i < sb[X].size(); ++i) {
@@ -279,8 +293,7 @@ void sbasis_to_cubic_bezier (std::vector<Point> & bz, D2<SBasis> const& sb)
delx[i] = xprime[0]*numer/denom;
dely[i] = yprime[0]*numer/denom;
}
- }
- else { // linear case
+ } else { // linear case
for (int i = 0; i < 2; ++i) {
delx[i] = (bz[3][X] - bz[0][X])/3;
dely[i] = (bz[3][Y] - bz[0][Y])/3;