summaryrefslogtreecommitdiffstats
path: root/src/helper
diff options
context:
space:
mode:
Diffstat (limited to 'src/helper')
-rw-r--r--src/helper/geom-curves.h10
-rw-r--r--src/helper/geom-pathstroke.cpp285
-rw-r--r--src/helper/geom-pathstroke.h50
-rw-r--r--src/helper/geom.cpp57
-rw-r--r--src/helper/geom.h7
-rw-r--r--src/helper/png-write.cpp12
-rw-r--r--src/helper/png-write.h7
7 files changed, 182 insertions, 246 deletions
diff --git a/src/helper/geom-curves.h b/src/helper/geom-curves.h
index 4586a346c..7357403f7 100644
--- a/src/helper/geom-curves.h
+++ b/src/helper/geom-curves.h
@@ -14,15 +14,13 @@
* Released under GNU GPL
*/
-#include <2geom/hvlinesegment.h>
#include <2geom/line.h>
#include <2geom/bezier-curve.h>
/// \todo un-inline this function
-inline bool is_straight_curve(Geom::Curve const & c) {
- if( dynamic_cast<Geom::LineSegment const*>(&c) ||
- dynamic_cast<Geom::HLineSegment const*>(&c) ||
- dynamic_cast<Geom::VLineSegment const*>(&c) )
+inline bool is_straight_curve(Geom::Curve const & c)
+{
+ if( dynamic_cast<Geom::LineSegment const*>(&c) )
{
return true;
}
@@ -31,7 +29,7 @@ inline bool is_straight_curve(Geom::Curve const & c) {
Geom::BezierCurve const *curve = dynamic_cast<Geom::BezierCurve const *>(&c);
if (curve) {
Geom::Line line(curve->initialPoint(), curve->finalPoint());
- std::vector<Geom::Point> pts = curve->points();
+ std::vector<Geom::Point> pts = curve->controlPoints();
for (unsigned i = 1; i < pts.size() - 1; ++i) {
if (!are_near(pts[i], line))
return false;
diff --git a/src/helper/geom-pathstroke.cpp b/src/helper/geom-pathstroke.cpp
index 292ba3044..c73a9e9e7 100644
--- a/src/helper/geom-pathstroke.cpp
+++ b/src/helper/geom-pathstroke.cpp
@@ -1,7 +1,8 @@
-/* Author:
+/* Authors:
* Liam P. White
+ * Tavmjong Bah
*
- * Copyright (C) 2014-2015 Author
+ * Copyright (C) 2014-2015 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -10,89 +11,20 @@
#include <2geom/path-sink.h>
#include <2geom/point.h>
#include <2geom/bezier-curve.h>
-#include <2geom/svg-elliptical-arc.h>
+#include <2geom/elliptical-arc.h>
#include <2geom/sbasis-to-bezier.h> // cubicbezierpath_from_sbasis
#include <2geom/path-intersection.h>
+#include <2geom/circle.h>
#include "helper/geom-pathstroke.h"
namespace Geom {
-// 2geom/circle-circle.cpp, no header
-int circle_circle_intersection(Point X0, double r0, Point X1, double r1, Point &p0, Point &p1);
-
-/**
- * Determine the intersection points between a circle C0 and a line defined
- * by two points, X0 and X1.
- *
- * Which intersection point is assigned to p0 or p1 is unspecified, and callers
- * should not depend on any particular intersection always being assigned to p0.
- *
- * Returns:
- * If the line and circle do not cross, 0 is returned.
- * If solution(s) exist, 2 is returned, and the results are written to p0 and p1.
- */
-static int circle_line_intersection(Circle C0, Point X0, Point X1, Point &p0, Point &p1)
-{
- /* equation of a circle: (x - h)^2 + (y - k)^2 = r^2 */
- Coord r = C0.ray();
- Coord h = C0.center()[X];
- Coord k = C0.center()[Y];
-
- Coord x0, y0;
- Coord x1, y1;
-
- if (are_near(X1[X], X0[X])) {
- /* slope is undefined (vertical line) */
- Coord c = X0[X];
- Coord det = r*r - (c-h)*(c-h);
-
- /* no intersection */
- if (det < 0)
- return 0;
-
- /* solve for y */
- y0 = k + std::sqrt(det);
- y1 = k - std::sqrt(det);
-
- // x == c (always)
- x0 = c;
- x1 = c;
- } else {
- /* equation of a line: y = mx + b */
- Coord m = (X1[Y] - X0[Y]) / (X1[X] - X0[X]);
- Coord b = X0[Y] - m*X0[X];
-
- /* obtain quadratic for x: */
- Coord A = m*m + 1;
- Coord B = 2*h - 2*b*m + 2*k*m;
- Coord C = b*b + h*h + k*k - r*r - 2*b*k;
-
- Coord det = B*B - 4*A*C;
-
- /* no intersection, circle and line do not cross */
- if (det < 0)
- return 0;
-
- /* solve quadratic */
- x0 = (B + std::sqrt(det)) / (2*A);
- x1 = (B - std::sqrt(det)) / (2*A);
-
- /* substitute the calculated x times to determine the y values */
- y0 = m*x0 + b;
- y1 = m*x1 + b;
- }
-
- p0 = Point(x0, y0);
- p1 = Point(x1, y1);
-
- return 2;
-}
static Point intersection_point(Point origin_a, Point vector_a, Point origin_b, Point vector_b)
{
- Coord denom = cross(vector_b, vector_a);
+ Coord denom = cross(vector_a, vector_b);
if (!are_near(denom,0.)) {
- Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom;
+ Coord t = (cross(vector_b, origin_a) + cross(origin_b, vector_b)) / denom;
return origin_a + vector_a*t;
}
return Point(infinity(), infinity());
@@ -129,14 +61,14 @@ namespace {
// Internal data structure
-struct join_data
-{
+struct join_data {
join_data(Geom::Path &_res, Geom::Path const&_outgoing, Geom::Point _in_tang, Geom::Point _out_tang, double _miter, double _width)
- : res(_res), outgoing(_outgoing), in_tang(_in_tang)
- , out_tang(_out_tang), miter(_miter), width(_width) {}
+ : res(_res), outgoing(_outgoing), in_tang(_in_tang), out_tang(_out_tang), miter(_miter), width(_width) {};
- // I/O
+ // contains the current path that is being built on
Geom::Path &res;
+
+ // contains the next curve to append
Geom::Path const& outgoing;
// input tangents
@@ -160,7 +92,7 @@ void bevel_join(join_data jd)
void round_join(join_data jd)
{
- jd.res.appendNew<Geom::SVGEllipticalArc>(jd.width, jd.width, 0, false, jd.width <= 0, jd.outgoing.initialPoint());
+ jd.res.appendNew<Geom::EllipticalArc>(jd.width, jd.width, 0, false, jd.width <= 0, jd.outgoing.initialPoint());
jd.res.append(jd.outgoing);
}
@@ -226,18 +158,20 @@ void miter_join_internal(join_data jd, bool clip)
void miter_join(join_data jd) { miter_join_internal(jd, false); }
void miter_clip_join(join_data jd) { miter_join_internal(jd, true); }
-Geom::Point pick_solution(Geom::Point points[2], Geom::Point tang2, Geom::Point endPt)
+Geom::Point pick_solution(std::vector<Geom::ShapeIntersection> points, Geom::Point tang2, Geom::Point endPt)
{
+ assert(points.size() == 2);
Geom::Point sol;
- if ( dot(tang2,points[0]-endPt) > 0 ) {
+ if ( dot(tang2, points[0].point() - endPt) > 0 ) {
// points[0] is bad, choose points[1]
sol = points[1];
- } else if ( dot(tang2,points[1]-endPt) > 0 ) { // points[0] could be good, now check points[1]
+ } else if ( dot(tang2, points[1].point() - endPt) > 0 ) { // points[0] could be good, now check points[1]
// points[1] is bad, choose points[0]
sol = points[0];
} else {
// both points are good, choose nearest
- sol = ( distanceSq(endPt, points[0]) < distanceSq(endPt, points[1]) ) ? points[0] : points[1];
+ sol = ( distanceSq(endPt, points[0].point()) < distanceSq(endPt, points[1].point()) )
+ ? points[0].point() : points[1].point();
}
return sol;
}
@@ -261,9 +195,8 @@ void extrapolate_join(join_data jd)
bool inc_ls = !circle1.center().isFinite();
bool out_ls = !circle2.center().isFinite();
- Geom::Point points[2];
+ std::vector<Geom::ShapeIntersection> points;
- int solutions = 0;
Geom::EllipticalArc *arc1 = NULL;
Geom::EllipticalArc *arc2 = NULL;
Geom::Point sol;
@@ -272,33 +205,29 @@ void extrapolate_join(join_data jd)
if (!inc_ls && !out_ls) {
// Two circles
- solutions = Geom::circle_circle_intersection(circle1.center(), circle1.ray(),
- circle2.center(), circle2.ray(),
- points[0], points[1]);
- if (solutions == 2) {
+ points = circle1.intersect(circle2);
+ if (points.size() == 2) {
sol = pick_solution(points, tang2, endPt);
- arc1 = circle1.arc(startPt, 0.5*(startPt+sol), sol, true);
- arc2 = circle2.arc(sol, 0.5*(sol+endPt), endPt, true);
+ arc1 = circle1.arc(startPt, 0.5*(startPt+sol), sol);
+ arc2 = circle2.arc(sol, 0.5*(sol+endPt), endPt);
}
} else if (inc_ls && !out_ls) {
// Line and circle
- solutions = Geom::circle_line_intersection(circle2, incoming.initialPoint(), incoming.finalPoint(), points[0], points[1]);
-
- if (solutions == 2) {
+ points = circle2.intersect(Line(incoming.initialPoint(), incoming.finalPoint()));
+ if (points.size() == 2) {
sol = pick_solution(points, tang2, endPt);
- arc2 = circle2.arc(sol, 0.5*(sol+endPt), endPt, true);
+ arc2 = circle2.arc(sol, 0.5*(sol+endPt), endPt);
}
} else if (!inc_ls && out_ls) {
// Circle and line
- solutions = Geom::circle_line_intersection(circle1, outgoing.initialPoint(), outgoing.finalPoint(), points[0], points[1]);
-
- if (solutions == 2) {
+ points = circle1.intersect(Line(outgoing.initialPoint(), outgoing.finalPoint()));
+ if (points.size() == 2) {
sol = pick_solution(points, tang2, endPt);
- arc1 = circle1.arc(startPt, 0.5*(sol+startPt), sol, true);
+ arc1 = circle1.arc(startPt, 0.5*(sol+startPt), sol);
}
}
- if (solutions != 2)
+ if (points.size() != 2)
// no solutions available, fall back to miter
return miter_clip_join(jd);
@@ -342,25 +271,24 @@ void extrapolate_join(join_data jd)
Geom::Ray end_ray(center, sol);
Geom::Line limit_line(center, 0); // Angle set below
- if (Geom::cross(start_ray.versor(), end_ray.versor()) > 0) {
+ if (Geom::cross(start_ray.versor(), end_ray.versor()) < 0) {
limit_line.setAngle(start_ray.angle() - limit_angle);
} else {
limit_line.setAngle(start_ray.angle() + limit_angle);
}
- Geom::EllipticalArc *arc_center = circle_center.arc(point_on_path, 0.5*(point_on_path + sol), sol, true);
+ Geom::EllipticalArc *arc_center = circle_center.arc(point_on_path, 0.5*(point_on_path + sol), sol);
if (arc_center && arc_center->sweepAngle() > limit_angle) {
// We need to clip
clipped = true;
if (!inc_ls) {
// Incoming circular
- solutions = Geom::circle_line_intersection(circle1, limit_line.pointAt(0), limit_line.pointAt(1), points[0], points[1]);
-
- if (solutions == 2) {
+ points = circle1.intersect(limit_line);
+ if (points.size() == 2) {
p1 = pick_solution(points, tang2, endPt);
delete arc1;
- arc1 = circle1.arc(startPt, 0.5*(p1+startPt), p1, true);
+ arc1 = circle1.arc(startPt, 0.5*(p1+startPt), p1);
}
} else {
p1 = Geom::intersection_point(startPt, tang1, limit_line.pointAt(0), limit_line.versor());
@@ -368,12 +296,11 @@ void extrapolate_join(join_data jd)
if (!out_ls) {
// Outgoing circular
- solutions = Geom::circle_line_intersection(circle2, limit_line.pointAt(0), limit_line.pointAt(1), points[0], points[1]);
-
- if (solutions == 2) {
+ points = circle2.intersect(limit_line);
+ if (points.size() == 2) {
p2 = pick_solution(points, tang1, endPt);
delete arc2;
- arc2 = circle2.arc(p2, 0.5*(p2+endPt), endPt, true);
+ arc2 = circle2.arc(p2, 0.5*(p2+endPt), endPt);
}
} else {
p2 = Geom::intersection_point(endPt, tang2, limit_line.pointAt(0), limit_line.versor());
@@ -415,9 +342,28 @@ void join_inside(join_data jd)
Geom::Path const& temp = jd.outgoing;
Geom::Crossings cross = Geom::crossings(res, temp);
- if (cross.size() == 1) {
- Geom::Path d1 = res.portion(0., cross[0].ta);
- Geom::Path d2 = temp.portion(cross[0].tb, temp.size());
+ int solution = -1; // lol, really hope there aren't more than INT_MAX crossings
+ if (cross.size() == 1) solution = 0;
+ else if (cross.size() > 1) {
+ // I am not sure how well this will work -- we pick the join node closest
+ // to the cross point of the paths
+ /*Geom::Point original = res.finalPoint()+Geom::rot90(jd.in_tang)*jd.width;
+ Geom::Coord trial = Geom::L2(res.pointAt(cross[0].ta)-original);
+ solution = 0;
+ for (size_t i = 1; i < cross.size(); ++i) {
+ //printf("Trying %d\n", i);
+ Geom::Coord test = Geom::L2(res.pointAt(cross[i].ta)-original);
+ if (test < trial) {
+ trial = test;
+ solution = i;
+ //printf("Found improved solution: %f\n", trial);
+ }
+ }*/
+ }
+
+ if (solution != -1) {
+ Geom::Path d1 = res.portion(0., cross[solution].ta);
+ Geom::Path d2 = temp.portion(cross[solution].tb, temp.size());
// Watch for bugs in 2geom crossing regarding severe inflection points
res.clear();
@@ -437,47 +383,6 @@ void tangents(Geom::Point tang[2], Geom::Curve const& incoming, Geom::Curve cons
tang[0] = tang1, tang[1] = tang2;
}
-void outline_helper(Geom::Path &res, Geom::Path const& temp, Geom::Point in_tang, Geom::Point out_tang, double width, double miter, Inkscape::LineJoinType join)
-{
- if (res.size() == 0 || temp.size() == 0)
- return;
-
- Geom::Curve const& outgoing = temp.front();
- if (Geom::are_near(res.finalPoint(), outgoing.initialPoint())) {
- // if the points are /that/ close, just ignore this one
- res.setFinal(temp.initialPoint());
- res.append(temp);
- return;
- }
-
- join_data jd(res, temp, in_tang, out_tang, miter, width);
-
- bool on_outside = (Geom::cross(in_tang, out_tang) < 0);
-
- if (on_outside) {
- join_func *jf;
- switch (join) {
- case Inkscape::JOIN_BEVEL:
- jf = &bevel_join;
- break;
- case Inkscape::JOIN_ROUND:
- jf = &round_join;
- break;
- case Inkscape::JOIN_EXTRAPOLATE:
- jf = &extrapolate_join;
- break;
- case Inkscape::JOIN_MITER_CLIP:
- jf = &miter_clip_join;
- break;
- default:
- jf = &miter_join;
- }
- jf(jd);
- } else {
- join_inside(jd);
- }
-}
-
// Offsetting a line segment is mathematically stable and quick to do
Geom::LineSegment offset_line(Geom::LineSegment const& l, double width)
{
@@ -512,12 +417,12 @@ void get_cubic_data(Geom::CubicBezier const& bez, double time, double& len, doub
if (Geom::are_near(l, 0)) {
return; // this isn't a segment...
}
- rad = 1e8;
+ rad = 1e8;
} else {
- rad = -l * (Geom::dot(der2, der2) / Geom::cross(der3, der2));
+ rad = -l * (Geom::dot(der2, der2) / Geom::cross(der2, der3));
}
} else {
- rad = -l * (Geom::dot(der1, der1) / Geom::cross(der2, der1));
+ rad = -l * (Geom::dot(der1, der1) / Geom::cross(der1, der2));
}
len = l;
}
@@ -564,7 +469,7 @@ void offset_cubic(Geom::Path& p, Geom::CubicBezier const& bez, double width, dou
// reached maximum recursive depth
// don't bother with any more correction
if (levels == 0) {
- p.append(c, Geom::Path::STITCH_DISCONTINUOUS);
+ p.append(c);
return;
}
@@ -596,7 +501,7 @@ void offset_quadratic(Geom::Path& p, Geom::QuadraticBezier const& bez, double wi
// cheat
// it's faster
// seriously
- std::vector<Geom::Point> points = bez.points();
+ std::vector<Geom::Point> points = bez.controlPoints();
Geom::Point b1 = points[0] + (2./3) * (points[1] - points[0]);
Geom::Point b2 = b1 + (1./3) * (points[2] - points[0]);
Geom::CubicBezier cub = Geom::CubicBezier(points[0], b1, b2, points[2]);
@@ -684,7 +589,7 @@ Geom::PathVector outline(Geom::Path const& input, double width, double miter, Li
Geom::PathBuilder res;
Geom::Path with_dir = half_outline(input, width/2., miter, join);
- Geom::Path against_dir = half_outline(input.reverse(), width/2., miter, join);
+ Geom::Path against_dir = half_outline(input.reversed(), width/2., miter, join);
res.moveTo(with_dir[0].initialPoint());
res.append(with_dir);
@@ -733,13 +638,16 @@ Geom::Path half_outline(Geom::Path const& input, double width, double miter, Lin
Geom::Path temp;
Geom::Point tang[2];
+ res.setStitching(true);
+ temp.setStitching(true);
+
res.start(start);
// Do two curves at a time for efficiency, since the join function needs to know the outgoing curve as well
const size_t k = (input.back_closed().isDegenerate() && input.closed())
?input.size_default()-1:input.size_default();
for (size_t u = 0; u < k; u += 2) {
- temp = Geom::Path();
+ temp.clear();
offset_curve(temp, &input[u], width);
@@ -748,27 +656,27 @@ Geom::Path half_outline(Geom::Path const& input, double width, double miter, Lin
res.append(temp);
} else {
tangents(tang, input[u-1], input[u]);
- outline_helper(res, temp, tang[0], tang[1], width, miter, join);
+ outline_join(res, temp, tang[0], tang[1], width, miter, join);
}
// odd number of paths
if (u < k - 1) {
- temp = Geom::Path();
+ temp.clear();
offset_curve(temp, &input[u+1], width);
tangents(tang, input[u], input[u+1]);
- outline_helper(res, temp, tang[0], tang[1], width, miter, join);
+ outline_join(res, temp, tang[0], tang[1], width, miter, join);
}
}
if (input.closed()) {
Geom::Curve const &c1 = res.back();
Geom::Curve const &c2 = res.front();
- temp = Geom::Path();
+ temp.clear();
temp.append(c1);
Geom::Path temp2;
temp2.append(c2);
tangents(tang, input.back(), input.front());
- outline_helper(temp, temp2, tang[0], tang[1], width, miter, join);
+ outline_join(temp, temp2, tang[0], tang[1], width, miter, join);
res.erase(res.begin());
res.erase_last();
//
@@ -779,6 +687,47 @@ Geom::Path half_outline(Geom::Path const& input, double width, double miter, Lin
return res;
}
+void outline_join(Geom::Path &res, Geom::Path const& temp, Geom::Point in_tang, Geom::Point out_tang, double width, double miter, Inkscape::LineJoinType join)
+{
+ if (res.size() == 0 || temp.size() == 0)
+ return;
+
+ Geom::Curve const& outgoing = temp.front();
+ if (Geom::are_near(res.finalPoint(), outgoing.initialPoint())) {
+ // if the points are /that/ close, just ignore this one
+ res.setFinal(temp.initialPoint());
+ res.append(temp);
+ return;
+ }
+
+ join_data jd(res, temp, in_tang, out_tang, miter, width);
+
+ bool on_outside = (Geom::cross(in_tang, out_tang) > 0);
+
+ if (on_outside) {
+ join_func *jf;
+ switch (join) {
+ case Inkscape::JOIN_BEVEL:
+ jf = &bevel_join;
+ break;
+ case Inkscape::JOIN_ROUND:
+ jf = &round_join;
+ break;
+ case Inkscape::JOIN_EXTRAPOLATE:
+ jf = &extrapolate_join;
+ break;
+ case Inkscape::JOIN_MITER_CLIP:
+ jf = &miter_clip_join;
+ break;
+ default:
+ jf = &miter_join;
+ }
+ jf(jd);
+ } else {
+ join_inside(jd);
+ }
+}
+
} // namespace Inkscape
/*
diff --git a/src/helper/geom-pathstroke.h b/src/helper/geom-pathstroke.h
index 0cfb9f817..6697273cf 100644
--- a/src/helper/geom-pathstroke.h
+++ b/src/helper/geom-pathstroke.h
@@ -1,10 +1,11 @@
#ifndef INKSCAPE_HELPER_PATH_STROKE_H
#define INKSCAPE_HELPER_PATH_STROKE_H
-/* Author:
+/* Authors:
* Liam P. White
+ * Tavmjong Bah
*
- * Copyright (C) 2014-2015 Author
+ * Copyright (C) 2014-2015 Authors
*
* Released under GNU GPL, read the file 'COPYING' for more information
*/
@@ -26,21 +27,54 @@ enum LineCapType {
BUTT_FLAT,
BUTT_ROUND,
BUTT_SQUARE,
- BUTT_PEAK, // ?
+ BUTT_PEAK, // This is not a line ending supported by the SVG standard.
};
/**
+ * Strokes the path given by @a input.
+ * Joins may behave oddly if the width is negative.
+ *
+ * @param[in] input Input path.
+ * @param[in] width Stroke width.
+ * @param[in] miter Miter limit. Only used when @a join is one of JOIN_MITER, JOIN_MITER_CLIP, and JOIN_EXTRAPOLATE.
+ * @param[in] join Line join type used during offset. Member of LineJoinType enum.
+ * @param[in] cap Line cap type used during stroking. Member of LineCapType enum.
+ *
+ * @return Stroked path.
+ * If the input path is closed, the resultant vector will contain two paths.
+ * Otherwise, there should be only one in the output.
+ */
+Geom::PathVector outline(Geom::Path const& input, double width, double miter, LineJoinType join = JOIN_BEVEL, LineCapType cap = BUTT_FLAT);
+
+/**
* Offset the input path by @a width.
* Joins may behave oddly if the width is negative.
*
- * @param input
- * @param width Amount to offset.
- * @param miter Miter limit. Only used with JOIN_MITER, JOIN_MITER_CLIP, and JOIN_EXTRAPOLATE.
- * @param join
+ * @param[in] input Input path.
+ * @param[in] width Amount to offset.
+ * @param[in] miter Miter limit. Only used when @a join is one of JOIN_MITER, JOIN_MITER_CLIP, and JOIN_EXTRAPOLATE.
+ * @param[in] join Line join type used during offset. Member of LineJoinType enum.
+ *
+ * @return Offsetted output.
*/
Geom::Path half_outline(Geom::Path const& input, double width, double miter, LineJoinType join = JOIN_BEVEL);
-Geom::PathVector outline(Geom::Path const& input, double width, double miter, LineJoinType join = JOIN_BEVEL, LineCapType cap = BUTT_FLAT);
+/**
+ * Builds a join on the provided path.
+ * Joins may behave oddly if the width is negative.
+ *
+ * @param[inout] res The path to build the join on.
+ * The outgoing path (or a portion thereof) will be appended after the join is created.
+ * Previous segments may be modified as an optimization, beware!
+ *
+ * @param[in] outgoing The segment to append on the outgoing portion of the join.
+ * @param[in] in_tang The end tangent to consider on the input path.
+ * @param[in] out_tang The begin tangent to consider on the output path.
+ * @param[in] width
+ * @param[in] miter
+ * @param[in] join
+ */
+void outline_join(Geom::Path &res, Geom::Path const& outgoing, Geom::Point in_tang, Geom::Point out_tang, double width, double miter, LineJoinType join);
} // namespace Inkscape
diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp
index 91689375f..ecb330b01 100644
--- a/src/helper/geom.cpp
+++ b/src/helper/geom.cpp
@@ -15,8 +15,7 @@
#include <typeinfo>
#include <2geom/pathvector.h>
#include <2geom/path.h>
-#include <2geom/bezier-curve.h>
-#include <2geom/hvlinesegment.h>
+#include <2geom/curves.h>
#include <2geom/transforms.h>
#include <2geom/rect.h>
#include <2geom/coord.h>
@@ -266,14 +265,13 @@ geom_cubic_bbox_wind_distance (Geom::Coord x000, Geom::Coord y000,
Geom::Coord tolerance)
{
Geom::Coord x0, y0, x1, y1, len2;
- int needdist, needwind, needline;
+ int needdist, needwind;
const Geom::Coord Px = pt[X];
const Geom::Coord Py = pt[Y];
needdist = 0;
needwind = 0;
- needline = 0;
if (bbox) cubic_bbox (x000, y000, x001, y001, x011, y011, x111, y111, *bbox);
@@ -303,8 +301,6 @@ geom_cubic_bbox_wind_distance (Geom::Coord x000, Geom::Coord y000,
/* fixme: (Lauris) */
if (((y1 - y0) > 5.0) || ((x1 - x0) > 5.0)) {
needdist = 1;
- } else {
- needline = 1;
}
}
}
@@ -315,8 +311,6 @@ geom_cubic_bbox_wind_distance (Geom::Coord x000, Geom::Coord y000,
/* fixme: (Lauris) */
if (((y1 - y0) > 5.0) || ((x1 - x0) > 5.0)) {
needwind = 1;
- } else {
- needline = 1;
}
}
}
@@ -345,7 +339,7 @@ geom_cubic_bbox_wind_distance (Geom::Coord x000, Geom::Coord y000,
geom_cubic_bbox_wind_distance (x000, y000, x00t, y00t, x0tt, y0tt, xttt, yttt, pt, NULL, wind, best, tolerance);
geom_cubic_bbox_wind_distance (xttt, yttt, x1tt, y1tt, x11t, y11t, x111, y111, pt, NULL, wind, best, tolerance);
- } else if (1 || needline) {
+ } else {
geom_line_wind_distance (x000, y000, x111, y111, pt, wind, best);
}
}
@@ -473,8 +467,8 @@ pathv_to_linear_and_cubic_beziers( Geom::PathVector const &pathv )
for (Geom::PathVector::const_iterator pit = pathv.begin(); pit != pathv.end(); ++pit) {
output.push_back( Geom::Path() );
+ output.back().setStitching(true);
output.back().start( pit->initialPoint() );
- output.back().close( pit->closed() );
for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit) {
if (is_straight_curve(*cit)) {
@@ -488,10 +482,13 @@ pathv_to_linear_and_cubic_beziers( Geom::PathVector const &pathv )
} else {
// convert all other curve types to cubicbeziers
Geom::Path cubicbezier_path = Geom::cubicbezierpath_from_sbasis(cit->toSBasis(), 0.1);
+ cubicbezier_path.close(false);
output.back().append(cubicbezier_path);
}
}
}
+
+ output.back().close( pit->closed() );
}
return output;
@@ -525,8 +522,7 @@ pathv_to_linear( Geom::PathVector const &pathv, double /*maxdisp*/)
}
else { /* all others must be Bezier curves */
Geom::BezierCurve const *curve = dynamic_cast<Geom::BezierCurve const *>(&*cit);
- Geom::CubicBezier b((*curve)[0], (*curve)[1], (*curve)[2], (*curve)[3]);
- std::vector<Geom::Point> bzrpoints = b.points();
+ std::vector<Geom::Point> bzrpoints = curve->controlPoints();
Geom::Point A = bzrpoints[0];
Geom::Point B = bzrpoints[1];
Geom::Point C = bzrpoints[2];
@@ -584,7 +580,7 @@ pathv_to_cubicbezier( Geom::PathVector const &pathv)
pitCubic.appendNew<Geom::LineSegment>( pitCubic.initialPoint() );
pitCubic.close(true);
}
- for (Geom::Path::const_iterator cit = pitCubic.begin(); cit != pitCubic.end_open(); ++cit) {
+ for (Geom::Path::iterator cit = pitCubic.begin(); cit != pitCubic.end_open(); ++cit) {
if (is_straight_curve(*cit)) {
Geom::CubicBezier b(cit->initialPoint(), cit->pointAt(0.3334) + Geom::Point(cubicGap,cubicGap), cit->finalPoint(), cit->finalPoint());
output.back().append(b);
@@ -854,41 +850,6 @@ recursive_bezier4(const double x1, const double y1,
recursive_bezier4(x1234, y1234, x234, y234, x34, y34, x4, y4, m_points, level + 1);
}
-
-/**
- * rounds all corners of the rectangle 'outwards', i.e. x0 and y0 are floored, x1 and y1 are ceiled.
- */
-void round_rectangle_outwards(Geom::Rect & rect) {
- Geom::Interval ints[2];
- for (int i=0; i < 2; i++) {
- ints[i] = Geom::Interval(std::floor(rect[i][0]), std::ceil(rect[i][1]));
- }
- rect = Geom::Rect(ints[0], ints[1]);
-}
-
-
-namespace Geom {
-
-bool transform_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon) {
- return
- Geom::are_near(m0[0], m1[0], epsilon) &&
- Geom::are_near(m0[1], m1[1], epsilon) &&
- Geom::are_near(m0[2], m1[2], epsilon) &&
- Geom::are_near(m0[3], m1[3], epsilon);
-}
-
-
-bool translate_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon) {
- return Geom::are_near(m0[4], m1[4], epsilon) && Geom::are_near(m0[5], m1[5], epsilon);
-}
-
-
-bool matrix_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon) {
- return transform_equalp(m0, m1, epsilon) && translate_equalp(m0, m1, epsilon);
-}
-
-} //end namespace Geom
-
/*
Local Variables:
mode:c++
diff --git a/src/helper/geom.h b/src/helper/geom.h
index 3232d9fd5..d49e2070c 100644
--- a/src/helper/geom.h
+++ b/src/helper/geom.h
@@ -33,13 +33,6 @@ void recursive_bezier4(const double x1, const double y1, const double x2, const
std::vector<Geom::Point> &pointlist,
int level);
-void round_rectangle_outwards(Geom::Rect & rect);
-
-namespace Geom{
-bool transform_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon);
-bool translate_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon);
-bool matrix_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon);
-}
#endif // INKSCAPE_HELPER_GEOM_H
/*
diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp
index 32e50b537..fc365c435 100644
--- a/src/helper/png-write.cpp
+++ b/src/helper/png-write.cpp
@@ -361,19 +361,19 @@ sp_export_get_rows(guchar const **rows, void **to_free, int row, int num_rows, v
/**
* Hide all items that are not listed in list, recursively, skipping groups and defs.
*/
-static void hide_other_items_recursively(SPObject *o, GSList *list, unsigned dkey)
+static void hide_other_items_recursively(SPObject *o, const std::vector<SPItem*> &list, unsigned dkey)
{
if ( SP_IS_ITEM(o)
&& !SP_IS_DEFS(o)
&& !SP_IS_ROOT(o)
&& !SP_IS_GROUP(o)
- && !g_slist_find(list, o) )
+ && list.end()==find(list.begin(),list.end(),o))
{
SP_ITEM(o)->invoke_hide(dkey);
}
// recurse
- if (!g_slist_find(list, o)) {
+ if (list.end()==find(list.begin(),list.end(),o)) {
for ( SPObject *child = o->firstChild() ; child; child = child->getNext() ) {
hide_other_items_recursively(child, list, dkey);
}
@@ -387,7 +387,7 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
unsigned long bgcolor,
unsigned int (*status) (float, void *),
void *data, bool force_overwrite,
- GSList *items_only)
+ const std::vector<SPItem*> &items_only)
{
return sp_export_png_file(doc, filename, Geom::Rect(Geom::Point(x0,y0),Geom::Point(x1,y1)),
width, height, xdpi, ydpi, bgcolor, status, data, force_overwrite, items_only);
@@ -399,7 +399,7 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
unsigned long bgcolor,
unsigned (*status)(float, void *),
void *data, bool force_overwrite,
- GSList *items_only)
+ const std::vector<SPItem*> &items_only)
{
g_return_val_if_fail(doc != NULL, EXPORT_ERROR);
g_return_val_if_fail(filename != NULL, EXPORT_ERROR);
@@ -457,7 +457,7 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
// We show all and then hide all items we don't want, instead of showing only requested items,
// because that would not work if the shown item references something in defs
- if (items_only) {
+ if (!items_only.empty()) {
hide_other_items_recursively(doc->getRoot(), items_only, dkey);
}
diff --git a/src/helper/png-write.h b/src/helper/png-write.h
index 8c04b25dc..2657fb635 100644
--- a/src/helper/png-write.h
+++ b/src/helper/png-write.h
@@ -14,8 +14,9 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
-#include <glib.h>
#include <2geom/forward.h>
+
+
class SPDocument;
enum ExportResult {
@@ -33,12 +34,12 @@ ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
double x0, double y0, double x1, double y1,
unsigned long int width, unsigned long int height, double xdpi, double ydpi,
unsigned long bgcolor,
- unsigned int (*status) (float, void *), void *data, bool force_overwrite = false, GSList *items_only = NULL);
+ unsigned int (*status) (float, void *), void *data, bool force_overwrite = false, const std::vector<SPItem*> &items_only = std::vector<SPItem*>());
ExportResult sp_export_png_file(SPDocument *doc, gchar const *filename,
Geom::Rect const &area,
unsigned long int width, unsigned long int height, double xdpi, double ydpi,
unsigned long bgcolor,
- unsigned int (*status) (float, void *), void *data, bool force_overwrite = false, GSList *items_only = NULL);
+ unsigned int (*status) (float, void *), void *data, bool force_overwrite = false, const std::vector<SPItem*> &items_only = std::vector<SPItem*>());
#endif // SEEN_SP_PNG_WRITE_H