summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorKrzysztof Kosi??ski <tweenk.pl@gmail.com>2011-07-14 19:42:57 +0000
committerKrzysztof KosiƄski <tweenk.pl@gmail.com>2011-07-14 19:42:57 +0000
commitefbf9755460d4c4b7a3d9d43dd753afcc8a28865 (patch)
tree41a259211da187e29f9983821b4cdfea221b6ad6 /src
parentFix crashes in print preview (diff)
parentMake cms_key in SPDesktopWidget a regular ustring rather than a pointer (diff)
downloadinkscape-efbf9755460d4c4b7a3d9d43dd753afcc8a28865.tar.gz
inkscape-efbf9755460d4c4b7a3d9d43dd753afcc8a28865.zip
Merge SPCanvasArena caching layer work
(bzr r10451)
Diffstat (limited to 'src')
-rw-r--r--src/2geom/Makefile_insert1
-rw-r--r--src/2geom/affine.cpp14
-rw-r--r--src/2geom/affine.h15
-rw-r--r--src/2geom/angle.h21
-rw-r--r--src/2geom/basic-intersection.h2
-rw-r--r--src/2geom/bezier-curve.cpp85
-rw-r--r--src/2geom/bezier-curve.h117
-rw-r--r--src/2geom/bezier-to-sbasis.h6
-rw-r--r--src/2geom/bezier-utils.cpp11
-rw-r--r--src/2geom/bezier-utils.h18
-rw-r--r--src/2geom/bezier.h27
-rw-r--r--src/2geom/choose.h21
-rw-r--r--src/2geom/circle.h21
-rw-r--r--src/2geom/circulator.h9
-rw-r--r--src/2geom/concepts.h20
-rw-r--r--src/2geom/conic_section_clipper_impl.cpp23
-rw-r--r--src/2geom/conicsec.cpp5
-rw-r--r--src/2geom/conjugate_gradient.h6
-rw-r--r--src/2geom/convex-cover.h14
-rw-r--r--src/2geom/coord.h39
-rw-r--r--src/2geom/crossing.h10
-rw-r--r--src/2geom/curve.cpp5
-rw-r--r--src/2geom/curves.h7
-rw-r--r--src/2geom/d2-sbasis.h17
-rw-r--r--src/2geom/d2.h8
-rw-r--r--src/2geom/forward.h19
-rw-r--r--src/2geom/generic-interval.h342
-rw-r--r--src/2geom/generic-rect.h390
-rw-r--r--src/2geom/hvlinesegment.h30
-rw-r--r--src/2geom/int-interval.h63
-rw-r--r--src/2geom/int-point.h157
-rw-r--r--src/2geom/int-rect.h76
-rw-r--r--src/2geom/interval.h280
-rw-r--r--src/2geom/isnan.h116
-rw-r--r--src/2geom/line.h31
-rw-r--r--src/2geom/linear.h2
-rw-r--r--src/2geom/math-utils.h49
-rw-r--r--src/2geom/ord.h4
-rw-r--r--src/2geom/path-intersection.h4
-rw-r--r--src/2geom/path.h33
-rw-r--r--src/2geom/pathvector.h13
-rw-r--r--src/2geom/piecewise.h8
-rw-r--r--src/2geom/point-l.h86
-rw-r--r--src/2geom/point.cpp48
-rw-r--r--src/2geom/point.h94
-rw-r--r--src/2geom/poly.h5
-rw-r--r--src/2geom/quadtree.h4
-rw-r--r--src/2geom/ray.h241
-rw-r--r--src/2geom/rect.cpp98
-rw-r--r--src/2geom/rect.h315
-rw-r--r--src/2geom/region.h4
-rw-r--r--src/2geom/sbasis-2d.h4
-rw-r--r--src/2geom/sbasis-curve.h45
-rw-r--r--src/2geom/sbasis-to-bezier.h4
-rw-r--r--src/2geom/sbasis.cpp2
-rw-r--r--src/2geom/sbasis.h2
-rw-r--r--src/2geom/sturm.h70
-rw-r--r--src/2geom/svg-elliptical-arc.h14
-rw-r--r--src/2geom/sweep.h4
-rw-r--r--src/2geom/toposweep.cpp663
-rw-r--r--src/2geom/toposweep.h222
-rw-r--r--src/2geom/transforms.cpp4
-rw-r--r--src/2geom/transforms.h15
-rw-r--r--src/2geom/utils.h12
-rw-r--r--src/axis-manip.h2
-rw-r--r--src/box3d-context.cpp22
-rw-r--r--src/desktop-events.cpp18
-rw-r--r--src/desktop.cpp1
-rw-r--r--src/dialogs/clonetiler.cpp1
-rw-r--r--src/display/canvas-arena.cpp154
-rw-r--r--src/display/canvas-arena.h4
-rw-r--r--src/display/canvas-axonomgrid.cpp25
-rw-r--r--src/display/canvas-grid.cpp12
-rw-r--r--src/display/guideline.cpp12
-rw-r--r--src/display/nr-arena-glyphs.cpp45
-rw-r--r--src/display/nr-arena-group.cpp12
-rw-r--r--src/display/nr-arena-image.cpp2
-rw-r--r--src/display/nr-arena-item.cpp274
-rw-r--r--src/display/nr-arena-item.h2
-rw-r--r--src/display/nr-arena-shape.cpp45
-rw-r--r--src/display/nr-arena-shape.h1
-rw-r--r--src/display/nr-arena.cpp1
-rw-r--r--src/display/nr-filter-composite.cpp1
-rw-r--r--src/display/nr-filter-displacement-map.cpp189
-rw-r--r--src/display/nr-filter-gaussian.cpp2
-rw-r--r--src/display/nr-filter-slot.cpp2
-rw-r--r--src/display/nr-filter-turbulence.cpp1
-rw-r--r--src/display/nr-filter-turbulence.h1
-rw-r--r--src/display/nr-filter-units.cpp17
-rw-r--r--src/display/nr-filter-units.h2
-rw-r--r--src/display/nr-filter.cpp10
-rw-r--r--src/display/sp-canvas-item.h4
-rw-r--r--src/display/sp-canvas.cpp67
-rw-r--r--src/display/sp-canvas.h7
-rw-r--r--src/document.cpp3
-rw-r--r--src/draw-context.h2
-rw-r--r--src/dropper-context.cpp9
-rw-r--r--src/dyna-draw-context.cpp2
-rw-r--r--src/eraser-context.cpp2
-rw-r--r--src/extension/implementation/implementation.h2
-rw-r--r--src/gradient-chemistry.cpp4
-rw-r--r--src/gradient-context.cpp6
-rw-r--r--src/graphlayout.cpp1
-rw-r--r--src/helper/geom.cpp10
-rw-r--r--src/helper/geom.h4
-rw-r--r--src/helper/pixbuf-ops.cpp1
-rw-r--r--src/helper/png-write.cpp1
-rw-r--r--src/helper/recthull.h2
-rw-r--r--src/libcola/cola.cpp2
-rw-r--r--src/libcola/gradient_projection.cpp2
-rw-r--r--src/libnr/Makefile_insert13
-rw-r--r--src/libnr/in-svg-plane.h5
-rw-r--r--src/libnr/libnr.def89
-rw-r--r--src/libnr/nr-convert2geom.h34
-rw-r--r--src/libnr/nr-coord.h29
-rw-r--r--src/libnr/nr-dim2.h22
-rw-r--r--src/libnr/nr-forward.h10
-rw-r--r--src/libnr/nr-i-coord.h25
-rw-r--r--src/libnr/nr-point-fns-test.h139
-rw-r--r--src/libnr/nr-point-fns.cpp91
-rw-r--r--src/libnr/nr-point-fns.h95
-rw-r--r--src/libnr/nr-point-l.h103
-rw-r--r--src/libnr/nr-point-ops.h88
-rw-r--r--src/libnr/nr-point.h155
-rw-r--r--src/libnr/nr-rect-l.cpp49
-rw-r--r--src/libnr/nr-rect-l.h131
-rw-r--r--src/libnr/nr-rect-ops.h51
-rw-r--r--src/libnr/nr-rect.cpp198
-rw-r--r--src/libnr/nr-rect.h243
-rw-r--r--src/libnr/nr-render.h25
-rw-r--r--src/libnr/nr-types-test.h142
-rw-r--r--src/libnr/nr-types.cpp68
-rw-r--r--src/libnr/nr-types.h39
-rw-r--r--src/libnr/nr-values.cpp12
-rw-r--r--src/libnr/nr-values.h5
-rw-r--r--src/libnr/nr_config.h.mingw12
-rw-r--r--src/libnr/nr_config.h.win3214
-rw-r--r--src/libvpsc/generate-constraints.cpp2
-rw-r--r--src/livarot/Path.h3
-rw-r--r--src/livarot/PathSimplify.cpp1
-rw-r--r--src/livarot/Shape.cpp6
-rw-r--r--src/livarot/Shape.h2
-rw-r--r--src/livarot/path-description.h2
-rw-r--r--src/livarot/sweep-event.h2
-rw-r--r--src/livarot/sweep-tree.h2
-rw-r--r--src/live_effects/lpe-spiro.cpp1
-rw-r--r--src/marker.cpp1
-rw-r--r--src/object-edit.cpp6
-rw-r--r--src/pen-context.cpp3
-rw-r--r--src/pencil-context.cpp12
-rw-r--r--src/rect-context.cpp4
-rw-r--r--src/rect-context.h2
-rw-r--r--src/removeoverlap.cpp3
-rw-r--r--src/selection-chemistry.cpp2
-rw-r--r--src/selection.cpp4
-rw-r--r--src/snap.cpp3
-rw-r--r--src/sp-clippath.cpp11
-rw-r--r--src/sp-conn-end-pair.h1
-rw-r--r--src/sp-flowtext.cpp5
-rw-r--r--src/sp-image.cpp3
-rw-r--r--src/sp-item.cpp4
-rw-r--r--src/sp-mask.cpp3
-rw-r--r--src/sp-namedview.cpp4
-rw-r--r--src/sp-offset.cpp2
-rw-r--r--src/sp-root.cpp1
-rw-r--r--src/sp-text.h1
-rw-r--r--src/spiral-context.cpp8
-rw-r--r--src/spiral-context.h2
-rw-r--r--src/spray-context.cpp1
-rw-r--r--src/spray-context.h2
-rw-r--r--src/star-context.cpp6
-rw-r--r--src/star-context.h2
-rw-r--r--src/style.cpp31
-rw-r--r--src/style.h4
-rw-r--r--src/svg-view.cpp1
-rw-r--r--src/tweak-context.cpp1
-rw-r--r--src/tweak-context.h2
-rw-r--r--src/ui/cache/svg_preview_cache.cpp1
-rw-r--r--src/ui/dialog/align-and-distribute.cpp6
-rw-r--r--src/ui/dialog/align-and-distribute.h1
-rw-r--r--src/ui/dialog/tile.cpp1
-rw-r--r--src/ui/dialog/transformation.cpp1
-rw-r--r--src/ui/view/edit-widget-interface.h2
-rw-r--r--src/ui/view/view.cpp2
-rw-r--r--src/ui/widget/page-sizer.cpp1
-rw-r--r--src/ui/widget/rotateable.cpp7
-rw-r--r--src/ui/widget/ruler.h2
-rw-r--r--src/unclump.cpp1
-rw-r--r--src/widgets/dash-selector.cpp4
-rw-r--r--src/widgets/desktop-widget.cpp25
-rw-r--r--src/widgets/desktop-widget.h2
-rw-r--r--src/widgets/icon.cpp1
-rw-r--r--src/widgets/toolbox.cpp8
193 files changed, 3506 insertions, 3686 deletions
diff --git a/src/2geom/Makefile_insert b/src/2geom/Makefile_insert
index 4f7c3b6ef..08bcbff45 100644
--- a/src/2geom/Makefile_insert
+++ b/src/2geom/Makefile_insert
@@ -77,6 +77,7 @@
2geom/quadtree.cpp \
2geom/quadtree.h \
2geom/ray.h \
+ 2geom/rect.cpp \
2geom/rect.h \
2geom/region.cpp \
2geom/region.h \
diff --git a/src/2geom/affine.cpp b/src/2geom/affine.cpp
index 925f43820..2a1f18d77 100644
--- a/src/2geom/affine.cpp
+++ b/src/2geom/affine.cpp
@@ -1,9 +1,3 @@
-#define __Geom_MATRIX_C__
-
-/** \file
- * Various matrix routines. Currently includes some Geom::Rotate etc. routines too.
- */
-
/*
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
@@ -387,10 +381,10 @@ Coord Affine::descrim2() const {
}
/** @brief Calculate the descriminant.
- * If the matrix doesn't contain a non-uniform scaling or shearing component, this value says
- * how will the length any line segment change after applying this transformation
- * to arbitrary objects on a plane (the new length will be
- * @code line_seg.length() * m.descrim()) @endcode.
+ * If the matrix doesn't contain a shearing or non-uniform scaling component, this value says
+ * how will the length of any line segment change after applying this transformation
+ * to arbitrary objects on a plane. The new length will be
+ * @code line_seg.length() * m.descrim()) @endcode
* @return \f$\sqrt{|\det A|}\f$. */
Coord Affine::descrim() const {
return sqrt(descrim2());
diff --git a/src/2geom/affine.h b/src/2geom/affine.h
index 277d8b4ee..b07fba0f7 100644
--- a/src/2geom/affine.h
+++ b/src/2geom/affine.h
@@ -1,7 +1,8 @@
-/** \file
- * \brief 3x3 affine transformation matrix.
+/**
+ * \file
+ * \brief 3x3 affine transformation matrix.
*//*
- * Main authors:
+ * Authors:
* Lauris Kaplinski <lauris@kaplinski.com> (Original NRAffine definition and related macros)
* Nathan Hurst <njh@mail.csse.monash.edu.au> (Geom::Affine class version of the above)
* Michael G. Sloan <mgsloan@gmail.com> (reorganization and additions)
@@ -10,8 +11,8 @@
* This code is in public domain.
*/
-#ifndef SEEN_LIB2GEOM_MATRIX_H
-#define SEEN_LIB2GEOM_MATRIX_H
+#ifndef SEEN_LIB2GEOM_AFFINE_H
+#define SEEN_LIB2GEOM_AFFINE_H
#include <boost/operators.hpp>
#include <2geom/forward.h>
@@ -236,9 +237,9 @@ inline Affine Affine::identity() {
return ret; // allow NRVO
}
-} /* namespace Geom */
+} // end namespace Geom
-#endif /* !__Geom_MATRIX_H__ */
+#endif // LIB2GEOM_SEEN_AFFINE_H
/*
Local Variables:
diff --git a/src/2geom/angle.h b/src/2geom/angle.h
index 42e3531f3..bdf546989 100644
--- a/src/2geom/angle.h
+++ b/src/2geom/angle.h
@@ -107,11 +107,18 @@ public:
if (ret < 0) ret += 360;
return ret;
}
-
+ /** @brief Create an angle from its measure in radians. */
+ static Angle from_radians(Coord d) {
+ Angle a(d);
+ return a;
+ }
+ /** @brief Create an angle from its measure in degrees. */
static Angle from_degrees(Coord d) {
Angle a(d * M_PI / 180);
return a;
}
+ /** @brief Create an angle from its measure in degrees in clock convention.
+ * @see Angle::degreesClock() */
static Angle from_degrees_clock(Coord d) {
// first make sure d is in [0, 360)
d = std::fmod(d, 360.0);
@@ -208,9 +215,12 @@ protected:
bool _sweep;
};
-inline double deg_to_rad(double deg) { return deg*M_PI/180.0;}
-
-inline double rad_to_deg(double rad) { return rad*180.0/M_PI;}
+/** @brief Given an angle in degrees, return radians
+ * @relates Angle */
+inline Coord deg_to_rad(Coord deg) { return deg*M_PI/180.0;}
+/** @brief Given an angle in radians, return degrees
+ * @relates Angle */
+inline Coord rad_to_deg(Coord rad) { return rad*180.0/M_PI;}
/*
* start_angle and angle must belong to [0, 2PI[
@@ -294,8 +304,7 @@ bool arc_contains (double a, double sa, double ia, double ea)
} // end namespace Geom
-#endif
-
+#endif // LIB2GEOM_SEEN_ANGLE_H
/*
Local Variables:
diff --git a/src/2geom/basic-intersection.h b/src/2geom/basic-intersection.h
index b07052449..5a813ae99 100644
--- a/src/2geom/basic-intersection.h
+++ b/src/2geom/basic-intersection.h
@@ -1,6 +1,6 @@
/**
* \file
- * \brief \todo brief description
+ * \brief Basic intersection routines
*
* Authors:
* ? <?@?.?>
diff --git a/src/2geom/bezier-curve.cpp b/src/2geom/bezier-curve.cpp
index bde0e3ef1..46aff8b49 100644
--- a/src/2geom/bezier-curve.cpp
+++ b/src/2geom/bezier-curve.cpp
@@ -1,8 +1,5 @@
-/**
- * \file
- * \brief Bezier curve
+/* Bezier curve implementation
*
- *//*
* Authors:
* MenTaLguY <mental@rydia.net>
* Marco Cecchetti <mrcekets at gmail.com>
@@ -41,7 +38,7 @@ namespace Geom
/**
* @class BezierCurve
- * @brief Two-dimensional Bezier curve of arbitrary order. (this is an abstract class)
+ * @brief Two-dimensional Bezier curve of arbitrary order.
*
* Bezier curves are an expansion of the concept of linear interpolation to n points.
* Linear segments in 2Geom are in fact Bezier curves of order 1.
@@ -82,28 +79,40 @@ namespace Geom
* have an intutive geometric interpretation. Because of this, they are frequently used
* in vector graphics editors.
*
- * Every bezier curve is contained in its control polygon (the convex polygon composed
+ * Every Bezier curve is contained in its control polygon (the convex polygon composed
* of its control points). This fact is useful for sweepline algorithms and intersection.
*
- * Bezier curves of order 1, 2 and 3 are common enough to have their own more specific subclasses:
- * LineSegment, QuadraticBezier, and CubicBezier.
- * Note that you cannot create a generic BezierCurve, you can only create a BezierCurve of a
- * specific order, by creating a BezierCurveN.
+ * @par Implementation notes
+ * The order of a Bezier curve is immuable once it has been created. Normally, you should
+ * know the order at compile time and use the BezierCurveN template. If you need to determine
+ * the order at runtime, use the BezierCurve::create() function. It will create a BezierCurveN
+ * for orders 1, 2 and 3 (up to cubic Beziers), so you can later <tt>dynamic_cast</tt>
+ * to those types, and for higher orders it will create an instance of BezierCurve.
*
* @relates BezierCurveN
* @ingroup Curves
*/
- /**
+/**
* @class BezierCurveN
+ * @brief Bezier curve with compile-time specified order.
+ *
* @tparam degree unsigned value indicating the order of the bezier curve
- * @brief Two-dimensional Bezier curve of specific order.
*
* @relates BezierCurve
* @ingroup Curves
*/
-
+
+BezierCurve::BezierCurve(std::vector<Point> const &pts)
+{
+ inner = D2<Bezier>(Bezier::Order(pts.size()-1), Bezier::Order(pts.size()-1));
+ for (unsigned d = 0; d < 2; ++d) {
+ for(unsigned i = 0; i <= pts.size(); i++)
+ inner[d][i] = pts[i][d];
+ }
+}
+
Coord BezierCurve::length(Coord tolerance) const
{
switch (order())
@@ -127,6 +136,48 @@ Coord BezierCurve::length(Coord tolerance) const
}
}
+BezierCurve *BezierCurve::create(std::vector<Point> const &pts)
+{
+ switch (pts.size()) {
+ case 0:
+ case 1:
+ THROW_LOGICALERROR("BezierCurve::create: too few points in vector");
+ return NULL;
+ case 2:
+ return new LineSegment(pts[0], pts[1]);
+ case 3:
+ return new QuadraticBezier(pts[0], pts[1], pts[2]);
+ case 4:
+ return new CubicBezier(pts[0], pts[1], pts[2], pts[3]);
+ default:
+ return new BezierCurve(pts);
+ }
+}
+
+// optimized specializations for LineSegment
+
+template <>
+Curve *BezierCurveN<1>::derivative() const {
+ double dx = inner[X][1] - inner[X][0], dy = inner[Y][1] - inner[Y][0];
+ return new BezierCurveN<1>(Point(dx,dy),Point(dx,dy));
+}
+
+template<>
+Coord BezierCurveN<1>::nearestPoint(Point const& p, Coord from, Coord to) const
+{
+ if ( from > to ) std::swap(from, to);
+ Point ip = pointAt(from);
+ Point fp = pointAt(to);
+ Point v = fp - ip;
+ Coord l2v = L2sq(v);
+ if (l2v == 0) return 0;
+ Coord t = dot( p - ip, v ) / l2v;
+ if ( t <= 0 ) return from;
+ else if ( t >= 1 ) return to;
+ else return from + t*(to-from);
+}
+
+
static Coord bezier_length_internal(std::vector<Point> &v1, Coord tolerance)
{
/* The Bezier length algorithm used in 2Geom utilizes a simple fact:
@@ -178,7 +229,7 @@ static Coord bezier_length_internal(std::vector<Point> &v1, Coord tolerance)
* After loop with i==2
* # # 2 3 4
* # 1 ? ?
- * 0 ? ? -> wirte 0 to v2[2]
+ * 0 ? ? -> write 0 to v2[2]
* ? ?
* ?
*
@@ -204,7 +255,7 @@ static Coord bezier_length_internal(std::vector<Point> &v1, Coord tolerance)
}
/** @brief Compute the length of a bezier curve given by a vector of its control points
- * @relates BezierCurve */
+ * @relatesalso BezierCurve */
Coord bezier_length(std::vector<Point> const &points, Coord tolerance)
{
if (points.size() < 2) return 0.0;
@@ -213,7 +264,7 @@ Coord bezier_length(std::vector<Point> const &points, Coord tolerance)
}
/** @brief Compute the length of a quadratic bezier curve given by its control points
- * @relates QuadraticBezier */
+ * @relatesalso QuadraticBezier */
Coord bezier_length(Point a0, Point a1, Point a2, Coord tolerance)
{
Coord lower = distance(a0, a2);
@@ -231,7 +282,7 @@ Coord bezier_length(Point a0, Point a1, Point a2, Coord tolerance)
}
/** @brief Compute the length of a cubic bezier curve given by its control points
- * @relates CubicBezier */
+ * @relatesalso CubicBezier */
Coord bezier_length(Point a0, Point a1, Point a2, Point a3, Coord tolerance)
{
Coord lower = distance(a0, a3);
diff --git a/src/2geom/bezier-curve.h b/src/2geom/bezier-curve.h
index 40da6f366..d13ff8321 100644
--- a/src/2geom/bezier-curve.h
+++ b/src/2geom/bezier-curve.h
@@ -1,14 +1,13 @@
/**
* \file
* \brief Bezier curve
- *
*//*
* Authors:
* MenTaLguY <mental@rydia.net>
* Marco Cecchetti <mrcekets at gmail.com>
* Krzysztof KosiƄski <tweenk.pl@gmail.com>
*
- * Copyright 2007-2009 Authors
+ * Copyright 2007-2011 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -47,10 +46,13 @@ namespace Geom
class BezierCurve : public Curve {
protected:
D2<Bezier> inner;
+ BezierCurve() {}
+ BezierCurve(BezierCurve const &b) : inner(b.inner) {}
+ BezierCurve(D2<Bezier> const &b) : inner(b) {}
+ BezierCurve(Bezier const &x, Bezier const &y) : inner(x, y) {}
+ BezierCurve(std::vector<Point> const &pts);
public:
- /// No constructors allowed!
-
/// @name Access and modify control points
/// @{
/** @brief Get the order of the Bezier curve.
@@ -66,8 +68,10 @@ public:
inner[X].setPoint(ix, v[X]);
inner[Y].setPoint(ix, v[Y]);
}
- /** @brief Set new control points for this curve.
- * @param ps Vector which must contain order() + 1 points. Note that the caller is responsible for checking the size of this vector. */
+ /** @brief Set new control points.
+ * @param ps Vector which must contain order() + 1 points.
+ * Note that the caller is responsible for checking the size of this vector.
+ * @throws LogicalError Thrown when the size of the vector does not match the order. */
virtual void setPoints(std::vector<Point> const &ps) {
// must be virtual, because HLineSegment will need to redefine it
if (ps.size() != order() + 1)
@@ -76,12 +80,18 @@ public:
setPoint(i, ps[i]);
}
}
- /** Access control points of the curve.
- * @param ix The (zero-based) index of the control point. Note that the caller is responsible for checking that this value is <= order().
+ /** @brief Access control points of the curve.
+ * @param ix The (zero-based) index of the control point. Note that the caller is responsible for checking that this value is <= order().
* @return The control point. No-reference return, use setPoint() to modify control points. */
Point const operator[](unsigned ix) const { return Point(inner[X][ix], inner[Y][ix]); }
/// @}
+ /// @name Construct a Bezier curve with runtime-determined order.
+ /// @{
+ /** @brief Construct a curve from a vector of control points. */
+ static BezierCurve *create(std::vector<Point> const &pts);
+ /// @}
+
// implementation of virtual methods goes here
#ifndef DOXYGEN_SHOULD_SKIP_THIS
virtual Point initialPoint() const { return inner.at0(); }
@@ -100,6 +110,27 @@ public:
bounds_local(Geom::derivative(inner[Y]), i));
return OptRect();
}
+ virtual Curve *duplicate() const {
+ return new BezierCurve(*this);
+ }
+ virtual Curve *portion(Coord f, Coord t) const {
+ return new BezierCurve(Geom::portion(inner, f, t));
+ }
+ virtual Curve *reverse() const {
+ return new BezierCurve(Geom::reverse(inner));
+ }
+ virtual Curve *transformed(Affine const &m) const {
+ BezierCurve *ret = new BezierCurve();
+ std::vector<Point> ps = points();
+ for (unsigned i = 0; i <= order(); i++) {
+ ps[i] = ps[i] * m;
+ }
+ ret->setPoints(ps);
+ return ret;
+ }
+ virtual Curve *derivative() const {
+ return new BezierCurve(Geom::derivative(inner[X]), Geom::derivative(inner[Y]));
+ }
virtual int degreesOfFreedom() const {
return 2 * (order() + 1);
}
@@ -121,7 +152,7 @@ public:
template <unsigned required_degree>
static void assert_degree(BezierCurveN<required_degree> const *) {}
- /// @name Construct the curve
+ /// @name Construct Bezier curves
/// @{
/** @brief Construct a Bezier curve of the specified order with all points zero. */
BezierCurveN() {
@@ -175,7 +206,19 @@ public:
/// @}
+ /** @brief Divide a Bezier curve into two curves
+ * @param t Time value
+ * @return Pair of Bezier curves \f$(\mathbf{D}, \mathbf{E})\f$ such that
+ * \f$\mathbf{D}[ [0,1] ] = \mathbf{C}[ [0,t] ]\f$ and
+ * \f$\mathbf{E}[ [0,1] ] = \mathbf{C}[ [t,1] ]\f$ */
+ std::pair<BezierCurveN, BezierCurveN> subdivide(Coord t) const {
+ std::pair<Bezier, Bezier> sx = inner[X].subdivide(t), sy = inner[Y].subdivide(t);
+ return std::make_pair(
+ BezierCurveN(sx.first, sy.first),
+ BezierCurveN(sx.second, sy.second));
+ }
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
virtual Curve *duplicate() const {
return new BezierCurveN(*this);
}
@@ -207,31 +250,29 @@ public:
}
}
virtual Curve *derivative() const;
-
- /** @brief Divide a Bezier curve into two curves
- * @param t Time value
- * @return Pair of Bezier curves \f$(\mathbf{D}, \mathbf{E})\f$ such that
- * \f$\mathbf{D}[ [0,1] ] = \mathbf{C}[ [0,t] ]\f$ and
- * \f$\mathbf{E}[ [0,1] ] = \mathbf{C}[ [t,1] ]\f$ */
- std::pair<BezierCurveN, BezierCurveN> subdivide(Coord t) const {
- std::pair<Bezier, Bezier> sx = inner[X].subdivide(t), sy = inner[Y].subdivide(t);
- return std::make_pair(
- BezierCurveN(sx.first, sy.first),
- BezierCurveN(sx.second, sy.second));
- }
-
- double nearestPoint( Point const& p, double from = 0, double to = 1 ) const {
+
+ // the method below is defined so that LineSegment can specialize it
+ virtual Coord nearestPoint(Point const& p, Coord from = 0, Coord to = 1) const {
return Curve::nearestPoint(p, from, to);
}
-
+#endif
};
// BezierCurveN<0> is meaningless; specialize it out
-template<> class BezierCurveN<0> : public BezierCurveN<1> { public: BezierCurveN();};
+template<> class BezierCurveN<0> : public BezierCurveN<1> { private: BezierCurveN();};
-// provide convenient names for common degree bezier curves
+/** @brief Line segment.
+ * Line segments are Bezier curves of order 1. They have only two control points,
+ * the starting point and the ending point.
+ * @ingroup Curves */
typedef BezierCurveN<1> LineSegment;
+
+/** @brief Quadratic (order 2) Bezier curve.
+ * @ingroup Curves */
typedef BezierCurveN<2> QuadraticBezier;
+
+/** @brief Cubic (order 3) Bezier curve.
+ * @ingroup Curves */
typedef BezierCurveN<3> CubicBezier;
template <unsigned degree>
@@ -239,28 +280,10 @@ inline
Curve *BezierCurveN<degree>::derivative() const {
return new BezierCurveN<degree-1>(Geom::derivative(inner[X]), Geom::derivative(inner[Y]));
}
-template <>
-inline
-Curve *BezierCurveN<1>::derivative() const {
- double dx = inner[X][1] - inner[X][0], dy = inner[Y][1] - inner[Y][0];
- return new BezierCurveN<1>(Point(dx,dy),Point(dx,dy));
-}
-template<>
-inline
-double LineSegment::nearestPoint(Point const& p, double from, double to) const
-{
- if ( from > to ) std::swap(from, to);
- Point ip = pointAt(from);
- Point fp = pointAt(to);
- Point v = fp - ip;
- Coord l2v = L2sq(v);
- if (l2v == 0) return 0;
- Coord t = dot( p - ip, v ) / l2v;
- if ( t <= 0 ) return from;
- else if ( t >= 1 ) return to;
- else return from + t*(to-from);
-}
+// optimized specializations for LineSegment
+template <> Curve *BezierCurveN<1>::derivative() const;
+template <> Coord BezierCurveN<1>::nearestPoint(Point const &, Coord, Coord) const;
inline Point middle_point(LineSegment const& _segment) {
return ( _segment.initialPoint() + _segment.finalPoint() ) / 2;
diff --git a/src/2geom/bezier-to-sbasis.h b/src/2geom/bezier-to-sbasis.h
index ba98a8a34..8cd4bf444 100644
--- a/src/2geom/bezier-to-sbasis.h
+++ b/src/2geom/bezier-to-sbasis.h
@@ -1,7 +1,7 @@
/**
- * \file bezier-to-sbasis.h
- * \brief \todo brief description
- *
+ * \file
+ * \brief Conversion between Bezier control points and SBasis curves
+ *//*
* Copyright 2006 Nathan Hurst <njh@mail.csse.monash.edu.au>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/2geom/bezier-utils.cpp b/src/2geom/bezier-utils.cpp
index eb317940f..af07db707 100644
--- a/src/2geom/bezier-utils.cpp
+++ b/src/2geom/bezier-utils.cpp
@@ -1,9 +1,5 @@
-#define __SP_BEZIER_UTILS_C__
-
-/** \file
- * Bezier interpolation for inkscape drawing code.
- */
-/*
+/* Bezier interpolation for inkscape drawing code.
+ *
* Original code published in:
* An Algorithm for Automatically Fitting Digitized Curves
* by Philip J. Schneider
@@ -52,8 +48,7 @@
#endif
#include <2geom/bezier-utils.h>
-
-#include <2geom/isnan.h>
+#include <2geom/math-utils.h>
#include <assert.h>
namespace Geom {
diff --git a/src/2geom/bezier-utils.h b/src/2geom/bezier-utils.h
index 9689db82d..3e56e6e25 100644
--- a/src/2geom/bezier-utils.h
+++ b/src/2geom/bezier-utils.h
@@ -1,10 +1,7 @@
-#ifndef SEEN_GEOM_BEZIER_UTILS_H
-#define SEEN_GEOM_BEZIER_UTILS_H
-
/**
* \file
- * \brief \todo brief description
- *
+ * \brief Bezier fitting algorithms
+ *//*
* An Algorithm for Automatically Fitting Digitized Curves
* by Philip J. Schneider
* from "Graphics Gems", Academic Press, 1990
@@ -41,11 +38,13 @@
*
*/
+#ifndef LIB2GEOM_SEEN_BEZIER_UTILS_H
+#define LIB2GEOM_SEEN_BEZIER_UTILS_H
+
#include <2geom/point.h>
-namespace Geom{
+namespace Geom {
-/* Bezier approximation utils */
Point bezier_pt(unsigned degree, Point const V[], double t);
int bezier_fit_cubic(Point bezier[], Point const data[], int len, double error);
@@ -84,8 +83,9 @@ cubic_bezier_poly_coeff(iterator b, Point *pc) {
}
}
-}
-#endif /* !SEEN_GEOM_BEZIER_UTILS_H */
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_BEZIER_UTILS_H
/*
Local Variables:
diff --git a/src/2geom/bezier.h b/src/2geom/bezier.h
index a7d75da45..48a1dc750 100644
--- a/src/2geom/bezier.h
+++ b/src/2geom/bezier.h
@@ -1,10 +1,13 @@
/**
- * \file bezier.h
- * \brief \todo brief description
+ * @file
+ * @brief Bezier polynomial
+ *//*
+ * Authors:
+ * MenTaLguY <mental@rydia.net>
+ * Michael Sloan <mgsloan@gmail.com>
+ * Nathan Hurst <njh@njhurst.com>
*
- * Copyright 2007 MenTaLguY <mental@rydia.net>
- * Copyright 2007 Michael Sloan <mgsloan@gmail.com>
- * Copyright 2007 Nathan Hurst <njh@njhurst.com>
+ * Copyright 2007 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -31,15 +34,15 @@
*
*/
-#ifndef SEEN_BEZIER_H
-#define SEEN_BEZIER_H
+#ifndef LIB2GEOM_SEEN_BEZIER_H
+#define LIB2GEOM_SEEN_BEZIER_H
-#include <2geom/coord.h>
#include <valarray>
-#include <2geom/isnan.h>
+#include <boost/optional.hpp>
+#include <2geom/coord.h>
+#include <2geom/math-utils.h>
#include <2geom/d2.h>
#include <2geom/solver.h>
-#include <boost/optional/optional.hpp>
namespace Geom {
@@ -280,7 +283,7 @@ public:
}
std::vector<double> roots(Interval const ivl) const {
std::vector<double> solutions;
- find_bernstein_roots(&const_cast<std::valarray<Coord>&>(c_)[0], order(), solutions, 0, ivl[0], ivl[1]);
+ find_bernstein_roots(&const_cast<std::valarray<Coord>&>(c_)[0], order(), solutions, 0, ivl.min(), ivl.max());
return solutions;
}
};
@@ -407,7 +410,7 @@ inline std::ostream &operator<< (std::ostream &out_file, const Bezier & b) {
}
}
-#endif //SEEN_BEZIER_H
+#endif // LIB2GEOM_SEEN_BEZIER_H
/*
Local Variables:
diff --git a/src/2geom/choose.h b/src/2geom/choose.h
index 3fecf1ba2..64ce76f39 100644
--- a/src/2geom/choose.h
+++ b/src/2geom/choose.h
@@ -1,7 +1,7 @@
/**
- * \file choose.h
- * \brief \todo brief description
- *
+ * \file
+ * \brief Calculation of binomial cefficients
+ *//*
* Copyright 2006 Nathan Hurst <njh@mail.csse.monash.edu.au>
*
* This library is free software; you can redistribute it and/or
@@ -29,10 +29,13 @@
*
*/
-#ifndef _CHOOSE_H
-#define _CHOOSE_H
+#ifndef LIB2GEOM_SEEN_CHOOSE_H
+#define LIB2GEOM_SEEN_CHOOSE_H
+
#include <vector>
+namespace Geom {
+
// XXX: Can we keep only the left terms easily?
// this would more than halve the array
// row index becomes n2 = n/2, row2 = n2*(n2+1)/2, row = row2*2+(n&1)?n2:0
@@ -121,13 +124,9 @@ class BinomialCoefficient
container_type coefficients;
};
+} // end namespace Geom
-
-
-
-
-
-#endif
+#endif // LIB2GEOM_SEEN_CHOOSE_H
/*
Local Variables:
diff --git a/src/2geom/circle.h b/src/2geom/circle.h
index ec58e163a..67a638437 100644
--- a/src/2geom/circle.h
+++ b/src/2geom/circle.h
@@ -1,7 +1,7 @@
/**
* \file
- * \brief Circle Curve
- *
+ * \brief Circles
+ *//*
* Authors:
* Marco Cecchetti <mrcekets at gmail.com>
*
@@ -31,18 +31,15 @@
* the specific language governing rights and limitations.
*/
+#ifndef LIB2GEOM_SEEN_CIRCLE_H
+#define LIB2GEOM_SEEN_CIRCLE_H
-#ifndef _2GEOM_CIRCLE_H_
-#define _2GEOM_CIRCLE_H_
-
-
+#include <vector>
#include <2geom/point.h>
#include <2geom/exception.h>
#include <2geom/path.h>
-#include <vector>
-namespace Geom
-{
+namespace Geom {
class EllipticalArc;
@@ -115,13 +112,9 @@ class Circle
Coord m_ray;
};
-
} // end namespace Geom
-
-
-#endif // _2GEOM_CIRCLE_H_
-
+#endif // LIB2GEOM_SEEN_CIRCLE_H
/*
Local Variables:
diff --git a/src/2geom/circulator.h b/src/2geom/circulator.h
index 1a70dc4d3..9671ce4a9 100644
--- a/src/2geom/circulator.h
+++ b/src/2geom/circulator.h
@@ -1,7 +1,7 @@
/**
- * \file circulator.h
- * \brief \todo brief description
- *
+ * @file circulator.h
+ * @brief Circular iterator adapter
+ *//*
* Copyright 2006 MenTaLguY <mental@rydia.net>
*
* This library is free software; you can redistribute it and/or
@@ -36,6 +36,9 @@
namespace Geom {
+/** @brief Circular iterator adapter
+ * This iterator adapter will loop indefinitely over a set of values
+ * from a random access container. */
template <typename Iterator>
class Circulator {
public:
diff --git a/src/2geom/concepts.h b/src/2geom/concepts.h
index a03538d42..c89c3a224 100644
--- a/src/2geom/concepts.h
+++ b/src/2geom/concepts.h
@@ -1,7 +1,7 @@
/**
* \file
- * \brief Declares various mathematical concepts, for restriction of template parameters
- *
+ * \brief Template concepts used by 2Geom
+ *//*
* Copyright 2007 Michael Sloan <mgsloan@gmail.com>
*
* This library is free software; you can redistribute it and/or
@@ -26,15 +26,15 @@
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
* OF ANY KIND, either express or implied. See the LGPL or the MPL for
* the specific language governing rights and limitations.
- *
*/
-#ifndef SEEN_CONCEPTS_H
-#define SEEN_CONCEPTS_H
+#ifndef LIB2GEOM_SEEN_CONCEPTS_H
+#define LIB2GEOM_SEEN_CONCEPTS_H
#include <2geom/sbasis.h>
#include <2geom/interval.h>
#include <2geom/point.h>
+#include <2geom/rect.h>
#include <vector>
#include <boost/concept_check.hpp>
#include <2geom/forward.h>
@@ -49,7 +49,7 @@ template <> struct ResultTraits<double> {
typedef SBasis sb_type;
};
-template <> struct ResultTraits<Point > {
+template <> struct ResultTraits<Point> {
typedef OptRect bounds_type;
typedef D2<SBasis> sb_type;
};
@@ -130,7 +130,7 @@ struct ScalableConcept {
}
};
-template <class T>
+template <typename T>
struct AddableConcept {
T i, j;
void constraints() {
@@ -139,7 +139,7 @@ struct AddableConcept {
}
};
-template <class T>
+template <typename T>
struct MultiplicableConcept {
T i, j;
void constraints() {
@@ -147,9 +147,9 @@ struct MultiplicableConcept {
}
};
-};
+} // end namespace Geom
-#endif //SEEN_CONCEPTS_H
+#endif // LIB2GEOM_SEEN_CONCEPTS_H
/*
Local Variables:
diff --git a/src/2geom/conic_section_clipper_impl.cpp b/src/2geom/conic_section_clipper_impl.cpp
index edfafb11c..33a218a8c 100644
--- a/src/2geom/conic_section_clipper_impl.cpp
+++ b/src/2geom/conic_section_clipper_impl.cpp
@@ -1,6 +1,4 @@
-/**
- * \file
- * \brief Conic section clipping with respect to a rectangle
+/* Conic section clipping with respect to a rectangle
*
* Authors:
* Marco Cecchetti <mrcekets at gmail>
@@ -31,30 +29,13 @@
* the specific language governing rights and limitations.
*/
-
-
-
#ifndef CLIP_WITH_CAIRO_SUPPORT
#include <2geom/conic_section_clipper.h>
#endif
-
-
-
namespace Geom
{
-struct lex_lesser
-{
- bool operator() (const Point & P, const Point & Q) const
- {
- if (P[X] < Q[X]) return true;
- if (P[X] == Q[X] && P[Y] < Q[Y]) return true;
- return false;
- }
-};
-
-
/*
* Find rectangle-conic crossing points. They are returned in the
* "crossing_points" parameter.
@@ -192,7 +173,7 @@ bool CLIPPER_CLASS::intersect (std::vector<Point> & crossing_points) const
cpts.size())
// remove duplicates
- std::sort (cpts.begin(), cpts.end(), lex_lesser());
+ std::sort (cpts.begin(), cpts.end(), Point::LexOrder<X>());
cpts.erase (std::unique (cpts.begin(), cpts.end()), cpts.end());
diff --git a/src/2geom/conicsec.cpp b/src/2geom/conicsec.cpp
index 2a537a1f0..a7e8e0ad8 100644
--- a/src/2geom/conicsec.cpp
+++ b/src/2geom/conicsec.cpp
@@ -1,7 +1,4 @@
-/**
- * \file
- * \brief Circle Curve
- *
+/*
* Authors:
* Nathan Hurst <njh@njhurst.com
*
diff --git a/src/2geom/conjugate_gradient.h b/src/2geom/conjugate_gradient.h
index 8ea1b83b4..a34307d4b 100644
--- a/src/2geom/conjugate_gradient.h
+++ b/src/2geom/conjugate_gradient.h
@@ -1,7 +1,7 @@
/**
- * \file
- * \brief \todo brief description
- *
+ * @file
+ * @brief Routines for solving a system of linear equations using the conjugate gradient method
+ *//*
* Copyright 2006 Nathan Hurst <njh@mail.csse.monash.edu.au>
*
* This library is free software; you can redistribute it and/or
diff --git a/src/2geom/convex-cover.h b/src/2geom/convex-cover.h
index d5e2dee44..e4b5de200 100644
--- a/src/2geom/convex-cover.h
+++ b/src/2geom/convex-cover.h
@@ -1,9 +1,6 @@
-#ifndef GEOM_CONVEX_COVER_H
-#define GEOM_CONVEX_COVER_H
-
/**
* \file
- * \brief \todo brief description
+ * \brief Dynamic convex hull structure
*
* Copyright 2006 Nathan Hurst <njh@mail.csse.monash.edu.au>
* Copyright 2006 Michael G. Sloan <mgsloan@gmail.com>
@@ -33,15 +30,18 @@
*
*/
-/** A convex cover is a sequence of convex polygons that completely cover the path. For now a
- * convex hull class is included here (the convex-hull header is wrong)
- */
+#ifndef GEOM_CONVEX_COVER_H
+#define GEOM_CONVEX_COVER_H
#include <2geom/point.h>
#include <vector>
namespace Geom{
+/* A convex cover is a sequence of convex polygons that completely cover the path. For now a
+ * convex hull class is included here (the convex-hull header is wrong)
+ */
+
/** ConvexHull
* A convexhull is a convex region - every point between two points in the convex hull is also in
* the convex hull. It is defined by a set of points travelling in a clockwise direction. We require the first point to be top most, and of the topmost, leftmost.
diff --git a/src/2geom/coord.h b/src/2geom/coord.h
index 9c42f6bfc..c7bbcdcd4 100644
--- a/src/2geom/coord.h
+++ b/src/2geom/coord.h
@@ -1,7 +1,7 @@
/**
* \file
* \brief Defines the Coord "real" type with sufficient precision for coordinates.
- *
+ *//*
* Copyright 2006 Nathan Hurst <njh@mail.csse.monash.edu.au>
*
* This library is free software; you can redistribute it and/or
@@ -29,15 +29,16 @@
*
*/
-#ifndef SEEN_Geom_COORD_H
-#define SEEN_Geom_COORD_H
+#ifndef LIB2GEOM_SEEN_COORD_H
+#define LIB2GEOM_SEEN_COORD_H
#include <cmath>
#include <limits>
+#include <2geom/forward.h>
namespace Geom {
-/** @brief Axis enum (X or Y). */
+/** @brief 2D axis enumeration (X or Y). */
enum Dim2 { X=0, Y=1 };
/**
@@ -48,6 +49,7 @@ enum Dim2 { X=0, Y=1 };
* differences of on-canvas points.
*/
typedef double Coord;
+typedef int IntCoord;
const Coord EPSILON = 1e-5; //1e-18;
@@ -57,13 +59,36 @@ inline Coord infinity() { return std::numeric_limits<Coord>::infinity(); }
inline bool are_near(Coord a, Coord b, double eps=EPSILON) { return a-b <= eps && a-b >= -eps; }
inline bool rel_error_bound(Coord a, Coord b, double eps=EPSILON) { return a <= eps*b && a >= -eps*b; }
+template <typename C>
+struct CoordTraits {};
-typedef long IntCoord;
+template<>
+struct CoordTraits<IntCoord> {
+ typedef IntPoint PointType;
+ typedef IntInterval IntervalType;
+ typedef OptIntInterval OptIntervalType;
+ typedef IntRect RectType;
+ typedef OptIntRect OptRectType;
+ inline static bool contains(IntCoord low, IntCoord high, IntCoord testlow, IntCoord testhigh) {
+ return low <= testlow && testhigh < high;
+ }
+};
-} /* namespace Geom */
+template<>
+struct CoordTraits<Coord> {
+ typedef Point PointType;
+ typedef Interval IntervalType;
+ typedef OptInterval OptIntervalType;
+ typedef Rect RectType;
+ typedef OptRect OptRectType;
+ inline static bool contains(Coord low, Coord high, Coord testlow, Coord testhigh) {
+ return low <= testlow && testhigh <= high;
+ }
+};
+} // end namespace Geom
-#endif /* !SEEN_Geom_COORD_H */
+#endif // LIB2GEOM_SEEN_COORD_H
/*
Local Variables:
diff --git a/src/2geom/crossing.h b/src/2geom/crossing.h
index 62e447450..75c75fc24 100644
--- a/src/2geom/crossing.h
+++ b/src/2geom/crossing.h
@@ -1,10 +1,10 @@
/**
- * \file
- * \brief \todo brief description
- *
+ * @file
+ * @brief Structure representing the intersection of two curves
+ *//*
* Authors:
- * Michael Sloane <?@?.?>
- * Marco <?@?.?>
+ * Michael Sloan <mgsloan@gmail.com>
+ * Marco Cecchetti <mrcekets at gmail.com>
*
* Copyright 2006-2008 authors
*
diff --git a/src/2geom/curve.cpp b/src/2geom/curve.cpp
index 49e011a8b..fe9d607d8 100644
--- a/src/2geom/curve.cpp
+++ b/src/2geom/curve.cpp
@@ -1,8 +1,5 @@
-/**
- * \file
- * \brief Abstract curve type - implementation of default methods
+/* Abstract curve type - implementation of default methods
*
- *//*
* Authors:
* MenTaLguY <mental@rydia.net>
* Marco Cecchetti <mrcekets at gmail.com>
diff --git a/src/2geom/curves.h b/src/2geom/curves.h
index 64cf3d4fb..319b1924d 100644
--- a/src/2geom/curves.h
+++ b/src/2geom/curves.h
@@ -32,9 +32,8 @@
* the specific language governing rights and limitations.
*/
-#ifndef _2GEOM_CURVES_H_
-#define _2GEOM_CURVES_H_
-
+#ifndef LIB2GEOM_SEEN_CURVES_H
+#define LIB2GEOM_SEEN_CURVES_H
#include <2geom/curve.h>
#include <2geom/sbasis-curve.h>
@@ -43,7 +42,7 @@
#include <2geom/elliptical-arc.h>
#include <2geom/svg-elliptical-arc.h>
-#endif // _2GEOM_CURVES_H_
+#endif // LIB2GEOM_SEEN_CURVES_H
/*
Local Variables:
diff --git a/src/2geom/d2-sbasis.h b/src/2geom/d2-sbasis.h
index bd6c35805..e61067e1b 100644
--- a/src/2geom/d2-sbasis.h
+++ b/src/2geom/d2-sbasis.h
@@ -1,11 +1,10 @@
/**
* \file
- * \brief Do not include this file \todo brief description
+ * \brief Do not include this file
*
* We don't actually want anyone to
- * include this, other than D2.h. If somone else tries, D2
- * won't be defined. If it is, this will already be included.
- *
+ * include this, other than D2.h.
+ *//*
* Authors:
* ? <?@?.?>
*
@@ -36,11 +35,11 @@
*
*/
-#ifdef _2GEOM_D2 /*This is intentional: we don't actually want anyone to
- include this, other than D2.h. If somone else tries, D2
- won't be defined. If it is, this will already be included. */
-#ifndef __2GEOM_SBASIS_CURVE_H
-#define __2GEOM_SBASIS_CURVE_H
+#ifdef SEEN_LIB2GEOM_D2_H /*This is intentional: we don't actually want anyone to
+ include this, other than D2.h. If somone else tries, D2
+ won't be defined. If it is, this will already be included. */
+#ifndef SEEN_LIB2GEOM_D2_SBASIS_H
+#define SEEN_LIB2GEOM_D2_SBASIS_H
#include <2geom/sbasis.h>
#include <2geom/sbasis-2d.h>
diff --git a/src/2geom/d2.h b/src/2geom/d2.h
index 3e4de430e..4a4f45a63 100644
--- a/src/2geom/d2.h
+++ b/src/2geom/d2.h
@@ -1,7 +1,7 @@
/**
* \file
* \brief Lifts one dimensional objects into 2d
- *
+ *//*
* Copyright 2007 Michael Sloan <mgsloan@gmail.com>
*
* This library is free software; you can redistribute it and/or
@@ -29,12 +29,13 @@
*
*/
-#ifndef _2GEOM_D2 //If this is change, change the guard in rect.h as well.
-#define _2GEOM_D2
+#ifndef SEEN_LIB2GEOM_D2_H
+#define SEEN_LIB2GEOM_D2_H
#include <2geom/point.h>
#include <2geom/interval.h>
#include <2geom/affine.h>
+#include <2geom/rect.h>
#include <boost/concept_check.hpp>
#include <2geom/concepts.h>
@@ -426,7 +427,6 @@ inline std::ostream &operator<< (std::ostream &out_file, const Geom::D2<T> &in_d
} //end namespace Geom
-#include <2geom/rect.h>
#include <2geom/d2-sbasis.h>
namespace Geom{
diff --git a/src/2geom/forward.h b/src/2geom/forward.h
index 399344dda..b1cad6f1f 100644
--- a/src/2geom/forward.h
+++ b/src/2geom/forward.h
@@ -41,11 +41,23 @@ namespace Geom {
// basic types
typedef double Coord;
+typedef int IntCoord;
class Point;
-class Interval;
-class OptInterval;
+class IntPoint;
class Line;
class Ray;
+template <typename> class GenericInterval;
+template <typename> class GenericOptInterval;
+class Interval;
+typedef GenericOptInterval<Coord> OptInterval;
+typedef GenericInterval<IntCoord> IntInterval;
+typedef GenericOptInterval<IntCoord> OptIntInterval;
+template <typename> class GenericRect;
+template <typename> class GenericOptRect;
+class Rect;
+typedef GenericOptRect<Coord> OptRect;
+typedef GenericRect<IntCoord> IntRect;
+typedef GenericOptRect<IntCoord> OptIntRect;
// fragments
class Linear;
@@ -90,9 +102,6 @@ class VShear;
template <typename> class D2;
template <typename> class Piecewise;
-typedef D2<Interval> Rect;
-class OptRect;
-
class Shape;
class Region;
class Hat;
diff --git a/src/2geom/generic-interval.h b/src/2geom/generic-interval.h
new file mode 100644
index 000000000..d719c16c8
--- /dev/null
+++ b/src/2geom/generic-interval.h
@@ -0,0 +1,342 @@
+/**
+ * @file
+ * @brief Closed interval of generic values
+ *//*
+ * Copyright 2011 Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_GENERIC_INTERVAL_H
+#define LIB2GEOM_SEEN_GENERIC_INTERVAL_H
+
+#include <cassert>
+#include <boost/none.hpp>
+#include <boost/optional.hpp>
+#include <boost/operators.hpp>
+
+namespace Geom {
+
+template <typename C>
+class GenericOptInterval;
+
+/**
+ * @brief A range of numbers which is never empty.
+ * @ingroup Primitives
+ */
+template <typename C>
+class GenericInterval
+ : boost::equality_comparable< GenericInterval<C>
+ , boost::additive< GenericInterval<C>
+ , boost::additive< GenericInterval<C>, C
+ , boost::orable< GenericInterval<C>
+ > > > >
+{
+ typedef GenericInterval<C> Self;
+protected:
+ C _b[2];
+public:
+ /// @name Create intervals.
+ /// @{
+ /** @brief Create an interval that contains only zero. */
+ GenericInterval() { _b[0] = 0; _b[1] = 0; }
+ /** @brief Create an interval that contains a single point. */
+ explicit GenericInterval(C u) { _b[0] = _b[1] = u; }
+ /** @brief Create an interval that contains all points between @c u and @c v. */
+ GenericInterval(C u, C v) {
+ if (u <= v) {
+ _b[0] = u; _b[1] = v;
+ } else {
+ _b[0] = v; _b[1] = u;
+ }
+ }
+
+ /** @brief Create an interval containing a range of values.
+ * The resulting interval will contain all values from the given range.
+ * The return type of iterators must be convertible to C. The given range
+ * must not be empty. For potentially empty ranges, see GenericOptInterval.
+ * @param start Beginning of the range
+ * @param end End of the range
+ * @return Interval that contains all values from [start, end). */
+ template <typename InputIterator>
+ static Self from_range(InputIterator start, InputIterator end) {
+ assert(start != end);
+ Self result(*start++);
+ for (; start != end; ++start) result.expandTo(*start);
+ return result;
+ }
+ /** @brief Create an interval from a C-style array of values it should contain. */
+ static Self from_array(C const *c, unsigned n) {
+ Self result = from_range(c, c+n);
+ return result;
+ }
+ /// @}
+
+ /// @name Inspect endpoints.
+ /// @{
+ C min() const { return _b[0]; }
+ C max() const { return _b[1]; }
+ C extent() const { return max() - min(); }
+ C middle() const { return (max() + min()) * 0.5; }
+ bool isSingular() const { return min() == max(); }
+ /// @}
+
+ /// @name Test coordinates and other intervals for inclusion.
+ /// @{
+ /** @brief Check whether the interval includes this number. */
+ bool contains(C val) const {
+ return CoordTraits<C>::contains(min(), max(), val, val);
+ }
+ /** @brief Check whether the interval includes the given interval. */
+ bool contains(Self const &val) const {
+ return CoordTraits<C>::contains(min(), max(), val.min(), val.max());
+ }
+ /** @brief Check whether the intervals have any common elements. */
+ bool intersects(Self const &val) const {
+ return contains(val.min()) || contains(val.max()) || val.contains(*this);
+ }
+ /// @}
+
+ /// @name Modify the interval.
+ /// @{
+ //TODO: NaN handleage for the next two?
+ /** @brief Set the lower boundary of the interval.
+ * When the given number is larger than the interval's largest element,
+ * it will be reduced to the single number @c val. */
+ void setMin(C val) {
+ if(val > _b[1]) {
+ _b[0] = _b[1] = val;
+ } else {
+ _b[0] = val;
+ }
+ }
+ /** @brief Set the upper boundary of the interval.
+ * When the given number is smaller than the interval's smallest element,
+ * it will be reduced to the single number @c val. */
+ void setMax(C val) {
+ if(val < _b[0]) {
+ _b[1] = _b[0] = val;
+ } else {
+ _b[1] = val;
+ }
+ }
+ /** @brief Extend the interval to include the given number. */
+ void expandTo(C val) {
+ if(val < _b[0]) _b[0] = val;
+ if(val > _b[1]) _b[1] = val; //no else, as we want to handle NaN
+ }
+ /** @brief Expand or shrink the interval in both directions by the given amount.
+ * After this method, the interval's length (extent) will be increased by
+ * <code>amount * 2</code>. Negative values can be given; they will shrink the interval.
+ * Shrinking by a value larger than half the interval's length will create a degenerate
+ * interval containing only the midpoint of the original. */
+ void expandBy(C amount) {
+ _b[0] -= amount;
+ _b[1] += amount;
+ if (_b[0] > _b[1]) {
+ C halfway = (_b[0]+_b[1])/2;
+ _b[0] = _b[1] = halfway;
+ }
+ }
+ /** @brief Union the interval with another one.
+ * The resulting interval will contain all points of both intervals.
+ * It might also contain some points which didn't belong to either - this happens
+ * when the intervals did not have any common elements. */
+ void unionWith(Self const &a) {
+ if(a._b[0] < _b[0]) _b[0] = a._b[0];
+ if(a._b[1] > _b[1]) _b[1] = a._b[1];
+ }
+ /// @}
+
+ /// @name Operators
+ /// @{
+ //IMPL: OffsetableConcept
+ //TODO: rename output_type to something else in the concept
+ typedef C output_type;
+ /** @brief Offset the interval by a specified amount */
+ Self &operator+=(C amnt) {
+ _b[0] += amnt; _b[1] += amnt;
+ return *this;
+ }
+ /** @brief Offset the interval by the negation of the specified amount */
+ Self &operator-=(C amnt) {
+ _b[0] -= amnt; _b[1] -= amnt;
+ return *this;
+ }
+
+ /** @brief Return an interval mirrored about 0 */
+ Self operator-() const { Self r(-_b[1], -_b[0]); return r; }
+ // IMPL: AddableConcept
+ /** @brief Add two intervals.
+ * Sum is defined as the set of points that can be obtained by adding any two values
+ * from both operands: \f$S = \{x \in A, y \in B: x + y\}\f$ */
+ Self &operator+=(Self const &o) {
+ _b[0] += o._b[0];
+ _b[1] += o._b[1];
+ return *this;
+ }
+ /** @brief Subtract two intervals.
+ * Difference is defined as the set of points that can be obtained by subtracting
+ * any value from the second operand from any value from the first operand:
+ * \f$S = \{x \in A, y \in B: x - y\}\f$ */
+ Self &operator-=(Self const &o) {
+ // equal to *this += -o
+ _b[0] -= o._b[1];
+ _b[1] -= o._b[0];
+ return *this;
+ }
+ /** @brief Union two intervals.
+ * Note that the intersection-and-assignment operator is not defined,
+ * because the result of an intersection can be empty, while Interval cannot. */
+ Self &operator|=(Self const &o) {
+ unionWith(o);
+ return *this;
+ }
+ /** @brief Test for interval equality. */
+ bool operator==(Self const &other) const {
+ return min() == other.min() && max() == other.max();
+ }
+ /// @}
+};
+
+/** @brief Union two intervals
+ * @relates GenericInterval */
+template <typename C>
+inline GenericInterval<C> unify(GenericInterval<C> const &a, GenericInterval<C> const &b) {
+ return a | b;
+}
+
+/**
+ * @brief A range of numbers that can be empty.
+ * @ingroup Primitives
+ */
+template <typename C>
+class GenericOptInterval
+ : public boost::optional<typename CoordTraits<C>::IntervalType>
+ , boost::orable< GenericOptInterval<C>, typename CoordTraits<C>::OptIntervalType
+ , boost::andable< GenericOptInterval<C>, typename CoordTraits<C>::OptIntervalType
+ > >
+{
+ typedef typename CoordTraits<C>::IntervalType CInterval;
+ typedef typename CoordTraits<C>::OptIntervalType OptCInterval;
+ typedef boost::optional<CInterval> Base;
+public:
+ /// @name Create optionally empty intervals of integers.
+ /// @{
+ /** @brief Create an empty interval. */
+ GenericOptInterval() : Base() {}
+ /** @brief Wrap an existing interval. */
+ GenericOptInterval(GenericInterval<C> const &a) : Base(CInterval(a)) {}
+ /** @brief Create an interval containing a single point. */
+ GenericOptInterval(C u) : Base(CInterval(u)) {}
+ /** @brief Create an interval containing a range of numbers. */
+ GenericOptInterval(C u, C v) : Base(CInterval(u,v)) {}
+
+ /** @brief Create a possibly empty interval containing a range of values.
+ * The resulting interval will contain all values from the given range.
+ * The return type of iterators must be convertible to C. The given range
+ * may be empty.
+ * @param start Beginning of the range
+ * @param end End of the range
+ * @return Interval that contains all values from [start, end), or nothing if the range
+ * is empty. */
+ template <typename InputIterator>
+ static GenericOptInterval<C> from_range(InputIterator start, InputIterator end) {
+ if (start == end) {
+ GenericOptInterval<C> ret;
+ return ret;
+ }
+ GenericOptInterval<C> ret(CInterval::from_range(start, end));
+ return ret;
+ }
+ /// @}
+
+ /** @brief Check whether this interval is empty. */
+ bool isEmpty() { return !*this; };
+
+ /** @brief Union with another interval, gracefully handling empty ones. */
+ void unionWith(GenericOptInterval<C> const &a) {
+ if (*this) { // check that we are not empty
+ (*this)->unionWith(*a);
+ } else if (a) {
+ *this = *a;
+ }
+ }
+ void intersectWith(GenericOptInterval<C> const &o) {
+ if (o && *this) {
+ if (!*this) return;
+ C u = std::max((*this)->min(), o->min());
+ C v = std::min((*this)->max(), o->max());
+ if (u <= v) {
+ *this = CInterval(u, v);
+ return;
+ }
+ }
+ (*static_cast<Base*>(this)) = boost::none;
+ }
+ GenericOptInterval<C> &operator|=(OptCInterval const &o) {
+ unionWith(o);
+ return *this;
+ }
+ GenericOptInterval<C> &operator&=(OptCInterval const &o) {
+ intersectWith(o);
+ return *this;
+ }
+};
+
+/** @brief Intersect two intervals and return a possibly empty range of numbers
+ * @relates GenericOptInterval */
+template <typename C>
+inline GenericOptInterval<C> intersect(GenericInterval<C> const &a, GenericInterval<C> const &b) {
+ return GenericOptInterval<C>(a) & GenericOptInterval<C>(b);
+}
+/** @brief Intersect two intervals and return a possibly empty range of numbers
+ * @relates GenericOptInterval */
+template <typename C>
+inline GenericOptInterval<C> operator&(GenericInterval<C> const &a, GenericInterval<C> const &b) {
+ return GenericOptInterval<C>(a) & GenericOptInterval<C>(b);
+}
+
+#ifdef _GLIBCXX_IOSTREAM
+template <typename C>
+inline std::ostream &operator<< (std::ostream &os,
+ Geom::GenericInterval<C> const &I) {
+ os << "Interval("<<I.min() << ", "<<I.max() << ")";
+ return os;
+}
+#endif
+
+} // namespace Geom
+#endif // !LIB2GEOM_SEEN_GENERIC_INTERVAL_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/2geom/generic-rect.h b/src/2geom/generic-rect.h
new file mode 100644
index 000000000..d60c4bb0f
--- /dev/null
+++ b/src/2geom/generic-rect.h
@@ -0,0 +1,390 @@
+/**
+ * \file
+ * \brief Axis-aligned rectangle
+ *//*
+ * Authors:
+ * Michael Sloan <mgsloan@gmail.com>
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ * Copyright 2007-2011 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, output to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ *
+ * Authors of original rect class:
+ * Lauris Kaplinski <lauris@kaplinski.com>
+ * Nathan Hurst <njh@mail.csse.monash.edu.au>
+ * bulia byak <buliabyak@users.sf.net>
+ * MenTaLguY <mental@rydia.net>
+ */
+
+#ifndef LIB2GEOM_SEEN_GENERIC_RECT_H
+#define LIB2GEOM_SEEN_GENERIC_RECT_H
+
+#include <boost/optional.hpp>
+
+namespace Geom {
+
+template <typename C>
+class GenericOptRect;
+
+/**
+ * @brief Axis aligned, non-empty, generic rectangle.
+ * @ingroup Primitives
+ */
+template <typename C>
+class GenericRect
+ : boost::additive< GenericRect<C>, typename CoordTraits<C>::PointType
+ , boost::equality_comparable< GenericRect<C>
+ , boost::orable< GenericRect<C>
+ , boost::orable< GenericRect<C>, typename CoordTraits<C>::OptRectType
+ > > > >
+{
+ typedef typename CoordTraits<C>::IntervalType CInterval;
+ typedef typename CoordTraits<C>::PointType CPoint;
+ typedef typename CoordTraits<C>::RectType CRect;
+ typedef typename CoordTraits<C>::OptRectType OptCRect;
+protected:
+ CInterval f[2];
+public:
+ /// @name Create rectangles.
+ /// @{
+ /** @brief Create a rectangle that contains only the point at (0,0). */
+ GenericRect() { f[X] = f[Y] = CInterval(); }
+ /** @brief Create a rectangle from X and Y intervals. */
+ GenericRect(CInterval const &a, CInterval const &b) {
+ f[X] = a;
+ f[Y] = b;
+ }
+ /** @brief Create a rectangle from two points. */
+ GenericRect(CPoint const &a, CPoint const &b) {
+ f[X] = CInterval(a[X], b[X]);
+ f[Y] = CInterval(a[Y], b[Y]);
+ }
+ /** @brief Create rectangle from coordinates of two points. */
+ GenericRect(C x0, C y0, C x1, C y1) {
+ f[X] = CInterval(x0, x1);
+ f[Y] = CInterval(y0, y1);
+ }
+ /** @brief Create a rectangle from a range of points.
+ * The resulting rectangle will contain all ponts from the range.
+ * The return type of iterators must be convertible to Point.
+ * The range must not be empty. For possibly empty ranges, see OptRect.
+ * @param start Beginning of the range
+ * @param end End of the range
+ * @return Rectangle that contains all points from [start, end). */
+ template <typename InputIterator>
+ static GenericRect<C> from_range(InputIterator start, InputIterator end) {
+ assert(start != end);
+ CPoint p1 = *start++;
+ GenericRect<C> result(p1, p1);
+ for (; start != end; ++start) {
+ result.expandTo(*start);
+ }
+ return result;
+ }
+ /** @brief Create a rectangle from a C-style array of points it should contain. */
+ static GenericRect<C> from_array(CPoint const *c, unsigned n) {
+ GenericRect<C> result = GenericRect<C>::from_range(c, c+n);
+ return result;
+ }
+ /** @brief Create rectangle from origin and dimensions. */
+ static GenericRect<C> from_xywh(C x, C y, C w, C h) {
+ CPoint xy(x, y);
+ CPoint wh(w, h);
+ GenericRect<C> result(xy, xy + wh);
+ return result;
+ }
+ /** @brief Create rectangle from origin and dimensions. */
+ static GenericRect<C> from_xywh(CPoint const &xy, CPoint const &wh) {
+ GenericRect<C> result(xy, xy + wh);
+ return result;
+ }
+ /// @}
+
+ /// @name Inspect dimensions.
+ /// @{
+ CInterval &operator[](unsigned i) { return f[i]; }
+ CInterval const &operator[](unsigned i) const { return f[i]; }
+
+ CPoint min() const { return CPoint(f[X].min(), f[Y].min()); }
+ CPoint max() const { return CPoint(f[X].max(), f[Y].max()); }
+ /** @brief Return the n-th corner of the rectangle.
+ * If the Y axis grows upwards, this returns corners in clockwise order
+ * starting from the lower left. If Y grows downwards, it returns the corners
+ * in counter-clockwise order starting from the upper left. */
+ CPoint corner(unsigned i) const {
+ switch(i % 4) {
+ case 0: return CPoint(f[X].min(), f[Y].min());
+ case 1: return CPoint(f[X].max(), f[Y].min());
+ case 2: return CPoint(f[X].max(), f[Y].max());
+ default: return CPoint(f[X].min(), f[Y].max());
+ }
+ }
+
+ //We should probably remove these - they're coord sys gnostic
+ /** @brief Return top coordinate of the rectangle (+Y is downwards). */
+ C top() const { return f[Y].min(); }
+ /** @brief Return bottom coordinate of the rectangle (+Y is downwards). */
+ C bottom() const { return f[Y].max(); }
+ /** @brief Return leftmost coordinate of the rectangle (+X is to the right). */
+ C left() const { return f[X].min(); }
+ /** @brief Return rightmost coordinate of the rectangle (+X is to the right). */
+ C right() const { return f[X].max(); }
+
+ /** @brief Get the horizontal extent of the rectangle. */
+ C width() const { return f[X].extent(); }
+ /** @brief Get the vertical extent of the rectangle. */
+ C height() const { return f[Y].extent(); }
+
+ /** @brief Get rectangle's width and height as a point.
+ * @return Point with X coordinate corresponding to the width and the Y coordinate
+ * corresponding to the height of the rectangle. */
+ CPoint dimensions() const { return CPoint(f[X].extent(), f[Y].extent()); }
+ /** @brief Get the point in the geometric center of the rectangle. */
+ CPoint midpoint() const { return CPoint(f[X].middle(), f[Y].middle()); }
+
+ /** @brief Compute rectangle's area. */
+ C area() const { return f[X].extent() * f[Y].extent(); }
+ /** @brief Check whether the rectangle has zero area. */
+ bool hasZeroArea() const { return (area() == 0); }
+
+ /** @brief Get the larger extent (width or height) of the rectangle. */
+ C maxExtent() const { return std::max(f[X].extent(), f[Y].extent()); }
+ /** @brief Get the smaller extent (width or height) of the rectangle. */
+ C minExtent() const { return std::min(f[X].extent(), f[Y].extent()); }
+ /// @}
+
+ /// @name Test other rectangles and points for inclusion.
+ /// @{
+ /** @brief Check whether the rectangles have any common points. */
+ bool intersects(GenericRect<C> const &r) const {
+ return f[X].intersects(r[X]) && f[Y].intersects(r[Y]);
+ }
+ /** @brief Check whether the rectangle includes all points in the given rectangle. */
+ bool contains(GenericRect<C> const &r) const {
+ return f[X].contains(r[X]) && f[Y].contains(r[Y]);
+ }
+
+ /** @brief Check whether the rectangles have any common points.
+ * A non-empty rectangle will not intersect empty rectangles. */
+ inline bool intersects(OptCRect const &r) const;
+ /** @brief Check whether the rectangle includes all points in the given rectangle.
+ * A non-empty rectangle will contain any empty rectangle. */
+ inline bool contains(OptCRect const &r) const;
+
+ /** @brief Check whether the given point is within the rectangle. */
+ bool contains(CPoint const &p) const {
+ return f[X].contains(p[X]) && f[Y].contains(p[Y]);
+ }
+ /// @}
+
+ /// @name Modify the rectangle.
+ /// @{
+ /** @brief Set the upper left point of the rectangle. */
+ void setMin(CPoint const &p) {
+ f[X].setMin(p[X]);
+ f[Y].setMin(p[Y]);
+ }
+ /** @brief Set the lower right point of the rectangle. */
+ void setMax(CPoint const &p) {
+ f[X].setMax(p[X]);
+ f[Y].setMax(p[Y]);
+ }
+ /** @brief Enlarge the rectangle to contain the given point. */
+ void expandTo(CPoint const &p) {
+ f[X].expandTo(p[X]); f[Y].expandTo(p[Y]);
+ }
+ /** @brief Enlarge the rectangle to contain the given rectangle. */
+ void unionWith(GenericRect<C> const &b) {
+ f[X].unionWith(b[X]); f[Y].unionWith(b[Y]);
+ }
+ /** @brief Enlarge the rectangle to contain the given rectangle.
+ * Unioning with an empty rectangle results in no changes. */
+ void unionWith(OptCRect const &b);
+
+ /** @brief Expand the rectangle in both directions by the specified amount.
+ * Note that this is different from scaling. Negative values wil shrink the
+ * rectangle. If <code>-amount</code> is larger than
+ * half of the width, the X interval will contain only the X coordinate
+ * of the midpoint; same for height. */
+ void expandBy(C amount) {
+ f[X].expandBy(amount); f[Y].expandBy(amount);
+ }
+ /** @brief Expand the rectangle by the coordinates of the given point.
+ * This will expand the width by the X coordinate of the point in both directions
+ * and the height by Y coordinate of the point. Negative coordinate values will
+ * shrink the rectangle. If <code>-p[X]</code> is larger than half of the width,
+ * the X interval will contain only the X coordinate of the midpoint; same for height. */
+ void expandBy(CPoint const &p) {
+ f[X].expandBy(p[X]); f[Y].expandBy(p[Y]);
+ }
+ /// @}
+
+ /// @name Operators
+ /// @{
+ /** @brief Offset the rectangle by a vector. */
+ GenericRect<C> &operator+=(CPoint const &p) {
+ f[X] += p[X];
+ f[Y] += p[Y];
+ return *this;
+ }
+ /** @brief Offset the rectangle by the negation of a vector. */
+ GenericRect<C> &operator-=(CPoint const &p) {
+ f[X] -= p[X];
+ f[Y] -= p[Y];
+ return *this;
+ }
+ /** @brief Union two rectangles. */
+ GenericRect<C> &operator|=(GenericRect<C> const &o) {
+ unionWith(o);
+ return *this;
+ }
+ GenericRect<C> &operator|=(OptCRect const &o) {
+ unionWith(o);
+ return *this;
+ }
+ /** @brief Test for equality of rectangles. */
+ bool operator==(GenericRect<C> const &o) const { return f[X] == o[X] && f[Y] == o[Y]; }
+ /// @}
+};
+
+/**
+ * @brief Axis-aligned generic rectangle that can be empty.
+ * @ingroup Primitives
+ */
+template <typename C>
+class GenericOptRect
+ : public boost::optional<typename CoordTraits<C>::RectType>
+ , boost::orable< GenericOptRect<C>
+ , boost::andable< GenericOptRect<C>
+ , boost::andable< GenericOptRect<C>, typename CoordTraits<C>::RectType
+ > > >
+{
+ typedef typename CoordTraits<C>::IntervalType CInterval;
+ typedef typename CoordTraits<C>::OptIntervalType OptCInterval;
+ typedef typename CoordTraits<C>::PointType CPoint;
+ typedef typename CoordTraits<C>::RectType CRect;
+ typedef typename CoordTraits<C>::OptRectType OptCRect;
+ typedef boost::optional<CRect> Base;
+public:
+ GenericOptRect() : Base() {}
+ GenericOptRect(GenericRect<C> const &a) : Base(CRect(a)) {}
+ GenericOptRect(CPoint const &a, CPoint const &b) : Base(CRect(a, b)) {}
+ /**
+ * Creates an empty OptRect when one of the argument intervals is empty.
+ */
+ GenericOptRect(OptCInterval const &x_int, OptCInterval const &y_int) {
+ if (x_int && y_int) {
+ *this = CRect(*x_int, *y_int);
+ }
+ // else, stay empty.
+ }
+
+ /** @brief Check for emptiness. */
+ inline bool isEmpty() const { return !*this; };
+
+ bool intersects(CRect const &r) const { return r.intersects(*this); }
+ bool contains(CRect const &r) const { return *this && (*this)->contains(r); }
+
+ bool intersects(OptCRect const &r) const { return *this && (*this)->intersects(r); }
+ bool contains(OptCRect const &r) const { return *this && (*this)->contains(r); }
+
+ bool contains(CPoint const &p) const { return *this && (*this)->contains(p); }
+
+ void unionWith(CRect const &b) {
+ if (*this) {
+ (*this)->unionWith(b);
+ } else {
+ *this = b;
+ }
+ }
+ void unionWith(OptCRect const &b) {
+ if (b) unionWith(*b);
+ }
+ void intersectWith(CRect const &b) {
+ if (!*this) return;
+ OptCInterval x = (**this)[X] & b[X], y = (**this)[Y] & b[Y];
+ if (x && y) {
+ *this = CRect(*x, *y);
+ } else {
+ *(static_cast<Base*>(this)) = boost::none;
+ }
+ }
+ void intersectWith(OptCRect const &b) {
+ if (b) {
+ intersectWith(*b);
+ } else {
+ *(static_cast<Base*>(this)) = boost::none;
+ }
+ }
+ GenericOptRect<C> &operator|=(OptCRect const &b) {
+ unionWith(b);
+ return *this;
+ }
+ GenericOptRect<C> &operator&=(CRect const &b) {
+ intersectWith(b);
+ return *this;
+ }
+ GenericOptRect<C> &operator&=(OptCRect const &b) {
+ intersectWith(b);
+ return *this;
+ }
+};
+
+template <typename C>
+inline void GenericRect<C>::unionWith(OptCRect const &b) {
+ if (b) {
+ unionWith(*b);
+ }
+}
+template <typename C>
+inline bool GenericRect<C>::intersects(OptCRect const &r) const {
+ return r && intersects(*r);
+}
+template <typename C>
+inline bool GenericRect<C>::contains(OptCRect const &r) const {
+ return !r || contains(*r);
+}
+
+#ifdef _GLIBCXX_IOSTREAM
+template <typename C>
+inline std::ostream &operator<<(std::ostream &out, GenericRect<C> const &r) {
+ out << "X: " << r[X] << " Y: " << r[Y];
+ return out;
+}
+#endif
+
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_RECT_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/2geom/hvlinesegment.h b/src/2geom/hvlinesegment.h
index 9419be8f6..05252468e 100644
--- a/src/2geom/hvlinesegment.h
+++ b/src/2geom/hvlinesegment.h
@@ -1,8 +1,11 @@
/**
* \file
- * \brief Horizontal and Vertical Line Segment
- *
- * Copyright 2008 Marco Cecchetti <mrcekets at gmail.com>
+ * \brief Horizontal and vertical line segment
+ *//*
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ * Copyright 2008-2011 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -28,14 +31,11 @@
* the specific language governing rights and limitations.
*/
-
-#ifndef _2GEOM_HVLINESEGMENT_H_
-#define _2GEOM_HVLINESEGMENT_H_
-
+#ifndef LIB2GEOM_SEEN_HVLINESEGMENT_H
+#define LIB2GEOM_SEEN_HVLINESEGMENT_H
#include <2geom/bezier-curve.h>
-
namespace Geom
{
@@ -44,6 +44,7 @@ class AxisLineSegment : public LineSegment
{
public:
static const Dim2 other_axis = static_cast<Dim2>((axis + 1) % 2);
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
virtual void setInitial(Point const &p) {
Point f = finalPoint();
f[axis] = p[axis];
@@ -106,10 +107,6 @@ public:
if (d != axis) return initialPoint()[other_axis];
return initialPoint()[axis] + t * (finalPoint()[axis] - initialPoint()[axis]);
}
-
- /**
- * The size of the returned vector equals n+1.
- */
virtual std::vector<Point> pointAndDerivatives(Coord t, unsigned n) const {
std::vector<Point> result;
result.push_back(pointAt(t));
@@ -124,6 +121,7 @@ public:
}
return result;
}
+#endif
protected:
AxisLineSegment(Point const &p0, Point const &p1) : LineSegment(p0, p1) {}
AxisLineSegment() {}
@@ -171,6 +169,7 @@ public:
return result;
}
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
virtual Curve* duplicate() const { return new HLineSegment(*this); }
virtual Curve *portion(Coord f, Coord t) const {
Point ip = pointAt(f);
@@ -195,6 +194,7 @@ public:
Coord x = finalPoint()[X] - initialPoint()[X];
return new HLineSegment(x, x, 0);
}
+#endif
}; // end class HLineSegment
@@ -241,6 +241,7 @@ public:
return result;
}
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
virtual Curve *duplicate() const { return new VLineSegment(*this); }
virtual Curve *portion(Coord f, Coord t) const {
Point ip = pointAt(f);
@@ -264,13 +265,12 @@ public:
Coord y = finalPoint()[Y] - initialPoint()[Y];
return new VLineSegment(0, y, y);
}
+#endif
}; // end class VLineSegment
} // end namespace Geom
-
-#endif // _2GEOM_HVLINESEGMENT_H_
-
+#endif // LIB2GEOM_SEEN_HVLINESEGMENT_H
/*
Local Variables:
diff --git a/src/2geom/int-interval.h b/src/2geom/int-interval.h
new file mode 100644
index 000000000..0faf48d80
--- /dev/null
+++ b/src/2geom/int-interval.h
@@ -0,0 +1,63 @@
+/**
+ * \file
+ * \brief Closed interval of integer values
+ *//*
+ * Copyright 2011 Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_INT_INTERVAL_H
+#define LIB2GEOM_SEEN_INT_INTERVAL_H
+
+#include <2geom/coord.h>
+#include <2geom/generic-interval.h>
+
+namespace Geom {
+
+/**
+ * @brief Range of integers that is never empty.
+ * @ingroup Primitives
+ */
+typedef GenericInterval<IntCoord> IntInterval;
+
+/**
+ * @brief Range of integers that can be empty.
+ * @ingroup Primitives
+ */
+typedef GenericOptInterval<IntCoord> OptIntInterval;
+
+} // namespace Geom
+#endif // !LIB2GEOM_SEEN_INT_INTERVAL_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/2geom/int-point.h b/src/2geom/int-point.h
new file mode 100644
index 000000000..cf2fe720f
--- /dev/null
+++ b/src/2geom/int-point.h
@@ -0,0 +1,157 @@
+/**
+ * \file
+ * \brief Cartesian point / 2D vector with integer coordinates
+ *//*
+ * Copyright 2011 Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_INT_POINT_H
+#define LIB2GEOM_SEEN_INT_POINT_H
+
+#include <stdexcept>
+#include <boost/operators.hpp>
+#include <2geom/coord.h>
+
+namespace Geom {
+
+/**
+ * @brief Two-dimensional point with integer coordinates.
+ *
+ * This class is an exact equivalent of Point, except it stores integer coordinates.
+ * Integer points are useful in contexts related to rasterized graphics, for example
+ * for bounding boxes when rendering SVG.
+ *
+ * @see Point
+ * @ingroup Primitives */
+class IntPoint
+ : boost::additive< IntPoint
+ , boost::totally_ordered< IntPoint
+ > >
+{
+ IntCoord _pt[2];
+public:
+ /// @name Creating integer points
+ /// @{
+ IntPoint() { }
+ IntPoint(IntCoord x, IntCoord y) {
+ _pt[X] = x;
+ _pt[Y] = y;
+ }
+ IntPoint(IntPoint const &p) {
+ _pt[X] = p._pt[X];
+ _pt[Y] = p._pt[Y];
+ }
+ IntPoint &operator=(IntPoint const &p) {
+ _pt[X] = p._pt[X];
+ _pt[Y] = p._pt[Y];
+ return *this;
+ }
+ /// @}
+
+ /// @name Access the coordinates of a point
+ /// @{
+ IntCoord operator[](unsigned i) const {
+ if ( i > Y ) throw std::out_of_range("index out of range");
+ return _pt[i];
+ }
+ IntCoord &operator[](unsigned i) {
+ if ( i > Y ) throw std::out_of_range("index out of range");
+ return _pt[i];
+ }
+ IntCoord operator[](Dim2 d) const { return _pt[d]; }
+ IntCoord &operator[](Dim2 d) { return _pt[d]; }
+ /// @}
+
+ /// @name Vector-like arithmetic operations
+ /// @{
+ IntPoint &operator+=(IntPoint const &o) {
+ _pt[X] += o._pt[X];
+ _pt[Y] += o._pt[Y];
+ return *this;
+ }
+ IntPoint &operator-=(IntPoint const &o) {
+ _pt[X] -= o._pt[X];
+ _pt[Y] -= o._pt[Y];
+ return *this;
+ }
+ /// @}
+
+ /// @name Various utilities
+ /// @{
+ /** @brief Equality operator. */
+ bool operator==(IntPoint const &in_pnt) const {
+ return ((_pt[X] == in_pnt[X]) && (_pt[Y] == in_pnt[Y]));
+ }
+ /** @brief Lexicographical ordering for points.
+ * Y coordinate is regarded as more significant. When sorting according to this
+ * ordering, the points will be sorted according to the Y coordinate, and within
+ * points with the same Y coordinate according to the X coordinate. */
+ bool operator<(IntPoint const &p) const {
+ return ( ( _pt[Y] < p[Y] ) ||
+ (( _pt[Y] == p[Y] ) && ( _pt[X] < p[X] )));
+ }
+ /// @}
+
+ /** @brief Lexicographical ordering functor. */
+ template <Dim2 d> struct LexOrder;
+ /** @brief Lexicographical ordering functor with runtime dimension. */
+ class LexOrderRt {
+ public:
+ LexOrderRt(Dim2 d) : dim(d) {}
+ inline bool operator()(IntPoint const &a, IntPoint const &b);
+ private:
+ Dim2 dim;
+ };
+};
+
+template<> struct IntPoint::LexOrder<X> {
+ bool operator()(IntPoint const &a, IntPoint const &b) {
+ return a[X] < b[X] || (a[X] == b[X] && a[Y] < b[Y]);
+ }
+};
+template<> struct IntPoint::LexOrder<Y> {
+ bool operator()(IntPoint const &a, IntPoint const &b) {
+ return a[Y] < b[Y] || (a[Y] == b[Y] && a[X] < b[X]);
+ }
+};
+inline bool IntPoint::LexOrderRt::operator()(IntPoint const &a, IntPoint const &b) {
+ return dim ? IntPoint::LexOrder<Y>()(a, b) : IntPoint::LexOrder<X>()(a, b);
+}
+
+} // namespace Geom
+
+#endif // !SEEN_GEOM_INT_POINT_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/2geom/int-rect.h b/src/2geom/int-rect.h
new file mode 100644
index 000000000..a143b3ac5
--- /dev/null
+++ b/src/2geom/int-rect.h
@@ -0,0 +1,76 @@
+/**
+ * \file
+ * \brief Axis-aligned rectangle with integer coordinates
+ *//*
+ * Copyright 2011 Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef LIB2GEOM_SEEN_INT_RECT_H
+#define LIB2GEOM_SEEN_INT_RECT_H
+
+#include <2geom/coord.h>
+#include <2geom/int-point.h>
+#include <2geom/int-interval.h>
+#include <2geom/generic-rect.h>
+
+namespace Geom {
+
+typedef GenericRect<IntCoord> IntRect;
+typedef GenericOptRect<IntCoord> OptIntRect;
+
+// the functions below do not work when defined generically
+inline OptIntRect operator&(IntRect const &a, IntRect const &b) {
+ OptIntRect ret(a);
+ ret.intersectWith(b);
+ return ret;
+}
+inline OptIntRect intersect(IntRect const &a, IntRect const &b) {
+ return a & b;
+}
+inline OptIntRect intersect(OptIntRect const &a, OptIntRect const &b) {
+ return a & b;
+}
+inline IntRect unify(IntRect const &a, IntRect const &b) {
+ return a | b;
+}
+inline OptIntRect unify(OptIntRect const &a, OptIntRect const &b) {
+ return a | b;
+}
+
+} // end namespace Geom
+
+#endif // !LIB2GEOM_SEEN_INT_RECT_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/2geom/interval.h b/src/2geom/interval.h
index a790a6c3b..ee6d674d2 100644
--- a/src/2geom/interval.h
+++ b/src/2geom/interval.h
@@ -37,19 +37,24 @@
#ifndef LIB2GEOM_SEEN_INTERVAL_H
#define LIB2GEOM_SEEN_INTERVAL_H
-#include <assert.h>
#include <boost/none.hpp>
#include <boost/optional.hpp>
#include <boost/operators.hpp>
#include <2geom/coord.h>
-#include <2geom/isnan.h>
+#include <2geom/math-utils.h>
+#include <2geom/generic-interval.h>
+#include <2geom/int-interval.h>
namespace Geom {
-class OptInterval;
+/**
+ * @brief Range of real numbers that can be empty.
+ * @ingroup Primitives
+ */
+typedef GenericOptInterval<Coord> OptInterval;
/**
- * @brief Range of numbers that is never empty.
+ * @brief Range of real numbers that is never empty.
*
* Intervals are closed ranges \f$[a, b]\f$, which means they include their endpoints.
* To use them as open ranges, you can use the interiorContains() methods.
@@ -57,32 +62,24 @@ class OptInterval;
* @ingroup Primitives
*/
class Interval
- : boost::equality_comparable< Interval
- , boost::additive< Interval
+ : public GenericInterval<Coord>
, boost::multipliable< Interval
- , boost::arithmetic< Interval, Coord
- , boost::orable< Interval
- > > > > >
+ , boost::multipliable< Interval, Coord
+ > >
{
-private:
- /// @invariant _b[0] <= _b[1]
- Coord _b[2];
-
+ typedef GenericInterval<Coord> Base;
public:
/// @name Create intervals.
/// @{
/** @brief Create an interval that contains only zero. */
- explicit Interval() { _b[0] = 0; _b[1] = 0; }
+ Interval() {}
/** @brief Create an interval that contains a single point. */
- explicit Interval(Coord u) { _b[0] = _b[1] = u; }
+ explicit Interval(Coord u) : Base(u) {}
/** @brief Create an interval that contains all points between @c u and @c v. */
- Interval(Coord u, Coord v) {
- if (u <= v) {
- _b[0] = u; _b[1] = v;
- } else {
- _b[0] = v; _b[1] = u;
- }
- }
+ Interval(Coord u, Coord v) : Base(u,v) {}
+ /** @brief Convert from integer interval */
+ Interval(IntInterval const &i) : Base(i.min(), i.max()) {}
+ Interval(Base const &b) : Base(b) {}
/** @brief Create an interval containing a range of values.
* The resulting interval will contain all values from the given range.
@@ -93,9 +90,7 @@ public:
* @return Interval that contains all values from [start, end). */
template <typename InputIterator>
static Interval from_range(InputIterator start, InputIterator end) {
- assert(start != end);
- Interval result(*start++);
- for (; start != end; ++start) result.expandTo(*start);
+ Interval result = Base::from_range(start, end);
return result;
}
/** @brief Create an interval from a C-style array of values it should contain. */
@@ -107,114 +102,38 @@ public:
/// @name Inspect endpoints.
/// @{
+ /** @brief Access endpoints by value.
+ * @deprecated Use min() and max() instead */
Coord operator[](unsigned i) const { return _b[i]; }
+ /** @brief Access endpoints by reference.
+ * @deprecated Use min() and max() instead
+ * @todo Remove Interval index operator, which can be used to break the invariant */
Coord& operator[](unsigned i) { return _b[i]; }
- Coord min() const { return _b[0]; }
- Coord max() const { return _b[1]; }
- Coord extent() const { return _b[1] - _b[0]; }
- Coord middle() const { return (_b[1] + _b[0]) * 0.5; }
- bool isSingular() const { return _b[0] == _b[1]; }
bool isFinite() const {
- return IS_FINITE(_b[0]) && IS_FINITE(_b[1]);
+ return IS_FINITE(min()) && IS_FINITE(max());
}
/// @}
/// @name Test coordinates and other intervals for inclusion.
/// @{
- /** @brief Check whether the interval includes this number. */
- bool contains(Coord val) const { return _b[0] <= val && val <= _b[1]; }
/** @brief Check whether the interior of the interval includes this number.
* Interior means all numbers in the interval except its ends. */
- bool interiorContains(Coord val) const { return _b[0] < val && val < _b[1]; }
- /** @brief Check whether the interval includes the given interval. */
- bool contains(Interval const &val) const { return _b[0] <= val._b[0] && val._b[1] <= _b[1]; }
+ bool interiorContains(Coord val) const { return min() < val && val < max(); }
/** @brief Check whether the interior of the interval includes the given interval.
* Interior means all numbers in the interval except its ends. */
- bool interiorContains(Interval const &val) const { return _b[0] < val._b[0] && val._b[1] < _b[1]; }
- /** @brief Check whether the intervals have any common elements. */
- bool intersects(Interval const &val) const {
- return contains(val._b[0]) || contains(val._b[1]) || val.contains(*this);
- }
+ bool interiorContains(Interval const &val) const { return min() < val.min() && val.max() < max(); }
/** @brief Check whether the interiors of the intervals have any common elements. */
bool interiorIntersects(Interval const &val) const {
- return interiorContains(val._b[0]) || interiorContains(val._b[1]) || val.interiorContains(*this);
- }
- /// @}
-
- /// @name Modify the interval.
- /// @{
- //TODO: NaN handleage for the next two?
- /** @brief Set the lower boundary of the interval.
- * When the given number is larger than the interval's largest element,
- * it will be reduced to the single number @c val. */
- void setMin(Coord val) {
- if(val > _b[1]) {
- _b[0] = _b[1] = val;
- } else {
- _b[0] = val;
- }
- }
- /** @brief Set the upper boundary of the interval.
- * When the given number is smaller than the interval's smallest element,
- * it will be reduced to the single number @c val. */
- void setMax(Coord val) {
- if(val < _b[0]) {
- _b[1] = _b[0] = val;
- } else {
- _b[1] = val;
- }
- }
- /** @brief Extend the interval to include the given number. */
- void expandTo(Coord val) {
- if(val < _b[0]) _b[0] = val;
- if(val > _b[1]) _b[1] = val; //no else, as we want to handle NaN
- }
- /** @brief Expand or shrink the interval in both directions by the given amount.
- * After this method, the interval's length (extent) will be increased by
- * <code>amount * 2</code>. Negative values can be given; they will shrink the interval.
- * Shrinking by a value larger than half the interval's length will create a degenerate
- * interval containing only the midpoint of the original. */
- void expandBy(double amount) {
- _b[0] -= amount;
- _b[1] += amount;
- if (_b[0] > _b[1]) {
- Coord halfway = (_b[0]+_b[1])/2;
- _b[0] = _b[1] = halfway;
- }
- }
- /** @brief Union the interval with another one.
- * The resulting interval will contain all points of both intervals.
- * It might also contain some points which didn't belong to either - this happens
- * when the intervals did not have any common elements. */
- void unionWith(const Interval & a) {
- if(a._b[0] < _b[0]) _b[0] = a._b[0];
- if(a._b[1] > _b[1]) _b[1] = a._b[1];
+ return interiorContains(val.min()) || interiorContains(val.max()) || val.interiorContains(*this);
}
/// @}
/// @name Operators
/// @{
- inline operator OptInterval();
- bool operator==(Interval const &other) const { return _b[0] == other._b[0] && _b[1] == other._b[1]; }
-
- //IMPL: OffsetableConcept
- //TODO: rename output_type to something else in the concept
- typedef Coord output_type;
- /** @brief Offset the interval by a specified amount */
- Interval &operator+=(Coord amnt) {
- _b[0] += amnt; _b[1] += amnt;
- return *this;
- }
- /** @brief Offset the interval by the negation of the specified amount */
- Interval &operator-=(Coord amnt) {
- _b[0] -= amnt; _b[1] -= amnt;
- return *this;
- }
+ inline operator OptInterval() { return OptInterval(*this); }
// IMPL: ScalableConcept
- /** @brief Return an interval mirrored about 0 */
- Interval operator-() const { return Interval(-_b[1], -_b[0]); }
/** @brief Scale an interval */
Interval &operator*=(Coord s) {
_b[0] *= s;
@@ -229,25 +148,6 @@ public:
if(s < 0) std::swap(_b[0], _b[1]);
return *this;
}
- // IMPL: AddableConcept
- /** @brief Add two intervals.
- * Sum is defined as the set of points that can be obtained by adding any two values
- * from both operands: \f$S = \{x \in A, y \in B: x + y\}\f$ */
- Interval &operator+=(Interval const &o) {
- _b[0] += o._b[0];
- _b[1] += o._b[1];
- return *this;
- }
- /** @brief Subtract two intervals.
- * Difference is defined as the set of points that can be obtained by subtracting
- * any value from the second operand from any value from the first operand:
- * \f$S = \{x \in A, y \in B: x - y\}\f$ */
- Interval &operator-=(Interval const &o) {
- // equal to *this += -o
- _b[0] -= o._b[1];
- _b[1] -= o._b[0];
- return *this;
- }
/** @brief Multiply two intervals.
* Product is defined as the set of points that can be obtained by multiplying
* any value from the second operand by any value from the first operand:
@@ -261,121 +161,25 @@ public:
expandTo(mx * o.max());
return *this;
}
- /** @brief Union two intervals.
- * Note that intersection is only defined for OptIntervals, because the result
- * of an intersection can be empty, while an Interval cannot. */
- Interval &operator|=(Interval const &o) {
- unionWith(o);
- return *this;
- }
/// @}
-};
-
-/** @brief Union two intervals
- * @relates Interval */
-inline Interval unify(Interval const &a, Interval const &b) {
- return a | b;
-}
-
-/**
- * @brief A range of numbers that can be empty.
- * @ingroup Primitives
- */
-class OptInterval
- : public boost::optional<Interval>
- , boost::orable< OptInterval
- , boost::andable< OptInterval
- > >
-{
-public:
- /// @name Create optionally empty intervals.
+
+ /// @name Rounding to integer values
/// @{
- /** @brief Create an empty interval. */
- OptInterval() : boost::optional<Interval>() {};
- /** @brief Wrap an existing interval. */
- OptInterval(Interval const &a) : boost::optional<Interval>(a) {};
- /** @brief Create an interval containing a single point. */
- OptInterval(Coord u) : boost::optional<Interval>(Interval(u)) {};
- /** @brief Create an interval containing a range of numbers. */
- OptInterval(Coord u, Coord v) : boost::optional<Interval>(Interval(u,v)) {};
-
- /** @brief Create a possibly empty interval containing a range of values.
- * The resulting interval will contain all values from the given range.
- * The return type of iterators must be convertible to double. The given range
- * may be empty.
- * @param start Beginning of the range
- * @param end End of the range
- * @return Interval that contains all values from [start, end), or nothing if the range
- * is empty. */
- template <typename InputIterator>
- static OptInterval from_range(InputIterator start, InputIterator end) {
- if (start == end) {
- OptInterval ret;
- return ret;
- }
- OptInterval ret(Interval::from_range(start, end));
+ /** @brief Return the smallest integer interval which contains this one. */
+ IntInterval roundOutwards() const {
+ IntInterval ret(floor(min()), ceil(max()));
return ret;
}
- /// @}
-
- /** @brief Check whether this OptInterval is empty. */
- bool isEmpty() { return !*this; };
-
- /** @brief Union with another interval, gracefully handling empty ones. */
- inline void unionWith(OptInterval const &a) {
- if (a) {
- if (*this) { // check that we are not empty
- (*this)->unionWith(*a);
- } else {
- *this = a;
- }
- }
- }
- inline void intersectWith(OptInterval const &o) {
- if (o && *this) {
- Coord u, v;
- u = std::max((*this)->min(), o->min());
- v = std::min((*this)->max(), o->max());
- if (u <= v) {
- *this = Interval(u, v);
- return;
- }
- }
- (*static_cast<boost::optional<Interval>*>(this)) = boost::none;
- }
- OptInterval &operator|=(OptInterval const &o) {
- unionWith(o);
- return *this;
- }
- OptInterval &operator&=(OptInterval const &o) {
- intersectWith(o);
- return *this;
+ /** @brief Return the largest integer interval which is contained in this one. */
+ OptIntInterval roundInwards() const {
+ IntCoord u = ceil(min()), v = floor(max());
+ if (u > v) { OptIntInterval e; return e; }
+ IntInterval ret(u, v);
+ return ret;
}
+ /// @}
};
-/** @brief Intersect two intervals and return a possibly empty range of numbers
- * @relates OptInterval */
-inline OptInterval intersect(Interval const &a, Interval const &b) {
- return OptInterval(a) & OptInterval(b);
-}
-/** @brief Intersect two intervals and return a possibly empty range of numbers
- * @relates OptInterval */
-inline OptInterval operator&(Interval const &a, Interval const &b) {
- return OptInterval(a) & OptInterval(b);
-}
-
-inline Interval::operator OptInterval() {
- return OptInterval(*this);
-}
-
-#ifdef _GLIBCXX_IOSTREAM
-inline std::ostream &operator<< (std::ostream &os,
- const Geom::Interval &I) {
- os << "Interval("<<I[0] << ", "<<I[1] << ")";
- return os;
-}
-#endif
-
}
#endif //SEEN_INTERVAL_H
diff --git a/src/2geom/isnan.h b/src/2geom/isnan.h
deleted file mode 100644
index e20ab7f87..000000000
--- a/src/2geom/isnan.h
+++ /dev/null
@@ -1,116 +0,0 @@
-/**
- * \file
- * \brief \todo brief description
- *
- * Authors:
- * ? <?@?.?>
- *
- * Copyright ?-? authors
- *
- * This library is free software; you can redistribute it and/or
- * modify it either under the terms of the GNU Lesser General Public
- * License version 2.1 as published by the Free Software Foundation
- * (the "LGPL") or, at your option, under the terms of the Mozilla
- * Public License Version 1.1 (the "MPL"). If you do not alter this
- * notice, a recipient may use your version of this file under either
- * the MPL or the LGPL.
- *
- * You should have received a copy of the LGPL along with this library
- * in the file COPYING-LGPL-2.1; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- * You should have received a copy of the MPL along with this library
- * in the file COPYING-MPL-1.1
- *
- * The contents of this file are subject to the Mozilla Public License
- * Version 1.1 (the "License"); you may not use this file except in
- * compliance with the License. You may obtain a copy of the License at
- * http://www.mozilla.org/MPL/
- *
- * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
- * OF ANY KIND, either express or implied. See the LGPL or the MPL for
- * the specific language governing rights and limitations.
- *
- */
-
-#ifndef _2GEOM_ISNAN_H__
-#define _2GEOM_ISNAN_H__
-
-/*
- * Temporary fix for various misdefinitions of isnan().
- * isnan() is becoming undef'd in some .h files.
- * #include this last in your .cpp file to get it right.
- *
- * The problem is that isnan and isfinite are part of C99 but aren't part of
- * the C++ standard (which predates C99).
- *
- * Authors:
- * Inkscape groupies and obsessive-compulsives
- *
- * Copyright (C) 2004 authors
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- *
- * 2005 modification hereby placed in public domain. Probably supercedes
- * the 2004 copyright for the code itself.
- */
-
-#include <math.h>
-/* You might try changing the above to <cmath> if you have problems.
- * Whether you use math.h or cmath, you may need to edit the .cpp file
- * and/or other .h files to use the same header file.
- */
-
-#if defined(__isnan)
-# define IS_NAN(_a) (__isnan(_a))
-#elif defined(__APPLE__) && __GNUC__ == 3
-# define IS_NAN(_a) (__isnan(_a)) /* MacOSX/Darwin definition < 10.4 */
-#elif defined(WIN32) || defined(_isnan)
-# define IS_NAN(_a) (_isnan(_a)) /* Win32 definition */
-#elif defined(isnan) || defined(__FreeBSD__) || defined(__osf__)
-# define IS_NAN(_a) (isnan(_a)) /* GNU definition */
-#elif defined (SOLARIS_2_8) && __GNUC__ == 3 && __GNUC_MINOR__ == 2
-# define IS_NAN(_a) (isnan(_a)) /* GNU definition */
-#else
-# define IS_NAN(_a) (std::isnan(_a))
-#endif
-/* If the above doesn't work, then try (a != a).
- * Also, please report a bug as per http://www.inkscape.org/report_bugs.php,
- * giving information about what platform and compiler version you're using.
- */
-
-
-#if defined(__isfinite)
-# define IS_FINITE(_a) (__isfinite(_a))
-#elif defined(__APPLE__) && __GNUC__ == 3
-# define IS_FINITE(_a) (__isfinite(_a)) /* MacOSX/Darwin definition < 10.4 */
-#elif defined(__sgi)
-# define IS_FINITE(_a) (_isfinite(_a))
-#elif defined(isfinite)
-# define IS_FINITE(_a) (isfinite(_a))
-#elif defined(__osf__)
-# define IS_FINITE(_a) (finite(_a) && !IS_NAN(_a))
-#elif defined (SOLARIS_2_8) && __GNUC__ == 3 && __GNUC_MINOR__ == 2
-#include <ieeefp.h>
-#define IS_FINITE(_a) (finite(_a) && !IS_NAN(_a))
-#else
-# define IS_FINITE(_a) (std::isfinite(_a))
-#endif
-/* If the above doesn't work, then try (finite(_a) && !IS_NAN(_a)) or
- * (!IS_NAN((_a) - (_a))).
- * Also, please report a bug as per http://www.inkscape.org/report_bugs.php,
- * giving information about what platform and compiler version you're using.
- */
-
-
-#endif /* _2GEOM_ISNAN_H__ */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/2geom/line.h b/src/2geom/line.h
index ccb0ae6c5..f2d31ecc6 100644
--- a/src/2geom/line.h
+++ b/src/2geom/line.h
@@ -1,8 +1,11 @@
/**
* \file
- * \brief Infinite Straight Line
- *
- * Copyright 2008 Marco Cecchetti <mrcekets at gmail.com>
+ * \brief Infinite straight line
+ *//*
+ * Authors:
+ * Marco Cecchetti <mrcekets at gmail.com>
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ * Copyright 2008-2011 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -28,22 +31,17 @@
* the specific language governing rights and limitations.
*/
-#ifndef _2GEOM_LINE_H_
-#define _2GEOM_LINE_H_
-
+#ifndef LIB2GEOM_SEEN_LINE_H
+#define LIB2GEOM_SEEN_LINE_H
#include <cmath>
-
+#include <boost/optional.hpp>
#include <2geom/bezier-curve.h> // for LineSegment
#include <2geom/rect.h>
#include <2geom/crossing.h>
#include <2geom/exception.h>
-
#include <2geom/ray.h>
-#include <boost/optional.hpp>
-
-
namespace Geom
{
@@ -226,8 +224,8 @@ public:
* @return Ray starting at t and going in the direction of the versor */
Ray ray(Coord t) {
Ray result;
- result.origin(pointAt(t));
- result.versor(m_versor);
+ result.setOrigin(pointAt(t));
+ result.setVersor(m_versor);
return result;
}
@@ -448,17 +446,16 @@ OptCrossing intersection(LineSegment const& ls1, LineSegment const& ls2);
} // end namespace Geom
-#endif // _2GEOM_LINE_H_
+#endif // LIB2GEOM_SEEN_LINE_H
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(substatement-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
- c-brace-offset:0
fill-column:99
End:
- vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/2geom/linear.h b/src/2geom/linear.h
index 1b6cca071..df6dd9904 100644
--- a/src/2geom/linear.h
+++ b/src/2geom/linear.h
@@ -35,7 +35,7 @@
#ifndef SEEN_LINEAR_H
#define SEEN_LINEAR_H
#include <2geom/interval.h>
-#include <2geom/isnan.h>
+#include <2geom/math-utils.h>
//#define USE_SBASIS_OF
diff --git a/src/2geom/math-utils.h b/src/2geom/math-utils.h
index 2c348f54b..77280aa50 100644
--- a/src/2geom/math-utils.h
+++ b/src/2geom/math-utils.h
@@ -1,6 +1,3 @@
-#ifndef LIB2GEOM_MATH_UTILS_HEADER
-#define LIB2GEOM_MATH_UTILS_HEADER
-
/**
* \file
* \brief Low level math functions and compatibility wrappers
@@ -36,6 +33,9 @@
*
*/
+#ifndef LIB2GEOM_SEEN_MATH_UTILS_H
+#define LIB2GEOM_SEEN_MATH_UTILS_H
+
#include "config.h"
#include <math.h> // sincos is usually only available in math.h
#include <cmath>
@@ -92,10 +92,51 @@ inline void sincos(double angle, double &sin_, double &cos_) {
#endif
}
-}
+/* Temporary fix for various misdefinitions of isnan().
+ * isnan() is becoming undef'd in some .h files.
+ * #include this last in your .cpp file to get it right.
+ *
+ * The problem is that isnan and isfinite are part of C99 but aren't part of
+ * the C++ standard (which predates C99).
+ */
+
+#if defined(__isnan)
+# define IS_NAN(_a) (__isnan(_a))
+#elif defined(__APPLE__) && __GNUC__ == 3
+# define IS_NAN(_a) (__isnan(_a)) /* MacOSX/Darwin definition < 10.4 */
+#elif defined(WIN32) || defined(_isnan)
+# define IS_NAN(_a) (_isnan(_a)) /* Win32 definition */
+#elif defined(isnan) || defined(__FreeBSD__) || defined(__osf__)
+# define IS_NAN(_a) (isnan(_a)) /* GNU definition */
+#elif defined (SOLARIS_2_8) && __GNUC__ == 3 && __GNUC_MINOR__ == 2
+# define IS_NAN(_a) (isnan(_a)) /* GNU definition */
+#else
+# define IS_NAN(_a) (std::isnan(_a))
+#endif
+/* If the above doesn't work, then try (a != a). */
+
+#if defined(__isfinite)
+# define IS_FINITE(_a) (__isfinite(_a))
+#elif defined(__APPLE__) && __GNUC__ == 3
+# define IS_FINITE(_a) (__isfinite(_a)) /* MacOSX/Darwin definition < 10.4 */
+#elif defined(__sgi)
+# define IS_FINITE(_a) (_isfinite(_a))
+#elif defined(isfinite)
+# define IS_FINITE(_a) (isfinite(_a))
+#elif defined(__osf__)
+# define IS_FINITE(_a) (finite(_a) && !IS_NAN(_a))
+#elif defined (SOLARIS_2_8) && __GNUC__ == 3 && __GNUC_MINOR__ == 2
+#include <ieeefp.h>
+#define IS_FINITE(_a) (finite(_a) && !IS_NAN(_a))
+#else
+# define IS_FINITE(_a) (std::isfinite(_a))
#endif
+} // end namespace Geom
+
+#endif // LIB2GEOM_SEEN_MATH_UTILS_H
+
/*
Local Variables:
mode:c++
diff --git a/src/2geom/ord.h b/src/2geom/ord.h
index ca91af579..ce524ebf7 100644
--- a/src/2geom/ord.h
+++ b/src/2geom/ord.h
@@ -1,7 +1,7 @@
/**
* \file
- * \brief \todo brief description
- *
+ * \brief Comparator template
+ *//*
* Authors:
* ? <?@?.?>
*
diff --git a/src/2geom/path-intersection.h b/src/2geom/path-intersection.h
index de2a5b02c..2470e44fb 100644
--- a/src/2geom/path-intersection.h
+++ b/src/2geom/path-intersection.h
@@ -1,7 +1,7 @@
/**
* \file
- * \brief \todo brief description
- *
+ * \brief Path intersection
+ *//*
* Authors:
* ? <?@?.?>
*
diff --git a/src/2geom/path.h b/src/2geom/path.h
index cbd449248..48d7acaaf 100644
--- a/src/2geom/path.h
+++ b/src/2geom/path.h
@@ -1,12 +1,12 @@
/**
* \file
* \brief Path - Series of continuous curves
- *
+ *//*
* Authors:
- * MenTaLguY <mental@rydia.net>
- * Marco Cecchetti <mrcekets at gmail.com>
+ * MenTaLguY <mental@rydia.net>
+ * Marco Cecchetti <mrcekets at gmail.com>
*
- * Copyright 2007-2008 authors
+ * Copyright 2007-2008 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -32,23 +32,16 @@
* the specific language governing rights and limitations.
*/
+#ifndef LIB2GEOM_SEEN_PATH_H
+#define LIB2GEOM_SEEN_PATH_H
-
-
-#ifndef SEEN_GEOM_PATH_H
-#define SEEN_GEOM_PATH_H
-
-
+#include <iterator>
+#include <algorithm>
#include <boost/shared_ptr.hpp>
#include <2geom/curve.h>
#include <2geom/bezier-curve.h>
-#include <iterator>
-#include <algorithm>
-
-
-namespace Geom
-{
+namespace Geom {
class Path;
@@ -696,17 +689,13 @@ Coord nearest_point(Point const& p, Path const& c)
namespace std {
template <>
-inline void swap<Geom::Path>(Geom::Path &a, Geom::Path &b)
-{
+inline void swap<Geom::Path>(Geom::Path &a, Geom::Path &b) {
a.swap(b);
}
} // end namespace std
-#endif // SEEN_GEOM_PATH_H
-
-
-
+#endif // LIB2GEOM_SEEN_PATH_H
/*
Local Variables:
diff --git a/src/2geom/pathvector.h b/src/2geom/pathvector.h
index 2f45b9d86..2b690a005 100644
--- a/src/2geom/pathvector.h
+++ b/src/2geom/pathvector.h
@@ -1,10 +1,9 @@
/**
* \file
- * \brief PathVector - std::vector containing Geom::Path
+ * \brief PathVector - std::vector containing Geom::Path.
* This file provides a set of operations that can be performed on PathVector,
* e.g. an affine transform.
- */
-/*
+ *//*
* Authors:
* Johan Engelen <goejendaagh@zonnet.nl>
*
@@ -34,8 +33,8 @@
* the specific language governing rights and limitations.
*/
-#ifndef SEEN_GEOM_PATHVECTOR_H
-#define SEEN_GEOM_PATHVECTOR_H
+#ifndef LIB2GEOM_SEEN_PATHVECTOR_H
+#define LIB2GEOM_SEEN_PATHVECTOR_H
#include <2geom/forward.h>
#include <2geom/path.h>
@@ -122,11 +121,9 @@ Point pointAt(PathVector const & path_in, PathVectorPosition const pvp) {
return path_in[pvp.path_nr].pointAt(pvp.t);
}
-
-
} // end namespace Geom
-#endif // SEEN_GEOM_PATHVECTOR_H
+#endif // LIB2GEOM_SEEN_PATHVECTOR_H
/*
Local Variables:
diff --git a/src/2geom/piecewise.h b/src/2geom/piecewise.h
index 19c66d8f0..837f33ea7 100644
--- a/src/2geom/piecewise.h
+++ b/src/2geom/piecewise.h
@@ -32,13 +32,13 @@
#ifndef SEEN_GEOM_PW_SB_H
#define SEEN_GEOM_PW_SB_H
-#include <2geom/sbasis.h>
#include <vector>
#include <map>
-
-#include <2geom/concepts.h>
-#include <2geom/isnan.h>
#include <boost/concept_check.hpp>
+#include <2geom/concepts.h>
+#include <2geom/math-utils.h>
+#include <2geom/sbasis.h>
+
namespace Geom {
/**
diff --git a/src/2geom/point-l.h b/src/2geom/point-l.h
deleted file mode 100644
index d57314a19..000000000
--- a/src/2geom/point-l.h
+++ /dev/null
@@ -1,86 +0,0 @@
-#ifndef SEEN_Geom_POINT_L_H
-#define SEEN_Geom_POINT_L_H
-
-#include <stdexcept>
-#include <2geom/point.h>
-
-namespace Geom {
-
-typedef long ICoord;
-
-class IPoint {
- ICoord _pt[2];
-
- public:
- IPoint() { }
-
- IPoint(ICoord x, ICoord y) {
- _pt[X] = x;
- _pt[Y] = y;
- }
-
- IPoint(NRPointL const &p) {
- _pt[X] = p.x;
- _pt[Y] = p.y;
- }
-
- IPoint(IPoint const &p) {
- for (unsigned i = 0; i < 2; ++i) {
- _pt[i] = p._pt[i];
- }
- }
-
- IPoint &operator=(IPoint const &p) {
- for (unsigned i = 0; i < 2; ++i) {
- _pt[i] = p._pt[i];
- }
- return *this;
- }
-
- operator Point() {
- return Point(_pt[X], _pt[Y]);
- }
-
- ICoord operator[](unsigned i) const throw(std::out_of_range) {
- if ( i > Y ) throw std::out_of_range("index out of range");
- return _pt[i];
- }
-
- ICoord &operator[](unsigned i) throw(std::out_of_range) {
- if ( i > Y ) throw std::out_of_range("index out of range");
- return _pt[i];
- }
-
- ICoord operator[](Dim2 d) const throw() { return _pt[d]; }
- ICoord &operator[](Dim2 d) throw() { return _pt[d]; }
-
- IPoint &operator+=(IPoint const &o) {
- for ( unsigned i = 0 ; i < 2 ; ++i ) {
- _pt[i] += o._pt[i];
- }
- return *this;
- }
-
- IPoint &operator-=(IPoint const &o) {
- for ( unsigned i = 0 ; i < 2 ; ++i ) {
- _pt[i] -= o._pt[i];
- }
- return *this;
- }
-};
-
-
-} // namespace Geom
-
-#endif /* !SEEN_Geom_POINT_L_H */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/2geom/point.cpp b/src/2geom/point.cpp
index a9005ef61..cafc0fdba 100644
--- a/src/2geom/point.cpp
+++ b/src/2geom/point.cpp
@@ -1,3 +1,38 @@
+/**
+ * \file
+ * \brief Cartesian point / 2D vector and related operations
+ *//*
+ * Authors:
+ * Michael G. Sloan <mgsloan@gmail.com>
+ * Nathan Hurst <njh@njhurst.com>
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ *
+ * Copyright (C) 2006-2009 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
#include <assert.h>
#include <math.h>
#include <2geom/point.h>
@@ -14,8 +49,8 @@ namespace Geom {
* from the origin (point at 0,0) to the stored coordinates,
* and has methods implementing several vector operations (like length()).
*
- * \par Operator note
- * \par
+ * @par Operator note
+ * @par
* Most operators are provided by Boost operator helpers, so they are not visible in this class.
* If @a p, @a q, @a r denote points, @a s a floating-point scalar, and @a m a transformation matrix,
* then the following operations are available:
@@ -149,12 +184,11 @@ Point unit_vector(Point const &a)
* that the origin (0, 0), its negation is returned. You can check whether
* the points' vectors have the same direction (e.g. lie
* on the same line passing through the origin) using
- * @code abs(a).normalize() == abs(b).normalize() @endcode.
+ * @code abs(a).normalize() == abs(b).normalize() @endcode
* To check with some margin of error, use
- * @code are_near(abs(a).normalize(), abs(b).normalize()) @endcode.
+ * @code are_near(abs(a).normalize(), abs(b).normalize()) @endcode
* Although naively this should take the absolute value of each coordinate, such an operation
* is not very useful.
- * @return \f$p' = (p_X, -p_Y)\f$
* @relates Point */
Point abs(Point const &b)
{
@@ -178,8 +212,8 @@ Point &Point::operator*=(Affine const &m) {
return *this;
}
-/** @brief Snap the angle B - A - dir to miltiples of \f$2\pi/n\f$.
- * The 'dir' argument must be normalized (have an unit length), otherwise the result
+/** @brief Snap the angle B - A - dir to multiples of \f$2\pi/n\f$.
+ * The 'dir' argument must be normalized (have unit length), otherwise the result
* is undefined.
* @return Point with the same distance from A as B, with a snapped angle.
* @post distance(A, B) == distance(A, result)
diff --git a/src/2geom/point.h b/src/2geom/point.h
index 3c6e12eff..69da8a4ae 100644
--- a/src/2geom/point.h
+++ b/src/2geom/point.h
@@ -42,7 +42,7 @@
#include <boost/operators.hpp>
#include <2geom/forward.h>
#include <2geom/coord.h>
-#include <2geom/isnan.h> //temporary fix for isnan()
+#include <2geom/int-point.h>
#include <2geom/math-utils.h>
#include <2geom/utils.h>
@@ -61,8 +61,9 @@ class Point
> > > > > > > > > // this uses chaining so it looks weird, but works
{
Coord _pt[2];
-
public:
+ /// @name Create points
+ /// @{
/** Construct a point on the origin. */
Point()
{ _pt[X] = _pt[Y] = 0; }
@@ -71,6 +72,11 @@ public:
Point(Coord x, Coord y) {
_pt[X] = x; _pt[Y] = y;
}
+ /** Construct from integer point. */
+ Point(IntPoint const &p) {
+ _pt[X] = p[X];
+ _pt[Y] = p[Y];
+ }
Point(Point const &p) {
for (unsigned i = 0; i < 2; ++i)
_pt[i] = p._pt[i];
@@ -80,6 +86,23 @@ public:
_pt[i] = p._pt[i];
return *this;
}
+ /** @brief Construct a point from its polar coordinates.
+ * The angle is specified in radians, in the mathematical convention (increasing
+ * counter-clockwise from +X). */
+ static Point polar(Coord angle, Coord radius) {
+ Point ret(polar(angle));
+ ret *= radius;
+ return ret;
+ }
+ /** @brief Construct an unit vector from its angle.
+ * The angle is specified in radians, in the mathematical convention (increasing
+ * counter-clockwise from +X). */
+ static Point polar(Coord angle) {
+ Point ret;
+ sincos(angle, ret[Y], ret[X]);
+ return ret;
+ }
+ /// @}
/// @name Access the coordinates of a point
/// @{
@@ -157,57 +180,54 @@ public:
}
/// @}
- /// @name Various utilities
+ /// @name Conversion to integer points
/// @{
- /** @brief Lower the precision of the point.
- * This will round both coordinates to multiples of \f$10^p\f$. */
- void round (int p = 0) {
- _pt[X] = (Coord)(decimal_round((double)_pt[X], p));
- _pt[Y] = (Coord)(decimal_round((double)_pt[Y], p));
- return;
+ /** @brief Round to nearest integer coordinates. */
+ IntPoint round() const {
+ IntPoint ret(::round(_pt[X]), ::round(_pt[Y]));
+ return ret;
+ }
+ /** @brief Round coordinates downwards. */
+ IntPoint floor() const {
+ IntPoint ret(::floor(_pt[X]), ::floor(_pt[Y]));
+ return ret;
+ }
+ /** @brief Round coordinates upwards. */
+ IntPoint ceil() const {
+ IntPoint ret(::ceil(_pt[X]), ::ceil(_pt[Y]));
+ return ret;
}
+ /// @}
- /** @brief Check whether both coordinates are finite.
- * @return True if neither coordinate is infinite. */
+ /// @name Various utilities
+ /// @{
+ /** @brief Check whether both coordinates are finite. */
bool isFinite() const {
for ( unsigned i = 0 ; i < 2 ; ++i ) {
if(!IS_FINITE(_pt[i])) return false;
}
return true;
}
+ /** @brief Check whether both coordinates are zero. */
+ bool isZero() const {
+ return _pt[X] == 0 && _pt[Y] == 0;
+ }
+ /** @brief Check whether the length of the vector is close to 1. */
+ bool isNormalized(Coord eps=EPSILON) const {
+ return are_near(length(), 1.0, eps);
+ }
/** @brief Equality operator.
* This tests for exact identity (as opposed to are_near()). Note that due to numerical
* errors, this test might return false even if the points should be identical. */
bool operator==(const Point &in_pnt) const {
- return ((_pt[X] == in_pnt[X]) && (_pt[Y] == in_pnt[Y]));
+ return (_pt[X] == in_pnt[X]) && (_pt[Y] == in_pnt[Y]);
}
/** @brief Lexicographical ordering for points.
* Y coordinate is regarded as more significant. When sorting according to this
* ordering, the points will be sorted according to the Y coordinate, and within
* points with the same Y coordinate according to the X coordinate. */
bool operator<(const Point &p) const {
- return ( ( _pt[Y] < p[Y] ) ||
- (( _pt[Y] == p[Y] ) && ( _pt[X] < p[X] )));
- }
- /// @}
-
- /// @name Point factories
- /// @{
- /** @brief Construct a point from its polar coordinates.
- * The angle is specified in radians, in the mathematical convention (increasing
- * counter-clockwise from +X). */
- static Point polar(Coord angle, Coord radius) {
- Point ret(polar(angle));
- ret *= radius;
- return ret;
- }
- /** @brief Construct an unit vector from its angle.
- * The angle is specified in radians, in the mathematical convention (increasing
- * counter-clockwise from +X). */
- static Point polar(Coord angle) {
- Point ret;
- sincos(angle, ret[Y], ret[X]);
- return ret;
+ return _pt[Y] < p[Y] || (_pt[Y] == p[Y] && _pt[X] < p[X]);
}
/// @}
@@ -315,7 +335,7 @@ inline Point lerp(double const t, Point const &a, Point const &b)
* For perpendicular vectors, it is zero. For parallel ones, its absolute value is highest,
* and the sign depends on whether they point in the same direction (+) or opposite ones (-).
* @return \f$a \cdot b = a_X b_X + a_Y b_Y\f$.
- * @relates Point*/
+ * @relates Point */
inline Coord dot(Point const &a, Point const &b)
{
return a[0] * b[0] + a[1] * b[1];
@@ -349,8 +369,8 @@ Coord L1(Point const &p);
Coord LInfty(Point const &p);
bool is_zero(Point const &p);
bool is_unit_vector(Point const &p);
-extern double atan2(Point const &p);
-extern double angle_between(Point const &a, Point const &b);
+double atan2(Point const &p);
+double angle_between(Point const &a, Point const &b);
Point abs(Point const &b);
Point constrain_angle(Point const &A, Point const &B, unsigned int n = 4, Geom::Point const &dir = Geom::Point(1,0));
diff --git a/src/2geom/poly.h b/src/2geom/poly.h
index 3567bda6d..7d93d0a85 100644
--- a/src/2geom/poly.h
+++ b/src/2geom/poly.h
@@ -1,7 +1,7 @@
/**
* \file
- * \brief \todo brief description
- *
+ * \brief Polynomial in canonical (monomial) basis
+ *//*
* Authors:
* ? <?@?.?>
*
@@ -34,7 +34,6 @@
#ifndef LIB2GEOM_SEEN_POLY_H
#define LIB2GEOM_SEEN_POLY_H
-
#include <assert.h>
#include <vector>
#include <iostream>
diff --git a/src/2geom/quadtree.h b/src/2geom/quadtree.h
index 01ea33ed7..949a9b898 100644
--- a/src/2geom/quadtree.h
+++ b/src/2geom/quadtree.h
@@ -1,7 +1,7 @@
/**
* \file
- * \brief \todo brief description
- *
+ * \brief Quad tree data structure
+ *//*
* Authors:
* ? <?@?.?>
*
diff --git a/src/2geom/ray.h b/src/2geom/ray.h
index 638b86195..75cc72005 100644
--- a/src/2geom/ray.h
+++ b/src/2geom/ray.h
@@ -1,7 +1,7 @@
/**
* \file
- * \brief Infinite Straight Ray
- *
+ * \brief Infinite straight ray
+ *//*
* Copyright 2008 Marco Cecchetti <mrcekets at gmail.com>
*
* This library is free software; you can redistribute it and/or
@@ -35,6 +35,7 @@
#include <2geom/point.h>
#include <2geom/bezier-curve.h> // for LineSegment
#include <2geom/exception.h>
+#include <2geom/math-utils.h>
namespace Geom
{
@@ -49,171 +50,88 @@ namespace Geom
*/
class Ray {
private:
- Point m_origin;
- Point m_versor;
+ Point _origin;
+ Point _versor;
public:
- Ray()
- : m_origin(0,0), m_versor(1,0)
- {
- }
-
- Ray(Point const& _origin, Coord angle )
- : m_origin(_origin), m_versor(std::cos(angle), std::sin(angle))
- {
- }
-
- Ray(Point const& A, Point const& B)
- {
- setBy2Points(A, B);
- }
-
- Point origin() const
- {
- return m_origin;
- }
-
- Point versor() const
- {
- return m_versor;
- }
-
- void origin(Point const& _point)
- {
- m_origin = _point;
- }
-
- void versor(Point const& _versor)
- {
- m_versor = _versor;
- }
-
- Coord angle() const
- {
- double a = std::atan2(m_versor[Y], m_versor[X]);
- if (a < 0) a += 2*M_PI;
- return a;
- }
-
- void angle(Coord _angle)
- {
- m_versor[X] = std::cos(_angle);
- m_versor[Y] = std::sin(_angle);
- }
-
- void setBy2Points(Point const& A, Point const& B)
- {
- m_origin = A;
- m_versor = B - A;
- if ( are_near(m_versor, Point(0,0)) )
- m_versor = Point(0,0);
- else
- m_versor.normalize();
- }
-
- bool isDegenerate() const
- {
- return ( m_versor[X] == 0 && m_versor[Y] == 0 );
- }
-
- Point pointAt(Coord t) const
- {
- if (t < 0) THROW_RANGEERROR("Ray::pointAt, negative t value passed");
- return m_origin + m_versor * t;
- }
-
- Coord valueAt(Coord t, Dim2 d) const
- {
- if (t < 0)
- THROW_RANGEERROR("Ray::valueAt, negative t value passed");
- if (d < 0 || d > 1)
- THROW_RANGEERROR("Ray::valueAt, dimension argument out of range");
- return m_origin[d] + m_versor[d] * t;
- }
-
- std::vector<Coord> roots(Coord v, Dim2 d) const
- {
- if (d < 0 || d > 1)
- THROW_RANGEERROR("Ray::roots, dimension argument out of range");
- std::vector<Coord> result;
- if ( m_versor[d] != 0 )
- {
- double t = (v - m_origin[d]) / m_versor[d];
- if (t >= 0) result.push_back(t);
- }
- // TODO: else ?
- return result;
- }
-
- // require are_near(_point, *this)
- // on the contrary the result value is meaningless
- Coord timeAt(Point const& _point) const
- {
- Coord t;
- if ( m_versor[X] != 0 )
- {
- t = (_point[X] - m_origin[X]) / m_versor[X];
- }
- else if ( m_versor[Y] != 0 )
- {
- t = (_point[Y] - m_origin[Y]) / m_versor[Y];
- }
- else // degenerate case
- {
- t = 0;
- }
- return t;
- }
-
- Coord nearestPoint(Point const& _point) const
- {
- if ( isDegenerate() ) return 0;
- double t = dot( _point - m_origin, m_versor );
- if (t < 0) t = 0;
- return t;
- }
-
- Ray reverse() const
- {
- Ray result;
- result.origin(m_origin);
- result.versor(-m_versor);
- return result;
- }
-
- Curve* portion(Coord f, Coord t) const
- {
- LineSegment* seg = new LineSegment(pointAt(f), pointAt(t));
- return seg;
- }
-
- LineSegment segment(Coord f, Coord t) const
- {
- return LineSegment(pointAt(f), pointAt(t));
- }
-
- Ray transformed(Affine const& m) const
- {
- return Ray(m_origin * m, (m_origin + m_versor) * m);
- }
-}; // end class ray
+ Ray() : _origin(0,0), _versor(1,0) {}
+ Ray(Point const& origin, Coord angle)
+ : _origin(origin)
+ {
+ sincos(angle, _versor[Y], _versor[X]);
+ }
+ Ray(Point const& A, Point const& B) {
+ setPoints(A, B);
+ }
+ Point origin() const { return _origin; }
+ Point versor() const { return _versor; }
+ void setOrigin(Point const &o) { _origin = o; }
+ void setVersor(Point const& v) { _versor = v; }
+ Coord angle() const { return std::atan2(_versor[Y], _versor[X]); }
+ void setAngle(Coord a) { sincos(a, _versor[Y], _versor[X]); }
+ void setPoints(Point const &a, Point const &b) {
+ _origin = a;
+ _versor = b - a;
+ if (are_near(_versor, Point(0,0)) )
+ _versor = Point(0,0);
+ else
+ _versor.normalize();
+ }
+ bool isDegenerate() const {
+ return ( _versor[X] == 0 && _versor[Y] == 0 );
+ }
+ Point pointAt(Coord t) const {
+ return _origin + _versor * t;
+ }
+ Coord valueAt(Coord t, Dim2 d) const {
+ return _origin[d] + _versor[d] * t;
+ }
+ std::vector<Coord> roots(Coord v, Dim2 d) const {
+ std::vector<Coord> result;
+ if ( _versor[d] != 0 ) {
+ double t = (v - _origin[d]) / _versor[d];
+ if (t >= 0) result.push_back(t);
+ } else if (_versor[(d+1)%2] == v) {
+ THROW_INFINITESOLUTIONS();
+ }
+ return result;
+ }
+ Coord nearestPoint(Point const& point) const {
+ if ( isDegenerate() ) return 0;
+ double t = dot(point - _origin, _versor);
+ if (t < 0) t = 0;
+ return t;
+ }
+ Ray reverse() const {
+ Ray result;
+ result.setOrigin(_origin);
+ result.setVersor(-_versor);
+ return result;
+ }
+ Curve *portion(Coord f, Coord t) const {
+ return new LineSegment(pointAt(f), pointAt(t));
+ }
+ LineSegment segment(Coord f, Coord t) const {
+ return LineSegment(pointAt(f), pointAt(t));
+ }
+ Ray transformed(Affine const& m) const {
+ return Ray(_origin * m, (_origin + _versor) * m);
+ }
+}; // end class Ray
inline
-double distance(Point const& _point, Ray const& _ray)
-{
+double distance(Point const& _point, Ray const& _ray) {
double t = _ray.nearestPoint(_point);
return ::Geom::distance(_point, _ray.pointAt(t));
}
inline
-bool are_near(Point const& _point, Ray const& _ray, double eps = EPSILON)
-{
+bool are_near(Point const& _point, Ray const& _ray, double eps = EPSILON) {
return are_near(distance(_point, _ray), 0, eps);
}
inline
-bool are_same(Ray const& r1, Ray const& r2, double eps = EPSILON)
-{
+bool are_same(Ray const& r1, Ray const& r2, double eps = EPSILON) {
return are_near(r1.versor(), r2.versor(), eps)
&& are_near(r1.origin(), r2.origin(), eps);
}
@@ -221,15 +139,13 @@ bool are_same(Ray const& r1, Ray const& r2, double eps = EPSILON)
// evaluate the angle between r1 and r2 rotating r1 in cw or ccw direction on r2
// the returned value is an angle in the interval [0, 2PI[
inline
-double angle_between(Ray const& r1, Ray const& r2, bool cw = true)
-{
+double angle_between(Ray const& r1, Ray const& r2, bool cw = true) {
double angle = angle_between(r1.versor(), r2.versor());
if (angle < 0) angle += 2*M_PI;
if (!cw) angle = 2*M_PI - angle;
return angle;
}
-
inline
Ray make_angle_bisector_ray(Ray const& r1, Ray const& r2)
{
@@ -243,22 +159,17 @@ Ray make_angle_bisector_ray(Ray const& r1, Ray const& r2)
return Ray(r1.origin(), M);
}
-
} // end namespace Geom
-
-
-#endif /*_2GEOM_RAY_H_*/
-
+#endif // LIB2GEOM_SEEN_RAY_H
/*
Local Variables:
mode:c++
c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(substatement-open . 0))
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
indent-tabs-mode:nil
- c-brace-offset:0
fill-column:99
End:
- vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/2geom/rect.cpp b/src/2geom/rect.cpp
new file mode 100644
index 000000000..0cb842d29
--- /dev/null
+++ b/src/2geom/rect.cpp
@@ -0,0 +1,98 @@
+/* Axis-aligned rectangle
+ *
+ * Authors:
+ * Michael Sloan <mgsloan@gmail.com>
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ * Copyright 2007-2011 Authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#include <2geom/rect.h>
+
+namespace Geom {
+
+/** @brief Transform the rectangle by an affine.
+ * The result of the transformation might not be axis-aligned. The return value
+ * of this operation will be the smallest axis-aligned rectangle containing
+ * all points of the true result. */
+Rect &Rect::operator*=(Affine const &m) {
+ Point pts[4];
+ for (unsigned i=0; i<4; ++i) pts[i] = corner(i) * m;
+ Coord minx = std::min(std::min(pts[0][X], pts[1][X]), std::min(pts[2][X], pts[3][X]));
+ Coord miny = std::min(std::min(pts[0][Y], pts[1][Y]), std::min(pts[2][Y], pts[3][Y]));
+ Coord maxx = std::max(std::max(pts[0][X], pts[1][X]), std::max(pts[2][X], pts[3][X]));
+ Coord maxy = std::max(std::max(pts[0][Y], pts[1][Y]), std::max(pts[2][Y], pts[3][Y]));
+ f[X].setMin(minx); f[X].setMax(maxx);
+ f[Y].setMin(miny); f[Y].setMax(maxy);
+ return *this;
+}
+
+Coord distanceSq(Point const &p, Rect const &rect)
+{
+ double dx = 0, dy = 0;
+ if ( p[X] < rect.left() ) {
+ dx = p[X] - rect.left();
+ } else if ( p[X] > rect.right() ) {
+ dx = rect.right() - p[X];
+ }
+ if (p[Y] < rect.top() ) {
+ dy = rect.top() - p[Y];
+ } else if ( p[Y] > rect.bottom() ) {
+ dy = p[Y] - rect.bottom();
+ }
+ return dx*dx+dy*dy;
+}
+
+/** @brief Returns the smallest distance between p and rect.
+ * @relates Rect */
+Coord distance(Point const &p, Rect const &rect)
+{
+ // copy of distanceSq, because we need to use hypot()
+ double dx = 0, dy = 0;
+ if ( p[X] < rect.left() ) {
+ dx = p[X] - rect.left();
+ } else if ( p[X] > rect.right() ) {
+ dx = rect.right() - p[X];
+ }
+ if (p[Y] < rect.top() ) {
+ dy = rect.top() - p[Y];
+ } else if ( p[Y] > rect.bottom() ) {
+ dy = p[Y] - rect.bottom();
+ }
+ return hypot(dx, dy);
+}
+
+} // namespace Geom
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :
diff --git a/src/2geom/rect.h b/src/2geom/rect.h
index 65bb1bb76..e9f6cbeb7 100644
--- a/src/2geom/rect.h
+++ b/src/2geom/rect.h
@@ -2,7 +2,10 @@
* \file
* \brief Axis-aligned rectangle
*//*
- * Copyright 2007 Michael Sloan <mgsloan@gmail.com>
+ * Authors:
+ * Michael Sloan <mgsloan@gmail.com>
+ * Krzysztof KosiƄski <tweenk.pl@gmail.com>
+ * Copyright 2007-2011 Authors
*
* This library is free software; you can redistribute it and/or
* modify it either under the terms of the GNU Lesser General Public
@@ -34,48 +37,42 @@
* MenTaLguY <mental@rydia.net>
*/
-#include <2geom/d2.h>
-
-#ifndef LIB2GEOM_RECT_H
-#define LIB2GEOM_RECT_H
+#ifndef LIB2GEOM_SEEN_RECT_H
+#define LIB2GEOM_SEEN_RECT_H
+#include <boost/optional.hpp>
#include <2geom/affine.h>
-#include <boost/optional/optional.hpp>
+#include <2geom/interval.h>
+#include <2geom/int-rect.h>
namespace Geom {
/**
- * @brief Axis-aligned, non-empty rectangle - convenience typedef
+ * @brief Axis-aligned rectangle that can be empty.
* @ingroup Primitives
*/
-typedef D2<Interval> Rect;
-class OptRect;
-
-inline Rect unify(Rect const &, Rect const &);
+typedef GenericOptRect<Coord> OptRect;
/**
* @brief Axis aligned, non-empty rectangle.
* @ingroup Primitives
*/
-template<>
-class D2<Interval> {
-private:
- Interval f[2];
+class Rect
+ : public GenericRect<Coord>
+ , boost::multipliable< Rect, Affine >
+{
+ typedef GenericRect<Coord> Base;
public:
/// @name Create rectangles.
/// @{
/** @brief Create a rectangle that contains only the point at (0,0). */
- D2<Interval>() { f[X] = f[Y] = Interval(); }
+ Rect() {}
/** @brief Create a rectangle from X and Y intervals. */
- D2<Interval>(Interval const &a, Interval const &b) {
- f[X] = a;
- f[Y] = b;
- }
+ Rect(Interval const &a, Interval const &b) : Base(a,b) {}
/** @brief Create a rectangle from two points. */
- D2<Interval>(Point const & a, Point const & b) {
- f[X] = Interval(a[X], b[X]);
- f[Y] = Interval(a[Y], b[Y]);
- }
+ Rect(Point const &a, Point const &b) : Base(a,b) {}
+ Rect(Coord x0, Coord y0, Coord x1, Coord y1) : Base(x0, y0, x1, y1) {}
+ Rect(Base const &b) : Base(b) {}
/** @brief Create a rectangle from a range of points.
* The resulting rectangle will contain all ponts from the range.
* The return type of iterators must be convertible to Point.
@@ -85,12 +82,7 @@ public:
* @return Rectangle that contains all points from [start, end). */
template <typename InputIterator>
static Rect from_range(InputIterator start, InputIterator end) {
- assert(start != end);
- Point p1 = *start++;
- Rect result(p1, p1);
- for (; start != end; ++start) {
- result.expandTo(*start);
- }
+ Rect result = Base::from_range(start, end);
return result;
}
/** @brief Create a rectangle from a C-style array of points it should contain. */
@@ -98,264 +90,97 @@ public:
Rect result = Rect::from_range(c, c+n);
return result;
}
+ static Rect from_xywh(Coord x, Coord y, Coord w, Coord h) {
+ Rect result = Base::from_xywh(x, y, w, h);
+ return result;
+ }
+ static Rect from_xywh(Point const &o, Point const &dim) {
+ Rect result = Base::from_xywh(o, dim);
+ return result;
+ }
/// @}
/// @name Inspect dimensions.
/// @{
- Interval& operator[](unsigned i) { return f[i]; }
- Interval const & operator[](unsigned i) const { return f[i]; }
-
- Point min() const { return Point(f[X].min(), f[Y].min()); }
- Point max() const { return Point(f[X].max(), f[Y].max()); }
- /** @brief Return the n-th corner of the rectangle.
- * If the Y axis grows upwards, this returns corners in clockwise order
- * starting from the lower left. If Y grows downwards, it returns the corners
- * in counter-clockwise order starting from the upper left. */
- Point corner(unsigned i) const {
- switch(i % 4) {
- case 0: return Point(f[X].min(), f[Y].min());
- case 1: return Point(f[X].max(), f[Y].min());
- case 2: return Point(f[X].max(), f[Y].max());
- default: return Point(f[X].min(), f[Y].max());
- }
- }
-
- //We should probably remove these - they're coord sys gnostic
- /** @brief Return top coordinate of the rectangle (+Y is downwards). */
- Coord top() const { return f[Y].min(); }
- /** @brief Return bottom coordinate of the rectangle (+Y is downwards). */
- Coord bottom() const { return f[Y].max(); }
- /** @brief Return leftmost coordinate of the rectangle (+X is to the right). */
- Coord left() const { return f[X].min(); }
- /** @brief Return rightmost coordinate of the rectangle (+X is to the right). */
- Coord right() const { return f[X].max(); }
-
- Coord width() const { return f[X].extent(); }
- Coord height() const { return f[Y].extent(); }
-
- /** @brief Get rectangle's width and height as a point.
- * @return Point with X coordinate corresponding to the width and the Y coordinate
- * corresponding to the height of the rectangle. */
- Point dimensions() const { return Point(f[X].extent(), f[Y].extent()); }
- Point midpoint() const { return Point(f[X].middle(), f[Y].middle()); }
-
-/**
- * \brief Compute the area of this rectangle.
- *
- * Note that a zero area rectangle is not empty - just as the interval [0,0] contains one point, the rectangle [0,0] x [0,0] contains 1 point and no area.
- * \retval For a valid return value, the rect must be tested for emptyness first.
- */
- /** @brief Compute rectangle's area. */
- Coord area() const { return f[X].extent() * f[Y].extent(); }
/** @brief Check whether the rectangle has zero area up to specified tolerance.
* @param eps Maximum value of the area to consider empty
* @return True if rectangle has an area smaller than tolerance, false otherwise */
- bool hasZeroArea(double eps = EPSILON) const { return (area() <= eps); }
-
- /** @brief Get the larger extent (width or height) of the rectangle. */
- Coord maxExtent() const { return std::max(f[X].extent(), f[Y].extent()); }
- /** @brief Get the smaller extent (width or height) of the rectangle. */
- Coord minExtent() const { return std::min(f[X].extent(), f[Y].extent()); }
+ bool hasZeroArea(Coord eps = EPSILON) const { return (area() <= eps); }
/// @}
/// @name Test other rectangles and points for inclusion.
/// @{
- /** @brief Check whether the rectangles have any common points. */
- bool intersects(Rect const &r) const {
- return f[X].intersects(r[X]) && f[Y].intersects(r[Y]);
- }
/** @brief Check whether the interiors of the rectangles have any common points. */
bool interiorIntersects(Rect const &r) const {
return f[X].interiorIntersects(r[X]) && f[Y].interiorIntersects(r[Y]);
}
- /** @brief Check whether the rectangle includes all points in the given rectangle. */
- bool contains(Rect const &r) const {
- return f[X].contains(r[X]) && f[Y].contains(r[Y]);
- }
/** @brief Check whether the interior includes all points in the given rectangle.
* Interior of the rectangle is the entire rectangle without its borders. */
bool interiorContains(Rect const &r) const {
return f[X].interiorContains(r[X]) && f[Y].interiorContains(r[Y]);
}
-
- /** @brief Check whether the rectangles have any common points.
- * A non-empty rectangle will not intersect empty rectangles. */
- inline bool intersects(OptRect const &r) const;
- /** @brief Check whether the rectangle includes all points in the given rectangle.
- * A non-empty rectangle will contain any empty rectangle. */
- inline bool contains(OptRect const &r) const;
- /** @brief Check whether the interior includes all points in the given rectangle.
- * The interior of a non-empty rectangle will contain any empty rectangle. */
inline bool interiorContains(OptRect const &r) const;
+ /// @}
- /** @brief Check whether the given point is within the rectangle. */
- bool contains(Point const &p) const {
- return f[X].contains(p[X]) && f[Y].contains(p[Y]);
+ /// @name Rounding to integer coordinates
+ /// @{
+ /** @brief Return the smallest integer rectangle which contains this one. */
+ IntRect roundOutwards() const {
+ IntRect ir(f[X].roundOutwards(), f[Y].roundOutwards());
+ return ir;
}
- /** @brief Check whether the given point is in the rectangle's interior.
- * This means the point must lie within the rectangle but not on its border. */
- bool interiorContains(Point const &p) const {
- return f[X].interiorContains(p[X]) && f[Y].interiorContains(p[Y]);
+ /** @brief Return the largest integer rectangle which is contained in this one. */
+ OptIntRect roundInwards() const {
+ OptIntRect oir(f[X].roundInwards(), f[Y].roundInwards());
+ return oir;
}
/// @}
- /// @name Modify the rectangle.
+ /// @name Operators
/// @{
- /** @brief Enlarge the rectangle to contain the given point. */
- void expandTo(Point p) {
- f[X].expandTo(p[X]); f[Y].expandTo(p[Y]);
- }
- /** @brief Enlarge the rectangle to contain the given rectangle. */
- void unionWith(Rect const &b) {
- f[X].unionWith(b[X]); f[Y].unionWith(b[Y]);
- }
- /** @brief Enlarge the rectangle to contain the given rectangle.
- * Unioning with an empty rectangle results in no changes. */
- void unionWith(OptRect const &b);
-
- //TODO: figure out how these work with negative values and OptRect
- /** @brief Expand the rectangle in both directions by the specified amount.
- * Note that this is different from scaling. Negative values wil shrink the
- * rectangle. If <code>-amount</code> is larger than
- * half of the width, the X interval will contain only the X coordinate
- * of the midpoint; same for height. */
- void expandBy(Coord amount) {
- f[X].expandBy(amount); f[Y].expandBy(amount);
- }
- /** @brief Expand the rectangle by the coordinates of the given point.
- * This will expand the width by the X coordinate of the point in both directions
- * and the height by Y coordinate of the point. Negative coordinate values will
- * shrink the rectangle. If <code>-p[X]</code> is larger than half of the width,
- * the X interval will contain only the X coordinate of the midpoint; same for height. */
- void expandBy(Point const p) {
- f[X].expandBy(p[X]); f[Y].expandBy(p[Y]);
- }
+ Rect &operator*=(Affine const &m);
/// @}
};
-inline Rect unify(Rect const & a, Rect const & b) {
- return Rect(unify(a[X], b[X]), unify(a[Y], b[Y]));
+Coord distanceSq(Point const &p, Rect const &rect);
+Coord distance(Point const &p, Rect const &rect);
+
+inline bool Rect::interiorContains(OptRect const &r) const {
+ return !r || interiorContains(static_cast<Rect const &>(*r));
}
-inline Rect union_list(std::vector<Rect> const &r) {
- if(r.empty()) return Rect(Interval(0,0), Interval(0,0));
- Rect ret = r[0];
- for(unsigned i = 1; i < r.size(); i++)
- ret.unionWith(r[i]);
+// the functions below do not work when defined generically
+inline OptRect operator&(Rect const &a, Rect const &b) {
+ OptRect ret(a);
+ ret.intersectWith(b);
return ret;
}
-
-inline
-Coord distanceSq( Point const& p, Rect const& rect )
-{
- double dx = 0, dy = 0;
- if ( p[X] < rect.left() )
- {
- dx = p[X] - rect.left();
- }
- else if ( p[X] > rect.right() )
- {
- dx = rect.right() - p[X];
- }
- if ( p[Y] < rect.top() )
- {
- dy = rect.top() - p[Y];
- }
- else if ( p[Y] > rect.bottom() )
- {
- dy = p[Y] - rect.bottom();
- }
- return dx*dx + dy*dy;
+inline OptRect intersect(Rect const &a, Rect const &b) {
+ return a & b;
}
-
-/**
- * Returns the smallest distance between p and rect.
- */
-inline
-Coord distance( Point const& p, Rect const& rect )
-{
- return std::sqrt(distanceSq(p, rect));
+inline OptRect intersect(OptRect const &a, OptRect const &b) {
+ return a & b;
}
-
-/**
- * @brief Axis-aligned rectangle that can be empty.
- * @ingroup Primitives
- */
-class OptRect : public boost::optional<Rect> {
-public:
- OptRect() : boost::optional<Rect>() {};
- OptRect(Rect const &a) : boost::optional<Rect>(a) {};
-
- /**
- * Creates an empty OptRect when one of the argument intervals is empty.
- */
- OptRect(OptInterval const &x_int, OptInterval const &y_int) {
- if (x_int && y_int) {
- *this = Rect(*x_int, *y_int);
- }
- // else, stay empty.
- }
-
- /** @brief Check for emptiness. */
- inline bool isEmpty() const { return (*this == false); };
-
- bool intersects(Rect const &r) const { return r.intersects(*this); }
- bool contains(Rect const &r) const { return *this && (*this)->contains(r); }
- bool interiorContains(Rect const &r) const { return *this && (*this)->interiorContains(r); }
-
- bool intersects(OptRect const &r) const { return *this && (*this)->intersects(r); }
- bool contains(OptRect const &r) const { return *this && (*this)->contains(r); }
- bool interiorContains(OptRect const &r) const { return *this && (*this)->interiorContains(r); }
-
- bool contains(Point const &p) const { return *this && (*this)->contains(p); }
- bool interiorContains(Point const &p) const { return *this && (*this)->contains(p); }
-
- inline void unionWith(OptRect const &b) {
- if (*this) { // check that we are not empty
- (*this)->unionWith(b);
- } else {
- *this = b;
- }
- }
-};
-
-
-/**
- * Returns the smallest rectangle that encloses both rectangles.
- * An empty argument is assumed to be an empty rectangle
- */
-inline OptRect unify(OptRect const & a, OptRect const & b) {
- if (!a) {
- return b;
- } else if (!b) {
- return a;
- } else {
- return unify(*a, *b);
- }
+inline Rect unify(Rect const &a, Rect const &b) {
+ return a | b;
}
-
-inline OptRect intersect(Rect const & a, Rect const & b) {
- return OptRect(intersect(a[X], b[X]), intersect(a[Y], b[Y]));
+inline OptRect unify(OptRect const &a, OptRect const &b) {
+ return a | b;
}
-inline void Rect::unionWith(OptRect const &b) {
- if (b) {
- unionWith(*b);
- }
-}
-inline bool Rect::intersects(OptRect const &r) const {
- return r && intersects(*r);
-}
-inline bool Rect::contains(OptRect const &r) const {
- return !r || contains(*r);
-}
-inline bool Rect::interiorContains(OptRect const &r) const {
- return !r || interiorContains(*r);
+/** @brief Union a list of rectangles
+ * @deprecated Use OptRect::from_range instead */
+inline Rect union_list(std::vector<Rect> const &r) {
+ if(r.empty()) return Rect(Interval(0,0), Interval(0,0));
+ Rect ret = r[0];
+ for(unsigned i = 1; i < r.size(); i++)
+ ret.unionWith(r[i]);
+ return ret;
}
} // end namespace Geom
-#endif //_2GEOM_RECT
+#endif // LIB2GEOM_SEEN_RECT_H
/*
Local Variables:
diff --git a/src/2geom/region.h b/src/2geom/region.h
index e23d6a158..06a4f63e9 100644
--- a/src/2geom/region.h
+++ b/src/2geom/region.h
@@ -1,7 +1,7 @@
/**
* \file
- * \brief \todo brief description
- *
+ * \brief Uncrossed path for boolean algorithms
+ *//*
* Authors:
* ? <?@?.?>
*
diff --git a/src/2geom/sbasis-2d.h b/src/2geom/sbasis-2d.h
index f1218b028..00429e259 100644
--- a/src/2geom/sbasis-2d.h
+++ b/src/2geom/sbasis-2d.h
@@ -1,7 +1,7 @@
/**
* \file
- * \brief \todo brief description
- *
+ * \brief Obsolete 2D SBasis function class
+ *//*
* Authors:
* Nathan Hurst <?@?.?>
* JFBarraud <?@?.?>
diff --git a/src/2geom/sbasis-curve.h b/src/2geom/sbasis-curve.h
index 22fe4fc1f..554b702e6 100644
--- a/src/2geom/sbasis-curve.h
+++ b/src/2geom/sbasis-curve.h
@@ -33,8 +33,8 @@
* the specific language governing rights and limitations.
*/
-#ifndef _2GEOM_SBASIS_CURVE_H_
-#define _2GEOM_SBASIS_CURVE_H_
+#ifndef LIB2GEOM_SEEN_SBASIS_CURVE_H
+#define LIB2GEOM_SEEN_SBASIS_CURVE_H
#include <2geom/curve.h>
#include <2geom/nearest-point.h>
@@ -45,24 +45,45 @@ namespace Geom
/** @brief Symmetric power basis curve.
*
- * Symmetric power basis (S-basis for short) polynomials are a versatile numeric representation
- * of arbitrary continuous curves. They combine the properties of Bezier curves
- * (geometric interpretation of parameters, numerical stability near ends of the curve)
- * and the monomial basis (fast evaluation). They are the main representation of curves
+ * Symmetric power basis (S-basis for short) polynomials are a versatile numeric
+ * representation of arbitrary continuous curves. They are the main representation of curves
* in 2Geom.
*
+ * S-basis is defined for odd degrees and composed of the following polynomials:
+ * \f{align*}{
+ P_k^0(t) &= t^k (1-t)^{k+1} \\
+ P_k^1(t) &= t^{k+1} (1-t)^k \f}
+ * This can be understood more easily with the help of the chart below. Each square
+ * represents a product of a specific number of \f$t\f$ and \f$(1-t)\f$ terms. Red dots
+ * are the canonical (monomial) basis, the green dots are the Bezier basis, and the blue
+ * dots are the S-basis, all of them of degree 7.
+ *
+ * @image html sbasis.png "Illustration of the monomial, Bezier and symmetric power bases"
+ *
+ * The S-Basis has several important properties:
+ * - S-basis polynomials are closed under multiplication.
+ * - Evaluation is fast, using a modified Horner scheme.
+ * - Degree change is as trivial as in the monomial basis. To elevate, just add extra
+ * zero coefficients. To reduce the degree, truncate the terms in the highest powers.
+ * Compare this with Bezier curves, where degree change is complicated.
+ * - Conversion between S-basis and Bezier basis is numerically stable.
+ *
+ * More in-depth information can be found in the following paper:
+ * J Sanchez-Reyes, "The symmetric analogue of the polynomial power basis".
+ * ACM Transactions on Graphics, Vol. 16, No. 3, July 1997, pages 319--357.
+ * http://portal.acm.org/citation.cfm?id=256162
+ *
* @ingroup Curves
*/
class SBasisCurve : public Curve {
-
private:
- SBasisCurve();
D2<SBasis> inner;
public:
explicit SBasisCurve(D2<SBasis> const &sb) : inner(sb) {}
explicit SBasisCurve(Curve const &other) : inner(other.toSBasis()) {}
+#ifndef DOXYGEN_SHOULD_SKIP_THIS
virtual Curve *duplicate() const { return new SBasisCurve(*this); }
virtual Point initialPoint() const { return inner.at0(); }
virtual Point finalPoint() const { return inner.at1(); }
@@ -104,16 +125,12 @@ public:
virtual int degreesOfFreedom() const {
return inner[0].degreesOfFreedom() + inner[1].degreesOfFreedom();
}
+#endif
};
-
} // end namespace Geom
-
-#endif // _2GEOM_SBASIS_CURVE_H_
-
-
-
+#endif // LIB2GEOM_SEEN_SBASIS_CURVE_H
/*
Local Variables:
diff --git a/src/2geom/sbasis-to-bezier.h b/src/2geom/sbasis-to-bezier.h
index 5b88a40fa..819aa87d6 100644
--- a/src/2geom/sbasis-to-bezier.h
+++ b/src/2geom/sbasis-to-bezier.h
@@ -1,7 +1,7 @@
/**
* \file
- * \brief \todo brief description
- *
+ * \brief Conversion between SBasis and Bezier basis polynomials
+ *//*
* Authors:
* ? <?@?.?>
*
diff --git a/src/2geom/sbasis.cpp b/src/2geom/sbasis.cpp
index e313ad08d..89640af5c 100644
--- a/src/2geom/sbasis.cpp
+++ b/src/2geom/sbasis.cpp
@@ -34,7 +34,7 @@
#include <cmath>
#include <2geom/sbasis.h>
-#include <2geom/isnan.h>
+#include <2geom/math-utils.h>
namespace Geom{
diff --git a/src/2geom/sbasis.h b/src/2geom/sbasis.h
index b1b0b6c2a..7a7e33fe4 100644
--- a/src/2geom/sbasis.h
+++ b/src/2geom/sbasis.h
@@ -345,7 +345,7 @@ SBasis compose_inverse(SBasis const &f, SBasis const &g, unsigned order=2, doubl
\relates SBasis
*/
inline SBasis portion(const SBasis &t, double from, double to) { return compose(t, Linear(from, to)); }
-inline SBasis portion(const SBasis &t, Interval ivl) { return compose(t, Linear(ivl[0], ivl[1])); }
+inline SBasis portion(const SBasis &t, Interval ivl) { return compose(t, Linear(ivl.min(), ivl.max())); }
// compute f(g)
inline SBasis
diff --git a/src/2geom/sturm.h b/src/2geom/sturm.h
deleted file mode 100644
index 4fef1b954..000000000
--- a/src/2geom/sturm.h
+++ /dev/null
@@ -1,70 +0,0 @@
-#ifndef LIB2GEOM_STURM_HEADER
-#define LIB2GEOM_STURM_HEADER
-
-#include <2geom/poly.h>
-#include <2geom/utils.h>
-
-namespace Geom {
-
-class sturm : public std::vector<Poly>{
-public:
- sturm(Poly const &X) {
- push_back(X);
- push_back(derivative(X));
- Poly Xi = back();
- Poly Xim1 = X;
- std::cout << "sturm:\n" << Xim1 << std::endl;
- std::cout << Xi << std::endl;
- while(Xi.size() > 1) {
- Poly r;
- divide(Xim1, Xi, r);
- std::cout << r << std::endl;
- assert(r.size() < Xi.size());
- Xim1 = Xi;
- Xi = -r;
- assert(Xim1.size() > Xi.size());
- push_back(Xi);
- }
- }
-
- unsigned count_signs(double t) {
- unsigned n_signs = 0;/* Number of sign-changes */
- const double big = 1e20; // a number such that practical polys would overflow on evaluation
- if(t >= big) {
- int old_sign = sgn((*this)[0].back());
- for (unsigned i = 1; i < size(); i++) {
- int sign = sgn((*this)[i].back());
- if (sign != old_sign)
- n_signs++;
- old_sign = sign;
- }
- } else {
- int old_sign = sgn((*this)[0].eval(t));
- for (unsigned i = 1; i < size(); i++) {
- int sign = sgn((*this)[i].eval(t));
- if (sign != old_sign)
- n_signs++;
- old_sign = sign;
- }
- }
- return n_signs;
- }
-
- unsigned n_roots_between(double l, double r) {
- return count_signs(l) - count_signs(r);
- }
-};
-
-} //namespace Geom
-
-#endif
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/2geom/svg-elliptical-arc.h b/src/2geom/svg-elliptical-arc.h
index 79497cdb3..ba0a18257 100644
--- a/src/2geom/svg-elliptical-arc.h
+++ b/src/2geom/svg-elliptical-arc.h
@@ -1,7 +1,6 @@
/**
* \file
* \brief SVG 1.1-compliant elliptical arc curve
- *
*//*
* Authors:
* MenTaLguY <mental@rydia.net>
@@ -35,8 +34,8 @@
*/
-#ifndef _2GEOM_SVG_ELLIPTICAL_ARC_H_
-#define _2GEOM_SVG_ELLIPTICAL_ARC_H_
+#ifndef LIB2GEOM_SEEN_SVG_ELLIPTICAL_ARC_H
+#define LIB2GEOM_SEEN_SVG_ELLIPTICAL_ARC_H
#include <2geom/curve.h>
#include <2geom/angle.h>
@@ -49,8 +48,7 @@
#include <2geom/numeric/fitting-model.h>
#include <algorithm>
-namespace Geom
-{
+namespace Geom {
class SVGEllipticalArc : public EllipticalArc {
public:
@@ -267,13 +265,9 @@ class make_elliptical_arc
bool svg_compliant;
};
-
} // end namespace Geom
-
-
-
-#endif /* _2GEOM_SVG_ELLIPTICAL_ARC_H_ */
+#endif // LIB2GEOM_SEEN_SVG_ELLIPTICAL_ARC_H
/*
Local Variables:
diff --git a/src/2geom/sweep.h b/src/2geom/sweep.h
index 1c73efee0..91371e6fb 100644
--- a/src/2geom/sweep.h
+++ b/src/2geom/sweep.h
@@ -1,7 +1,7 @@
/**
* \file
- * \brief \todo brief description
- *
+ * \brief Sweepline intersection of groups of rectangles
+ *//*
* Authors:
* ? <?@?.?>
*
diff --git a/src/2geom/toposweep.cpp b/src/2geom/toposweep.cpp
new file mode 100644
index 000000000..cfb91857c
--- /dev/null
+++ b/src/2geom/toposweep.cpp
@@ -0,0 +1,663 @@
+#include <2geom/toposweep.h>
+
+#include <2geom/path-intersection.h>
+#include <2geom/basic-intersection.h>
+
+//using namespace Geom;
+
+namespace Geom {
+
+TopoGraph::Edge &TopoGraph::Vertex::operator[](unsigned ix) {
+ ix %= degree();
+ return ix < enters.size() ? enters[ix] : exits[ix - enters.size()];
+}
+
+TopoGraph::Edge TopoGraph::Vertex::operator[](unsigned ix) const {
+ ix %= degree();
+ return ix < enters.size() ? enters[ix] : exits[ix - enters.size()];
+}
+
+void TopoGraph::Vertex::erase(unsigned ix) {
+ ix %= degree();
+ if(ix < enters.size())
+ enters.erase(enters.begin() + ix);
+ else
+ exits.erase(exits.begin() + (ix - enters.size()));
+}
+
+void TopoGraph::Vertex::insert(unsigned ix, Edge v) {
+ ix %= degree();
+ if(ix < enters.size())
+ enters.insert(enters.begin() + ix, v);
+ else
+ exits.insert(exits.begin() + (ix - enters.size()), v);
+}
+
+unsigned TopoGraph::Vertex::find_section(boost::shared_ptr<Section> section) const {
+ unsigned i = 0;
+ for(; i < degree(); i++)
+ if((*this)[i].section == section) return i;
+ return i;
+}
+
+TopoGraph::Edge TopoGraph::remove_edge(unsigned ix, unsigned jx) {
+ Vertex &v = vertices[ix];
+ if(v.degree()) {
+ jx %= v.degree();
+ Edge &ret = v[jx];
+ v.erase(jx);
+ v = vertices[ret.other];
+ if(v.degree()) {
+ v.erase(v.find_section(ret.section));
+ return ret;
+ }
+ }
+ assert(0);
+}
+
+void TopoGraph::cannonize() {
+ std::vector<unsigned> vix;
+ unsigned ix = 0;
+ for(unsigned i = 0; i < vertices.size(); i++) {
+ vix.push_back(ix);
+ if(vertices[i].degree() != 0) vertices[ix++] = vertices[i];
+ }
+
+ for(unsigned i = 0; i < ix; i++)
+ for(unsigned j = 0; j < vertices[i].degree(); j++)
+ vertices[i][j].other = vix[vertices[i][j].other];
+}
+
+
+void TopoGraph::assert_invariants() const {
+ for(unsigned i = 0; i < vertices.size(); i++) {
+ for(unsigned j = 0; j < vertices[i].degree(); j++) {
+ Edge e = vertices[i][j];
+ assert(e.other != i);
+ assert(are_near(e.section->fp, vertices[i].avg, tol) || are_near(e.section->tp, vertices[i].avg, tol));
+ assert(!are_near(e.section->fp, e.section->tp, tol));
+ assert(e.section.get());
+ unsigned oix = vertices[e.other].find_section(e.section);
+ assert(oix != vertices[e.other].degree());
+ }
+ }
+}
+
+//near predicate utilized in process_splits
+template<typename T>
+struct NearPredicate { bool operator()(T x, T y) { return are_near(x, y); } };
+
+// ensures that f and t are elements of a vector, sorts and uniqueifies
+// also asserts that no values fall outside of f and t
+// if f is greater than t, the sort is in reverse
+void process_splits(std::vector<double> &splits, double f, double t) {
+ splits.push_back(f);
+ std::sort(splits.begin(), splits.end());
+ while(are_near(splits.back(), t)) splits.erase(splits.end() - 1);
+ splits.push_back(t);
+ if(f > t) std::reverse(splits.begin(), splits.end());
+
+ //remove any splits which fall outside t / f
+ while(!splits.empty() && splits.front() != f) splits.erase(splits.begin());
+ while(!splits.empty() && splits.back() != t) splits.erase(splits.end() - 1);
+
+ std::vector<double>::iterator end = std::unique(splits.begin(), splits.end(), NearPredicate<double>());
+ splits.resize(end - splits.begin());
+}
+
+// A little sugar for appending a list to another
+template<typename T>
+void concatenate(T &a, T const &b) { a.insert(a.end(), b.begin(), b.end()); }
+
+//returns a list of monotonic sections of a path
+//TODO: handle saddle points
+std::vector<boost::shared_ptr<Section> > mono_sections(PathVector const &ps, Dim2 d) {
+ std::vector<boost::shared_ptr<Section> > monos;
+ for(unsigned i = 0; i < ps.size(); i++) {
+ //TODO: necessary? can we have empty paths?
+ if(ps[i].size()) {
+ for(unsigned j = 0; j < ps[i].size(); j++) {
+ //find the points of 0 derivative
+ Curve* deriv = ps[i][j].derivative();
+ std::vector<double> splits = deriv->roots(0, X);
+ concatenate(splits, deriv->roots(0, Y));
+ delete deriv;
+ process_splits(splits, 0, 1);
+ //split on points of 0 derivative
+ for(unsigned k = 1; k < splits.size(); k++)
+ monos.push_back(boost::shared_ptr<Section>(new Section(CurveIx(i,j), splits[k-1], splits[k], ps, d)));
+ }
+ }
+ }
+ return monos;
+}
+
+//finds the t-value on a section, which corresponds to a particular horizontal or vertical line
+//d indicates the dimension along which the roots is performed.
+//-1 is returned if no root is found
+double section_root(Section const &s, PathVector const &ps, double v, Dim2 d) {
+ std::vector<double> roots = s.curve.get(ps).roots(v, d);
+ for(unsigned j = 0; j < roots.size(); j++)
+ if(Interval(s.f, s.t).contains(roots[j])) return roots[j];
+ return -1;
+}
+
+bool SectionSorter::section_order(Section const &a, double at, Section const &b, double bt) const {
+ Point ap = a.curve.get(ps).pointAt(at);
+ Point bp = b.curve.get(ps).pointAt(bt);
+ if(are_near(ap[dim], bp[dim], tol)) {
+ // since the sections are monotonic, if the endpoints are on opposite sides of this
+ // coincidence, the order is determinable
+ if(a.tp[dim] < ap[dim] && b.tp[dim] > bp[dim]) return true;
+ if(a.tp[dim] > ap[dim] && b.tp[dim] < bp[dim]) return false;
+ //TODO: sampling / higher derivatives when unit tangents match
+ Point ad = a.curve.get(ps).unitTangentAt(a.f);
+ Point bd = b.curve.get(ps).unitTangentAt(b.f);
+ // tangent can point backwards
+ if(ad[1-dim] < 0) ad = -ad;
+ if(bd[1-dim] < 0) bd = -bd;
+ return ad[dim] < bd[dim];
+ }
+ return ap[dim] < bp[dim];
+}
+
+bool SectionSorter::operator()(Section const &a, Section const &b) const {
+ if(&a == &b) return false;
+ Rect ra = a.bbox(), rb = b.bbox();
+ //TODO: should we use tol in these conditions?
+ if(ra[dim].max() <= rb[dim].min()) return true;
+ if(rb[dim].max() <= ra[dim].min()) return false;
+ //we know that the rects intersect on dim
+ //by referencing f / t we are assuming that the section was constructed with 1-dim
+ if(ra[1-dim].intersects(rb[1-dim])) {
+ if(are_near(a.fp[1-dim], b.fp[1-dim], tol)) {
+ return section_order(a, a.f > a.t ? a.f - 0.01 : a.f + 0.01,
+ b, b.f > b.t ? b.f - 0.01 : b.f + 0.01);
+ } else if(a.fp[1-dim] < b.fp[1-dim]) {
+ //b inside a
+ double ta = section_root(a, ps, b.fp[1-dim], Dim2(1-dim));
+ //TODO: fix bug that necessitates this
+ if(ta == -1) ta = (a.t + a.f) / 2;
+ return section_order(a, ta, b, b.f);
+ } else {
+ //a inside b
+ double tb = section_root(b, ps, a.fp[1-dim], Dim2(1-dim));
+ //TODO: fix bug that necessitates this
+ if(tb == -1) tb = (b.t + b.f) / 2;
+ return section_order(a, a.f, b, tb);
+ }
+ }
+
+ return Point::LexOrderRt(dim)(a.fp, b.fp);
+}
+
+// splits a section into pieces, as specified by an array of doubles, mutating the section to
+// represent the first part, and returning the rest
+//TODO: output iterator?
+std::vector<boost::shared_ptr<Section> > split_section(boost::shared_ptr<Section> s, PathVector const &ps, std::vector<double> &cuts, Dim2 d) {
+ std::vector<boost::shared_ptr<Section> > ret;
+
+ process_splits(cuts, s->f, s->t);
+ if(cuts.size() <= 2) return ret;
+
+ s->t = cuts[1];
+ s->tp = s->curve.get(ps)(cuts[1]);
+ assert(Point::LexOrderRt(d)(s->fp, s->tp));
+
+ ret.reserve(cuts.size() - 2);
+ for(int i = cuts.size() - 1; i > 1; i--) ret.push_back(boost::shared_ptr<Section>(new Section(s->curve, cuts[i-1], cuts[i], ps, d)));
+ return ret;
+}
+
+//merges the sorted lists a and b according to comparison z
+template<typename X, typename Z>
+void merge(X &a, X const &b, Z const &z) {
+ a.reserve(a.size() + b.size());
+ unsigned start = a.size();
+ concatenate(a, b);
+ std::inplace_merge(a.begin(), a.begin() + start, a.end(), z);
+}
+
+//TODO: faster than linear
+unsigned find_vertex(std::vector<TopoGraph::Vertex> const &vertices, Point p, double tol) {
+ for(unsigned i = 0; i < vertices.size(); i++)
+ if(are_near(vertices[i].avg, p, tol)) return i;
+ return vertices.size();
+}
+
+//takes a vector of T pointers, and returns a vector of T with copies
+template<typename T>
+std::vector<T> deref_vector(std::vector<boost::shared_ptr<T> > const &xs, unsigned from = 0) {
+ std::vector<T> ret;
+ ret.reserve(xs.size() - from);
+ for(unsigned i = from; i < xs.size(); i++)
+ ret.push_back(T(*xs[i]));
+ return ret;
+}
+
+//used to create reversed sorting predicates
+template<typename C>
+struct ReverseAdapter {
+ typedef typename C::second_argument_type first_argument_type;
+ typedef typename C::first_argument_type second_argument_type;
+ typedef typename C::result_type result_type;
+ const C &comp;
+ ReverseAdapter(const C &c) : comp(c) {}
+ result_type operator()(const first_argument_type &a, const second_argument_type &b) const { return comp(b, a); }
+};
+
+//used to sort std::vector<Section*>
+template<typename C>
+struct DerefAdapter {
+ typedef typename boost::shared_ptr<typename C::first_argument_type> first_argument_type;
+ typedef typename boost::shared_ptr<typename C::second_argument_type> second_argument_type;
+ typedef typename C::result_type result_type;
+ const C &comp;
+ DerefAdapter(const C &c) : comp(c) {}
+ result_type operator()(const first_argument_type a, const second_argument_type b) const {
+ if(!a) return false;
+ if(!b) return true;
+ return comp(*a, *b);
+ }
+};
+
+struct EdgeSorter {
+ typedef TopoGraph::Edge first_argument_type;
+ typedef TopoGraph::Edge second_argument_type;
+ typedef bool result_type;
+ SectionSorter s;
+ EdgeSorter(const PathVector &rs, Dim2 d, double t) : s(rs, d, t) {}
+ bool operator()(TopoGraph::Edge const &e1, TopoGraph::Edge const &e2) const { return s(*e1.section, *e2.section); }
+};
+
+#ifdef SWEEP_GRAPH_DEBUG
+//used for debugging purposes - each element represents a subsequent iteration of the algorithm.
+std::vector<std::vector<Section> > monoss;
+std::vector<std::vector<Section> > chopss;
+std::vector<std::vector<Section> > contexts;
+#endif
+
+/*
+ 1) take item off sweep sorted todo
+ 2) find all of the to-values before the beginning of this section
+ 3) sort these lexicographically, process them in order, grouping other sections in the context, and constructing a vertex in one fell swoop.
+ 4) add our section into context, splitting on intersections
+
+ 3 is novel, we perform it by storing
+ */
+
+template<typename A, typename B, typename Z>
+struct MergeIterator {
+ A const &a;
+ B &b;
+ Z const &z;
+ unsigned ai;
+ bool on_a;
+ MergeIterator(A const &av, B &bv, Z const &zv) : a(av), b(bv), z(zv), ai(0), on_a(b.empty() || z(a[0], b.back())) {}
+ MergeIterator &operator++() {
+ if(!done()) {
+ on_a = b.empty() ? true : (ai >= a.size() ? false : z(a[ai], b.back()));
+ if(on_a) {
+ ++ai;
+ if(ai >= a.size()) on_a = false;
+ } else {
+ b.erase(b.end());
+ if(b.empty()) on_a = true;
+ }
+ }
+ return *this;
+ }
+ typename A::value_type operator*() {
+ assert(!done());
+ return on_a ? a[ai] : b.back();
+ }
+ bool done() { return b.empty() && ai >= a.size() - 1; }
+ typename A::value_type operator->() { assert(!done()); return on_a ? a[ai] : b.back(); }
+};
+
+void modify_windings(std::vector<int> &windings, boost::shared_ptr<Section> sec, Dim2 d) {
+ unsigned k = sec->curve.path;
+ if(k >= windings.size() || sec->fp[d] == sec->tp[d]) return;
+ if(sec->f < sec->t) windings[k]++;
+ if(sec->f > sec->t) windings[k]--;
+}
+
+struct Context {
+ boost::shared_ptr<Section> section;
+ int from_vert;
+ int to_vert;
+ Context(boost::shared_ptr<Section> sect, int from) : section(sect), from_vert(from), to_vert(-1) {}
+};
+
+template<typename C>
+struct ContextAdapter {
+ typedef Context first_argument_type;
+ typedef typename C::second_argument_type second_argument_type;
+ typedef typename C::result_type result_type;
+ const C &comp;
+ ContextAdapter(const C &c) : comp(c) {}
+ result_type operator()(const Context &a, const second_argument_type &b) const { return comp(a.section, b); }
+};
+
+#define DINF std::numeric_limits<double>::infinity()
+
+TopoGraph::TopoGraph(PathVector const &ps, Dim2 d, double t) : dim(d), tol(t) {
+ //s_sort = vertical section order
+ ContextAdapter<DerefAdapter<SectionSorter> > s_sort = DerefAdapter<SectionSorter>(SectionSorter(ps, (Dim2)(1-d), tol));
+ //sweep_sort = horizontal sweep order
+ DerefAdapter<SweepSorter> sweep_sort = DerefAdapter<SweepSorter>(SweepSorter(d));
+ //heap_sort = reverse horizontal sweep order
+ ReverseAdapter<DerefAdapter<SweepSorter> > heap_sort = ReverseAdapter<DerefAdapter<SweepSorter> >(sweep_sort);
+ //edge_sort = sorter for edges
+ EdgeSorter edge_sort = EdgeSorter(ps, (Dim2)(1-d), tol);
+
+ std::vector<boost::shared_ptr<Section> > input_sections = mono_sections(ps, d), chops;
+ std::sort(input_sections.begin(), input_sections.end(), sweep_sort);
+
+ std::vector<Context> context;
+
+ vertices.reserve(input_sections.size());
+
+ //std::vector<unsigned> to_process;
+
+ std::vector<int> windings(ps.size(), 0);
+ for(MergeIterator<Area, Area, DerefAdapter<SweepSorter> > iter(input_sections, chops, sweep_sort); ; ++iter) {
+ //represents our position in the sweep, which controls what we finalize
+ //if we have no more to process, finish the rest by setting our position to infinity
+ Point lim;
+ if(iter.done()) lim[X] = lim[Y] = DINF; else lim = iter->fp;
+
+ /*
+ //finalize vertices
+ for(unsigned i = 0; i < to_process.size(); i++) {
+ if(vertices[to_process[i]].avg[d] + tol < lim[d])
+ for(unsigned j = 0; j < context.size(); j++) {
+
+ }
+ } */
+
+ //find all sections to remove
+ for(int i = context.size() - 1; i >= 0; i--) {
+ boost::shared_ptr<Section> sec = context[i].section;
+ if(Point::LexOrderRt(d)(lim, sec->tp)) {
+ //sec->tp is less than or equal to lim
+ if(context[i].to_vert == -1) {
+ //we need to create a new vertex; add everything that enters it
+ //Point avg;
+ //unsigned cnt;
+ std::vector<Edge> enters;
+ std::fill(windings.begin(), windings.end(), 0);
+ for(unsigned j = 0; j < context.size(); j++) {
+ modify_windings(windings, context[j].section, d);
+ if(are_near(sec->tp, context[j].section->tp, tol)) {
+ assert(-1 == context[j].to_vert);
+ context[j].section->windings = windings;
+ context[j].to_vert = vertices.size();
+ enters.push_back(Edge(context[j].section, context[j].from_vert));
+ //avg += context[j].section->tp;
+ //cnt++;
+ }
+ }
+ //Vertex &v(avg / (double)cnt);
+ Vertex v(context[i].section->tp);
+ v.enters = enters;
+ vertices.push_back(v);
+ //to_process.push_back(vertices.size() - 1);
+ }
+ context.erase(context.begin() + i);
+ }
+ }
+
+ if(!iter.done()) {
+ boost::shared_ptr<Section> s = *iter;
+
+ //create a new context, associate a beginning vertex, and insert it in the proper location
+ unsigned ix = find_vertex(vertices, s->fp, tol);
+ if(ix == vertices.size()) {
+ vertices.push_back(Vertex(s->fp));
+ //to_process.push_back(vertices.size() - 1);
+ }
+ unsigned context_ix = std::lower_bound(context.begin(), context.end(), s, s_sort) - context.begin();
+
+ context.insert(context.begin() + context_ix, Context(s, ix));
+
+ Interval si = Interval(s->fp[1-d], s->tp[1-d]);
+
+ // Now we intersect with neighbors - do a sweep!
+ std::vector<double> this_splits;
+ for(unsigned i = 0; i < context.size(); i++) {
+ if(context[i].section == context[context_ix].section) continue;
+
+ boost::shared_ptr<Section> sec = context[i].section;
+
+ if(!si.intersects(Interval(sec->fp[1-d], sec->tp[1-d]))) continue;
+
+ std::vector<double> other_splits;
+ Crossings xs = mono_intersect(s->curve.get(ps), Interval(s->f, s->t),
+ sec->curve.get(ps), Interval(sec->f, sec->t));
+ if(xs.empty()) continue;
+
+ for(unsigned j = 0; j < xs.size(); j++) {
+ this_splits.push_back(xs[j].ta);
+ other_splits.push_back(xs[j].tb);
+ }
+ merge(chops, split_section(sec, ps, other_splits, d), heap_sort);
+ }
+ if(!this_splits.empty())
+ merge(chops, split_section(context[context_ix].section, ps, this_splits, d), heap_sort);
+
+ std::sort(chops.begin(), chops.end(), heap_sort);
+
+ if(context[context_ix].section->tp[d] - context[context_ix].section->fp[d] <= tol) {
+ if(!are_near(context[context_ix].section->tp, context[context_ix].section->fp, tol)) {
+ ix = find_vertex(vertices, context[context_ix].section->tp, tol);
+ if(ix != vertices.size()) {
+ boost::shared_ptr<Section> sec = context[context_ix].section;
+ Edge e(sec, context[context_ix].from_vert);
+
+ std::vector<Edge>::iterator it = std::lower_bound(vertices[ix].enters.begin(), vertices[ix].enters.end(), e, edge_sort);
+
+ if(vertices[ix].enters.empty()) {
+ std::fill(windings.begin(), windings.end(), 0);
+ for(unsigned j = 0; j <= context_ix; j++) modify_windings(windings, context[j].section, d);
+ } else if(it == vertices[ix].enters.end()) {
+ windings = (it-1)->section->windings;
+ modify_windings(windings, (it-1)->section, d);
+ } else {
+ windings = it->section->windings;
+ }
+
+ sec->windings = windings;
+ modify_windings(windings, sec, d);
+
+ for(std::vector<Edge>::iterator it2 = it; it2 != vertices[ix].enters.end(); ++it2) {
+ it2->section->windings = windings;
+ modify_windings(windings, it2->section, d);
+ }
+
+ vertices[ix].enters.insert(it, e);
+ context.erase(context.begin() + context_ix);
+ }
+ } else context.erase(context.begin() + context_ix);
+ }
+ }
+
+ #ifdef SWEEP_GRAPH_DEBUG
+ std::vector<Section> rem;
+ for(unsigned i = iter.ai + 1; i < iter.a.size(); i++) rem.push_back(*iter.a[i]);
+ monoss.push_back(rem);
+ chopss.push_back(deref_vector(iter.b));
+ rem.clear();
+ for(unsigned i = 0; i < context.size(); i++) rem.push_back(*context[i].section);
+ contexts.push_back(rem);
+ #endif
+
+ if(iter.done() && context.empty()) return;
+ }
+}
+
+void trim_whiskers(TopoGraph &g) {
+ std::vector<unsigned> affected;
+
+ for(unsigned i = 0; i < g.size(); i++)
+ if(g[i].degree() == 1) affected.push_back(i);
+
+ while(!affected.empty()) {
+ unsigned j = 0;
+ for(unsigned i = 0; i < affected.size(); i++)
+ if(g[affected[i]].degree() == 1)
+ affected[j++] = g.remove_edge(affected[i], 0).other;
+ affected.resize(j);
+ }
+}
+
+void add_edge_at(TopoGraph &g, unsigned ix, boost::shared_ptr<Section> s, TopoGraph::Edge jx, bool before = true) {
+ TopoGraph::Vertex &v = g[ix];
+ for(unsigned i = 0; i < v.enters.size(); i++) {
+ if(v.enters[i].section == s) {
+ v.enters.insert(v.enters.begin() + (before ? i : i + 1), jx);
+ return;
+ }
+ }
+ for(unsigned i = 0; i < v.exits.size(); i++) {
+ if(v.exits[i].section == s) {
+ v.exits.insert(v.exits.begin() + (before ? i : i + 1), jx);
+ return;
+ }
+ }
+ //TODO: fix the fall through to here
+ //assert(false);
+}
+
+void double_whiskers(TopoGraph &g) {
+ for(unsigned i = 0; i < g.size(); i++) {
+ if(g[i].degree() == 1) {
+ unsigned j = i;
+ TopoGraph::Edge e = g[i][0];
+ while(true) {
+ TopoGraph::Edge next_edge = g[j][1 - g[j].find_section(e.section)];
+ boost::shared_ptr<Section> new_section = boost::shared_ptr<Section>(new Section(*e.section));
+ add_edge_at(g, j, e.section, TopoGraph::Edge(new_section, e.other), false);
+ add_edge_at(g, e.other, e.section, TopoGraph::Edge(new_section, j), true);
+
+ if(g[e.other].degree() == 3) {
+ j = e.other;
+ e = next_edge;
+ } else break;
+ }
+ }
+ }
+}
+
+/*
+void remove_degenerate(TopoGraph &g) {
+ for(unsigned i = 0; i < g.size(); i++) {
+ for(int j = g[i].degree(); j >= 0; j--) {
+ if(g[i][j].other == i)
+ }
+ }
+}*/
+
+/*
+void remove_vestigial(TopoGraph &g) {
+ for(unsigned i = 0; i < g.size(); i++) {
+ if(g[i].enters.size() == 1 && g[i].exits.size() == 1) {
+ TopoGraph::Edge &e1 = g[i][0], &e2 = g[i][1];
+ if(e1.section == e2.section) {
+ //vestigial vert
+ Section *new_section = new Section(e1.section->curve,
+ e1.section->f, e2.section->t,
+ e1.section->fp, e2.section->tp);
+
+ e1.other
+
+ Vertex *v1 = e1.other, *v2 = e2.other;
+ v1->lookup_section(e1.section) = Edge(new_section, v2);
+ v2->lookup_section(e2.section) = Edge(new_section, v1);
+ g.erase(g.begin() + i);
+ }
+ }
+ }
+}*/
+
+//planar area finding
+//linear on number of edges
+Areas traverse_areas(TopoGraph const &g) {
+ Areas ret;
+
+ //stores which edges we've visited
+ std::vector<std::vector<bool> > visited;
+ for(unsigned i = 0; i < g.size(); i++) visited.push_back(std::vector<bool>(g[i].degree(), false));
+
+ for(unsigned vix = 0; vix < g.size(); vix++) {
+ while(true) {
+ //find an unvisited edge to start on
+
+ unsigned e_ix = std::find(visited[vix].begin(), visited[vix].end(), false) - visited[vix].begin();
+ if(e_ix == g[vix].degree()) break;
+
+ unsigned start = e_ix;
+ unsigned cur = vix;
+
+ Area area;
+ //std::vector<std::vector<bool> > before(visited);
+ while(cur < g.size() && !visited[cur][e_ix]) {
+ visited[cur][e_ix] = true;
+
+ TopoGraph::Edge e = g[cur][e_ix];
+
+ area.push_back(e.section);
+
+ //go to clockwise edge
+ cur = e.other;
+ unsigned deg = g[cur].degree();
+ e_ix = g[cur].find_section(e.section);
+
+ if(deg == 1 || e_ix == deg) {
+ visited[cur][e_ix] = true;
+ break;
+ }
+
+ e_ix = (e_ix + 1) % deg;
+
+ if(cur == vix && start == e_ix) break;
+ }
+ //if(vix == cur && start == e_ix) {
+ ret.push_back(area);
+ //} else visited = before;
+ }
+ }
+ return ret;
+}
+
+void remove_area_whiskers(Areas &areas) {
+ for(int i = areas.size() - 1; i >= 0; i--)
+ if(areas[i].size() == 2 && *areas[i][0] == *areas[i][1])
+ areas.erase(areas.begin() + i);
+}
+
+Path area_to_path(PathVector const &ps, Area const &area) {
+ Path ret;
+ if(area.size() == 0) return ret;
+ Point prev = area[0]->fp;
+ for(unsigned i = 0; i < area.size(); i++) {
+ bool forward = are_near(area[i]->fp, prev, 0.01);
+ Curve *curv = area[i]->curve.get(ps).portion(
+ forward ? area[i]->f : area[i]->t,
+ forward ? area[i]->t : area[i]->f);
+ ret.append(*curv, Path::STITCH_DISCONTINUOUS);
+ delete curv;
+ prev = forward ? area[i]->tp : area[i]->fp;
+ }
+ return ret;
+}
+
+PathVector areas_to_paths(PathVector const &ps, Areas const &areas) {
+ std::vector<Path> ret;
+ ret.reserve(areas.size());
+ for(unsigned i = 0; i < areas.size(); i++)
+ ret.push_back(area_to_path(ps, areas[i]));
+ return ret;
+}
+
+} // end namespace Geom
diff --git a/src/2geom/toposweep.h b/src/2geom/toposweep.h
new file mode 100644
index 000000000..428115dd3
--- /dev/null
+++ b/src/2geom/toposweep.h
@@ -0,0 +1,222 @@
+
+/**
+ * \file
+ * \brief TopoSweep - topology / graph representation of a PathVector, for boolean operations and related tasks
+ *
+ * Authors:
+ * Michael Sloan <mgsloan at gmail.com>
+ * Nathan Hurst <njhurst at njhurst.com>
+ *
+ * Copyright 2007-2009 authors
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it either under the terms of the GNU Lesser General Public
+ * License version 2.1 as published by the Free Software Foundation
+ * (the "LGPL") or, at your option, under the terms of the Mozilla
+ * Public License Version 1.1 (the "MPL"). If you do not alter this
+ * notice, a recipient may use your version of this file under either
+ * the MPL or the LGPL.
+ *
+ * You should have received a copy of the LGPL along with this library
+ * in the file COPYING-LGPL-2.1; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ * You should have received a copy of the MPL along with this library
+ * in the file COPYING-MPL-1.1
+ *
+ * The contents of this file are subject to the Mozilla Public License
+ * Version 1.1 (the "License"); you may not use this file except in
+ * compliance with the License. You may obtain a copy of the License at
+ * http://www.mozilla.org/MPL/
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
+ * OF ANY KIND, either express or implied. See the LGPL or the MPL for
+ * the specific language governing rights and limitations.
+ */
+
+#ifndef SEEN_GEOM_TOPOSWEEP_H
+#define SEEN_GEOM_TOPOSWEEP_H
+
+#include <2geom/coord.h>
+#include <2geom/point.h>
+#include <2geom/pathvector.h>
+#include <2geom/rect.h>
+#include <2geom/path.h>
+#include <2geom/curve.h>
+
+#include <boost/shared_ptr.hpp>
+
+namespace Geom {
+
+// indicates a particular curve in a pathvector
+struct CurveIx {
+ unsigned path, ix;
+ CurveIx(unsigned p, unsigned i) : path(p), ix(i) {}
+ // retrieves the indicated curve from the pathvector
+ Curve const &get(PathVector const &ps) const {
+ return ps[path][ix];
+ }
+ bool operator==(CurveIx const &other) const {
+ return other.path == path && other.ix == ix;
+ }
+};
+
+// represents a monotonic section of a path
+struct Section {
+ CurveIx curve;
+ double f, t;
+ Point fp, tp;
+ std::vector<int> windings;
+ Section(CurveIx cix, double fd, double td, Point fdp, Point tdp) : curve(cix), f(fd), t(td), fp(fdp), tp(tdp) { }
+ Section(CurveIx cix, double fd, double td, PathVector ps, Dim2 d) : curve(cix), f(fd), t(td) {
+ fp = curve.get(ps).pointAt(f), tp = curve.get(ps).pointAt(t);
+ if (Point::LexOrderRt(d)(tp, fp)) {
+ //swap from and to, since tp is left or above fp
+ std::swap(f, t);
+ std::swap(fp, tp);
+ }
+ }
+ Rect bbox() const { return Rect(fp, tp); }
+ bool operator==(Section const &other) const {
+ return (curve == other.curve) && (f == other.f) && (t == other.t);
+ }
+};
+
+class TopoGraph {
+ public:
+
+ // Represents an e double tol;dge on a vertex
+ class Edge {
+ public:
+ boost::shared_ptr<Section> section; // section associated with this edge
+ unsigned other; // index of the vertex this edge points to
+ Edge(boost::shared_ptr<Section> s, unsigned o) : section(s), other(o) {}
+ };
+
+ // Represents a vertex in the graph, in terms of a point and edges which enter and exit.
+ // A vertex has an "avg" point, which is a representative point for the vertex. All
+ // edges have an endpoint tol away.
+ class Vertex {
+ public:
+ std::vector<Edge> enters, exits; // indexes of the enter / exit edges
+ Point avg;
+ Vertex(Point p) : avg(p) {}
+ inline unsigned degree() const { return enters.size() + exits.size(); }
+ Edge operator[](unsigned ix) const;
+ Edge &operator[](unsigned ix);
+ void erase(unsigned ix);
+ void insert(unsigned ix, Edge e);
+ unsigned find_section(boost::shared_ptr<Section> section) const;
+ };
+
+ TopoGraph(PathVector const &ps, Dim2 d, double t);
+
+ unsigned size() const { return vertices.size(); }
+
+ Vertex &operator[](unsigned ix) { return vertices[ix]; }
+ Vertex const &operator[](unsigned ix) const { return vertices[ix]; }
+
+ //removes both edges, and returns the vertices[ix][jx] one
+ Edge remove_edge(unsigned ix, unsigned jx);
+
+ //returns a graph with all zero degree vertices and unused edges removed
+ void cannonize();
+
+ //checks invariants
+ void assert_invariants() const;
+
+ std::vector<Vertex> vertices;
+ Dim2 dim;
+ double tol;
+};
+
+//TODO: convert to classes
+typedef std::vector<boost::shared_ptr<Section> > Area;
+typedef std::vector<Area> Areas;
+
+//TopoGraph sweep_graph(PathVector const &ps, Dim2 d = X, double tol = 0.00001);
+
+void trim_whiskers(TopoGraph &g);
+void double_whiskers(TopoGraph &g);
+//void remove_degenerate(TopoGraph &g);
+//void remove_vestigial(TopoGraph &g);
+//Areas traverse_areas(TopoGraph const &g);
+
+
+void remove_area_whiskers(Areas &areas);
+PathVector areas_to_paths(PathVector const &ps, Areas const &areas);
+
+class SectionSorter {
+ const PathVector &ps;
+ Dim2 dim;
+ double tol;
+ bool section_order(Section const &a, double at, Section const &b, double bt) const;
+ public:
+ typedef Section first_argument_type;
+ typedef Section second_argument_type;
+ typedef bool result_type;
+
+ SectionSorter(const PathVector &rs, Dim2 d, double t = 0.00001) : ps(rs), dim(d), tol(t) {}
+ bool operator()(Section const &a, Section const &b) const;
+};
+
+//sorter used to create the initial sweep of sections, such that they are dealt with in order
+struct SweepSorter {
+ typedef Section first_argument_type;
+ typedef Section second_argument_type;
+ typedef bool result_type;
+ Dim2 dim;
+ SweepSorter(Dim2 d) : dim(d) {}
+ bool operator()(const Section &a, const Section &b) const {
+ return Point::LexOrderRt(dim)(a.fp, b.fp);
+ }
+};
+
+struct UnionOp {
+ unsigned ix;
+ bool nz1, nz2;
+ UnionOp(unsigned i, bool a, bool b) : ix(i), nz1(a), nz2(b) {}
+ bool operator()(std::vector<int> const &windings) const {
+ int w1 = 0, w2 = 0;
+ for(unsigned j = 0; j < ix; j++) w1 += windings[j];
+ for(unsigned j = ix; j < windings.size(); j++) w2 += windings[j];
+ return (nz1 ? w1 : w1 % 2) != 0 || (nz2 ? w2 : w2 % 2) != 0;
+ }
+};
+
+//returns all areas for which the winding -> bool function yields true
+template<class Z>
+Areas filter_areas(PathVector const &ps, Areas const & areas, Z const &z) {
+ Areas ret;
+ SweepSorter sorty = SweepSorter(Y);
+ SectionSorter sortx = SectionSorter(ps, X);
+ for(unsigned i = 0; i < areas.size(); i++) {
+ if(areas[i].size() < 2) continue;
+ //find a representative section
+ unsigned rj = 0;
+ bool rev = are_near(areas[i][0]->fp, areas[i][1]->tp);
+ for(unsigned j = 1; j < areas[i].size(); j++)
+ if(sorty(*areas[i][rj], *areas[i][j])) rj = j;
+ if(sortx(*areas[i][rj], *areas[i][(rj+areas[i].size() - 1) % areas[i].size()])) {
+ rj = 0;
+ for(unsigned j = 1; j < areas[i].size(); j++)
+ if(sorty(*areas[i][j], *areas[i][rj])) rj = j;
+ }
+ if(z(areas[i][rj]->windings)) ret.push_back(areas[i]);
+ }
+ return ret;
+}
+
+} // end namespace Geom
+
+#endif // SEEN_GEOM_TOPOSWEEP_H
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/2geom/transforms.cpp b/src/2geom/transforms.cpp
index 3a1866c13..2658719c4 100644
--- a/src/2geom/transforms.cpp
+++ b/src/2geom/transforms.cpp
@@ -60,12 +60,12 @@ Point &Point::operator*=(Rotate const &r)
}
Point &Point::operator*=(HShear const &h)
{
- _pt[X] += h.f * _pt[Y];
+ _pt[X] += h.f * _pt[X];
return *this;
}
Point &Point::operator*=(VShear const &v)
{
- _pt[Y] += v.f * _pt[X];
+ _pt[Y] += v.f * _pt[Y];
return *this;
}
diff --git a/src/2geom/transforms.h b/src/2geom/transforms.h
index 48d4b1dba..9623bed26 100644
--- a/src/2geom/transforms.h
+++ b/src/2geom/transforms.h
@@ -32,12 +32,12 @@
* the specific language governing rights and limitations.
*/
-#ifndef SEEN_Geom_TRANSFORMS_H
-#define SEEN_Geom_TRANSFORMS_H
+#ifndef LIB2GEOM_SEEN_TRANSFORMS_H
+#define LIB2GEOM_SEEN_TRANSFORMS_H
+#include <cmath>
#include <2geom/forward.h>
#include <2geom/affine.h>
-#include <cmath>
namespace Geom {
@@ -66,7 +66,8 @@ struct TransformConcept {
}
};
-/** @brief Base template for transforms. */
+/** @brief Base template for transforms.
+ * This class is an implementation detail and should not be used directly. */
template <typename T>
class TransformOperations
: boost::equality_comparable< T
@@ -198,6 +199,7 @@ public:
};
/** @brief Common base for shearing transforms.
+ * This class is an implementation detail and should not be used directly.
* @ingroup Transforms */
template <typename S>
class ShearBase
@@ -259,10 +261,9 @@ inline Translate pow(Translate const &t, int n) {
//TODO: matrix to trans/scale/rotate
-} /* namespace Geom */
-
+} // end namespace Geom
-#endif /* !SEEN_Geom_TRANSFORMS_H */
+#endif // LIB2GEOM_SEEN_TRANSFORMS_H
/*
Local Variables:
diff --git a/src/2geom/utils.h b/src/2geom/utils.h
index e90a4623b..6a72d42c4 100644
--- a/src/2geom/utils.h
+++ b/src/2geom/utils.h
@@ -1,10 +1,7 @@
-#ifndef LIB2GEOM_UTILS_HEADER
-#define LIB2GEOM_UTILS_HEADER
-
/**
* \file
* \brief Various utility functions.
- *
+ *//*
* Copyright 2007 Johan Engelen <goejendaagh@zonnet.nl>
* Copyright 2006 Michael G. Sloan <mgsloan@gmail.com>
*
@@ -33,6 +30,9 @@
*
*/
+#ifndef SEEN_LIB2GEOM_UTILS_H
+#define SEEN_LIB2GEOM_UTILS_H
+
#include <cstddef>
#include <vector>
@@ -59,9 +59,9 @@ struct MultipliableNoncommutative : B
}
};
-}
+} // end namespace Geom
-#endif
+#endif // SEEN_LIB2GEOM_UTILS_H
/*
Local Variables:
diff --git a/src/axis-manip.h b/src/axis-manip.h
index 835f67a97..d81da4164 100644
--- a/src/axis-manip.h
+++ b/src/axis-manip.h
@@ -12,8 +12,8 @@
#ifndef SEEN_AXIS_MANIP_H
#define SEEN_AXIS_MANIP_H
+#include <utility>
#include <gtk/gtk.h>
-#include "libnr/nr-point.h"
namespace Proj {
diff --git a/src/box3d-context.cpp b/src/box3d-context.cpp
index 8bba30eb9..87b182d10 100644
--- a/src/box3d-context.cpp
+++ b/src/box3d-context.cpp
@@ -301,11 +301,11 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
m.setup(desktop, true, bc->item);
m.freeSnapReturnByRef(button_dt, Inkscape::SNAPSOURCE_NODE_HANDLE);
m.unSetup();
- bc->center = from_2geom(button_dt);
+ bc->center = button_dt;
- bc->drag_origin = from_2geom(button_dt);
- bc->drag_ptB = from_2geom(button_dt);
- bc->drag_ptC = from_2geom(button_dt);
+ bc->drag_origin = button_dt;
+ bc->drag_ptB = button_dt;
+ bc->drag_ptC = button_dt;
// This can happen after saving when the last remaining perspective was purged and must be recreated.
if (!cur_persp) {
@@ -314,7 +314,7 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
}
/* Projective preimages of clicked point under current perspective */
- bc->drag_origin_proj = cur_persp->perspective_impl->tmat.preimage (from_2geom(button_dt), 0, Proj::Z);
+ bc->drag_origin_proj = cur_persp->perspective_impl->tmat.preimage (button_dt, 0, Proj::Z);
bc->drag_ptB_proj = bc->drag_origin_proj;
bc->drag_ptC_proj = bc->drag_origin_proj;
bc->drag_ptC_proj.normalize();
@@ -358,10 +358,10 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
}
if (!bc->extruded) {
- bc->drag_ptB = from_2geom(motion_dt);
- bc->drag_ptC = from_2geom(motion_dt);
+ bc->drag_ptB = motion_dt;
+ bc->drag_ptC = motion_dt;
- bc->drag_ptB_proj = cur_persp->perspective_impl->tmat.preimage (from_2geom(motion_dt), 0, Proj::Z);
+ bc->drag_ptB_proj = cur_persp->perspective_impl->tmat.preimage (motion_dt, 0, Proj::Z);
bc->drag_ptC_proj = bc->drag_ptB_proj;
bc->drag_ptC_proj.normalize();
bc->drag_ptC_proj[Proj::Z] = 0.25;
@@ -371,15 +371,15 @@ static gint sp_box3d_context_root_handler(SPEventContext *event_context, GdkEven
if (!bc->ctrl_dragged) {
/* snapping */
Box3D::PerspectiveLine pline (bc->drag_ptB, Proj::Z, document->getCurrentPersp3D());
- bc->drag_ptC = pline.closest_to (from_2geom(motion_dt));
+ bc->drag_ptC = pline.closest_to (motion_dt);
bc->drag_ptB_proj.normalize();
bc->drag_ptC_proj = cur_persp->perspective_impl->tmat.preimage (bc->drag_ptC, bc->drag_ptB_proj[Proj::X], Proj::X);
} else {
- bc->drag_ptC = from_2geom(motion_dt);
+ bc->drag_ptC = motion_dt;
bc->drag_ptB_proj.normalize();
- bc->drag_ptC_proj = cur_persp->perspective_impl->tmat.preimage (from_2geom(motion_dt), bc->drag_ptB_proj[Proj::X], Proj::X);
+ bc->drag_ptC_proj = cur_persp->perspective_impl->tmat.preimage (motion_dt, bc->drag_ptB_proj[Proj::X], Proj::X);
}
m.freeSnapReturnByRef(bc->drag_ptC, Inkscape::SNAPSOURCE_NODE_HANDLE);
}
diff --git a/src/desktop-events.cpp b/src/desktop-events.cpp
index bbc7d10c5..b886e884e 100644
--- a/src/desktop-events.cpp
+++ b/src/desktop-events.cpp
@@ -155,9 +155,9 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
m.unSetup();
}
- sp_guideline_set_position(SP_GUIDELINE(guide), from_2geom(event_dt));
- desktop->set_coordinate_status(to_2geom(event_dt));
- desktop->setPosition(to_2geom(event_dt));
+ sp_guideline_set_position(SP_GUIDELINE(guide), event_dt);
+ desktop->set_coordinate_status(event_dt);
+ desktop->setPosition(event_dt);
}
break;
case GDK_BUTTON_RELEASE:
@@ -186,13 +186,13 @@ static gint sp_dt_ruler_event(GtkWidget *widget, GdkEvent *event, SPDesktopWidge
Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
Inkscape::XML::Node *repr = xml_doc->createElement("sodipodi:guide");
sp_repr_set_point(repr, "orientation", normal);
- sp_repr_set_point(repr, "position", from_2geom(event_dt));
+ sp_repr_set_point(repr, "position", event_dt);
desktop->namedview->appendChild(repr);
Inkscape::GC::release(repr);
DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_NONE,
_("Create guide"));
}
- desktop->set_coordinate_status(from_2geom(event_dt));
+ desktop->set_coordinate_status(event_dt);
}
default:
break;
@@ -345,8 +345,8 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
break;
}
moved = true;
- desktop->set_coordinate_status(from_2geom(motion_dt));
- desktop->setPosition(from_2geom(motion_dt));
+ desktop->set_coordinate_status(motion_dt);
+ desktop->setPosition(motion_dt);
ret = TRUE;
}
@@ -429,8 +429,8 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data)
_("Delete guide"));
}
moved = false;
- desktop->set_coordinate_status(from_2geom(event_dt));
- desktop->setPosition (from_2geom(event_dt));
+ desktop->set_coordinate_status(event_dt);
+ desktop->setPosition (event_dt);
}
drag_type = SP_DRAG_NONE;
sp_canvas_item_ungrab(item, event->button.time);
diff --git a/src/desktop.cpp b/src/desktop.cpp
index d05c94790..4ff2716ca 100644
--- a/src/desktop.cpp
+++ b/src/desktop.cpp
@@ -57,6 +57,7 @@
#include <sigc++/functors/mem_fun.h>
#include <gtkmm.h>
+#include <2geom/transforms.h>
#include <2geom/rect.h>
#include "macros.h"
#include "inkscape-private.h"
diff --git a/src/dialogs/clonetiler.cpp b/src/dialogs/clonetiler.cpp
index e79de069a..f8553f2aa 100644
--- a/src/dialogs/clonetiler.cpp
+++ b/src/dialogs/clonetiler.cpp
@@ -17,6 +17,7 @@
#include <glib/gmem.h>
#include <gtk/gtk.h>
#include <glibmm/i18n.h>
+#include <2geom/transforms.h>
#include "desktop.h"
#include "desktop-handles.h"
diff --git a/src/display/canvas-arena.cpp b/src/display/canvas-arena.cpp
index 6930e4d7c..dd4a4ed5c 100644
--- a/src/display/canvas-arena.cpp
+++ b/src/display/canvas-arena.cpp
@@ -31,7 +31,10 @@ static void sp_canvas_arena_destroy(GtkObject *object);
static void sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static void sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf);
+static void sp_canvas_arena_render_cache (SPCanvasItem *item, Geom::IntRect const &area);
+static void sp_canvas_arena_dirty_cache (SPCanvasArena *arena, NRRectL *area);
static double sp_canvas_arena_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
+static void sp_canvas_arena_visible_area_changed (SPCanvasItem *item, Geom::IntRect const &old_area, Geom::IntRect const &new_area);
static gint sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event);
static gint sp_canvas_arena_send_event (SPCanvasArena *arena, GdkEvent *event);
@@ -93,6 +96,7 @@ sp_canvas_arena_class_init (SPCanvasArenaClass *klass)
item_class->render = sp_canvas_arena_render;
item_class->point = sp_canvas_arena_point;
item_class->event = sp_canvas_arena_event;
+ item_class->visible_area_changed = sp_canvas_arena_visible_area_changed;
}
static void
@@ -106,6 +110,9 @@ sp_canvas_arena_init (SPCanvasArena *arena)
nr_arena_group_set_transparent (NR_ARENA_GROUP (arena->root), TRUE);
arena->active = NULL;
+ arena->cache = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, 1, 1);
+ arena->cache_area = Geom::IntRect::from_xywh(0,0,1,1);
+ arena->dirty = cairo_region_create();
nr_active_object_add_listener ((NRActiveObject *) arena->arena, (NRObjectEventVector *) &carenaev, sizeof (carenaev), arena);
}
@@ -131,6 +138,11 @@ sp_canvas_arena_destroy (GtkObject *object)
nr_object_unref ((NRObject *) arena->arena);
arena->arena = NULL;
}
+ if (arena->cache) {
+ cairo_surface_destroy(arena->cache);
+ arena->cache = NULL;
+ }
+ cairo_region_destroy(arena->dirty);
if (GTK_OBJECT_CLASS (parent_class)->destroy)
(* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
@@ -187,33 +199,74 @@ sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned
static void
sp_canvas_arena_render (SPCanvasItem *item, SPCanvasBuf *buf)
{
- gint bw, bh;
-
SPCanvasArena *arena = SP_CANVAS_ARENA (item);
//SPCanvas *canvas = item->canvas;
- nr_arena_item_invoke_update (arena->root, NULL, &arena->gc,
- NR_ARENA_ITEM_STATE_BBOX | NR_ARENA_ITEM_STATE_RENDER,
- NR_ARENA_ITEM_STATE_NONE);
+ //nr_arena_item_invoke_update (arena->root, NULL, &arena->gc,
+ // NR_ARENA_ITEM_STATE_BBOX | NR_ARENA_ITEM_STATE_RENDER,
+ // NR_ARENA_ITEM_STATE_NONE);
+
+ Geom::OptIntRect r = buf->rect;
+ if (!r || r->hasZeroArea()) return;
+
+ cairo_rectangle_int_t crect;
+ crect.x = r->left();
+ crect.y = r->top();
+ crect.width = r->width();
+ crect.height = r->height();
+ if (cairo_region_contains_rectangle(arena->dirty, &crect) != CAIRO_REGION_OVERLAP_OUT) {
+ sp_canvas_arena_render_cache(item, *r);
+ cairo_region_subtract_rectangle(arena->dirty, &crect);
+ }
- sp_canvas_prepare_buffer(buf);
+ cairo_save(buf->ct);
+ cairo_translate(buf->ct, -r->left(), -r->top());
+ //cairo_rectangle(buf->ct, r->left(), r->top(), r->width(), r->height());
+ //cairo_clip(buf->ct);
+ cairo_set_source_surface(buf->ct, arena->cache, arena->cache_area.left(), arena->cache_area.top());
+ cairo_paint(buf->ct);
+ //nr_arena_item_invoke_render (buf->ct, arena->root, &area, NULL, 0);
+ cairo_restore(buf->ct);
+}
- bw = buf->rect.x1 - buf->rect.x0;
- bh = buf->rect.y1 - buf->rect.y0;
- if ((bw < 1) || (bh < 1)) return;
+static void sp_canvas_arena_render_cache (SPCanvasItem *item, Geom::IntRect const &area)
+{
+ SPCanvasArena *arena = SP_CANVAS_ARENA (item);
+
+ Geom::OptIntRect r = Geom::intersect(arena->cache_area, area);
+ if (!r || r->hasZeroArea()) return; // nothing to do
+
+ cairo_t *ct = cairo_create(arena->cache);
+ cairo_translate(ct, -arena->cache_area.left(), -arena->cache_area.top());
+
+ // clear area to paint
+ cairo_rectangle(ct, area.left(), area.top(), area.width(), area.height());
+ cairo_clip(ct);
+ cairo_save(ct);
+ cairo_set_source_rgba(ct, 0,0,0,0);
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(ct);
+ cairo_restore(ct);
+
+ NRRectL nr_area(r);
- NRRectL area;
+ nr_arena_item_invoke_update (arena->root, NULL, &arena->gc,
+ NR_ARENA_ITEM_STATE_BBOX | NR_ARENA_ITEM_STATE_RENDER,
+ NR_ARENA_ITEM_STATE_NONE);
+ nr_arena_item_invoke_render (ct, arena->root, &nr_area, NULL, 0);
- area.x0 = buf->rect.x0;
- area.y0 = buf->rect.y0;
- area.x1 = buf->rect.x1;
- area.y1 = buf->rect.y1;
+ cairo_destroy(ct);
+}
- sp_canvas_prepare_buffer(buf);
- cairo_save(buf->ct);
- cairo_translate(buf->ct, -area.x0, -area.y0);
- nr_arena_item_invoke_render (buf->ct, arena->root, &area, NULL, 0);
- cairo_restore(buf->ct);
+static void
+sp_canvas_arena_dirty_cache (SPCanvasArena *arena, NRRectL *area)
+{
+ cairo_rectangle_int_t rect;
+ rect.x = area->x0;
+ rect.y = area->y0;
+ rect.width = area->x1 - area->x0;
+ rect.height = area->y1 - area->y0;
+ cairo_region_union_rectangle(arena->dirty, &rect);
}
static double
@@ -237,6 +290,67 @@ sp_canvas_arena_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_
return 1e18;
}
+static void
+sp_canvas_arena_visible_area_changed (SPCanvasItem *item, Geom::IntRect const &old_area, Geom::IntRect const &new_area)
+{
+ SPCanvasArena *arena = SP_CANVAS_ARENA(item);
+
+ cairo_surface_t *new_cache = cairo_image_surface_create(CAIRO_FORMAT_ARGB32,
+ new_area.width(), new_area.height());
+ cairo_t *ct = cairo_create(new_cache);
+ cairo_set_source_surface(ct, arena->cache, old_area.left() - new_area.left(), old_area.top() - new_area.top());
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(ct);
+ cairo_destroy(ct);
+ cairo_surface_destroy(arena->cache);
+ arena->cache = new_cache;
+ arena->cache_area = new_area;
+
+ cairo_rectangle_int_t crect;
+ crect.x = new_area.left();
+ crect.y = new_area.top();
+ crect.width = new_area.width();
+ crect.height = new_area.height();
+ cairo_region_intersect_rectangle(arena->dirty, &crect);
+
+ // invalidate newly exposed areas
+ /*
+ * +----------------------+
+ * | top strip |
+ * +-------+------+-------+
+ * | | | |
+ * | left | old | right |
+ * | strip | area | strip |
+ * | | | |
+ * +-------+------+-------+
+ * | bottom strip |
+ * +----------------------+
+ */
+
+ // top strip
+ if (new_area.top() < old_area.top()) {
+ NRRectL top_strip(new_area.left(), new_area.top(), new_area.right(), old_area.top());
+ sp_canvas_arena_dirty_cache(arena, &top_strip);
+ }
+ // left strip
+ if (new_area.left() < old_area.left()) {
+ NRRectL left_strip(new_area.left(), std::max(new_area.top(), old_area.top()),
+ old_area.left(), std::min(new_area.bottom(), old_area.bottom()));
+ sp_canvas_arena_dirty_cache(arena, &left_strip);
+ }
+ // right strip
+ if (new_area.right() > old_area.right()) {
+ NRRectL right_strip(old_area.right(), std::max(new_area.top(), old_area.top()),
+ new_area.right(), std::min(new_area.bottom(), old_area.bottom()));
+ sp_canvas_arena_dirty_cache(arena, &right_strip);
+ }
+ // bottom strip
+ if (new_area.bottom() > old_area.bottom()) {
+ NRRectL bottom_strip(new_area.left(), old_area.bottom(), new_area.right(), new_area.bottom());
+ sp_canvas_arena_dirty_cache(arena, &bottom_strip);
+ }
+}
+
static gint
sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event)
{
@@ -336,6 +450,8 @@ sp_canvas_arena_request_update (NRArena */*arena*/, NRArenaItem */*item*/, void
static void
sp_canvas_arena_request_render (NRArena */*arena*/, NRRectL *area, void *data)
{
+ if (!area) return;
+ sp_canvas_arena_dirty_cache (SP_CANVAS_ARENA(data), area);
sp_canvas_request_redraw (SP_CANVAS_ITEM (data)->canvas, area->x0, area->y0, area->x1, area->y1);
}
diff --git a/src/display/canvas-arena.h b/src/display/canvas-arena.h
index 4cfeccb5a..220976da0 100644
--- a/src/display/canvas-arena.h
+++ b/src/display/canvas-arena.h
@@ -45,6 +45,10 @@ struct _SPCanvasArena {
/* fixme: */
NRArenaItem *picked;
gdouble delta;
+
+ Geom::IntRect cache_area;
+ cairo_surface_t *cache;
+ cairo_region_t *dirty;
};
struct _SPCanvasArenaClass {
diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp
index dbf7b424d..ec2d35f69 100644
--- a/src/display/canvas-axonomgrid.cpp
+++ b/src/display/canvas-axonomgrid.cpp
@@ -33,6 +33,7 @@
#include "svg/svg-color.h"
#include "util/mathfns.h"
#include "xml/node-event-vector.h"
+#include "round.h"
#define SAFE_SETPIXEL //undefine this when it is certain that setpixel is never called with invalid params
@@ -549,13 +550,13 @@ CanvasAxonomGrid::Render (SPCanvasBuf *buf)
// x-axis always goes from topleft to bottomright. (0,0) - (1,1)
gdouble const xintercept_y_bc = (buf_tl_gc[Geom::X] * tan_angle[X]) - buf_tl_gc[Geom::Y] ;
gdouble const xstart_y_sc = ( xintercept_y_bc - floor(xintercept_y_bc/lyw)*lyw ) + buf->rect.y0;
- gint const xlinestart = (gint) Inkscape::round( (xstart_y_sc - buf->rect.x0*tan_angle[X] -ow[Geom::Y]) / lyw );
+ gint const xlinestart = round( (xstart_y_sc - buf->rect.x0*tan_angle[X] -ow[Geom::Y]) / lyw );
gint xlinenum = xlinestart;
// lines starting on left side.
for (y = xstart_y_sc; y < buf->rect.y1; y += lyw, xlinenum++) {
gint const x0 = buf->rect.x0;
- gint const y0 = (gint) Inkscape::round(y);
- gint const x1 = x0 + (gint) Inkscape::round( (buf->rect.y1 - y) / tan_angle[X] );
+ gint const y0 = round(y);
+ gint const x1 = x0 + round( (buf->rect.y1 - y) / tan_angle[X] );
gint const y1 = buf->rect.y1;
if (!scaled && (xlinenum % empspacing) != 0) {
@@ -570,8 +571,8 @@ CanvasAxonomGrid::Render (SPCanvasBuf *buf)
for (x = xstart_x_sc; x < buf->rect.x1; x += lxw_x, xlinenum--) {
gint const y0 = buf->rect.y0;
gint const y1 = buf->rect.y1;
- gint const x0 = (gint) Inkscape::round(x);
- gint const x1 = x0 + (gint) Inkscape::round( (y1 - y0) / tan_angle[X] );
+ gint const x0 = round(x);
+ gint const x1 = x0 + round( (y1 - y0) / tan_angle[X] );
if (!scaled && (xlinenum % empspacing) != 0) {
sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, color);
@@ -582,10 +583,10 @@ CanvasAxonomGrid::Render (SPCanvasBuf *buf)
// y-axis lines (vertical)
gdouble const ystart_x_sc = floor (buf_tl_gc[Geom::X] / spacing_ylines) * spacing_ylines + ow[Geom::X];
- gint const ylinestart = (gint) Inkscape::round((ystart_x_sc - ow[Geom::X]) / spacing_ylines);
+ gint const ylinestart = round((ystart_x_sc - ow[Geom::X]) / spacing_ylines);
gint ylinenum = ylinestart;
for (x = ystart_x_sc; x < buf->rect.x1; x += spacing_ylines, ylinenum++) {
- gint const x0 = (gint) Inkscape::round(x);
+ gint const x0 = round(x);
if (!scaled && (ylinenum % empspacing) != 0) {
sp_grid_vline (buf, x0, buf->rect.y0, buf->rect.y1 - 1, color);
@@ -597,13 +598,13 @@ CanvasAxonomGrid::Render (SPCanvasBuf *buf)
// z-axis always goes from bottomleft to topright. (0,1) - (1,0)
gdouble const zintercept_y_bc = (buf_tl_gc[Geom::X] * -tan_angle[Z]) - buf_tl_gc[Geom::Y] ;
gdouble const zstart_y_sc = ( zintercept_y_bc - floor(zintercept_y_bc/lyw)*lyw ) + buf->rect.y0;
- gint const zlinestart = (gint) Inkscape::round( (zstart_y_sc + buf->rect.x0*tan_angle[Z] - ow[Geom::Y]) / lyw );
+ gint const zlinestart = round( (zstart_y_sc + buf->rect.x0*tan_angle[Z] - ow[Geom::Y]) / lyw );
gint zlinenum = zlinestart;
// lines starting from left side
for (y = zstart_y_sc; y < buf->rect.y1; y += lyw, zlinenum++) {
gint const x0 = buf->rect.x0;
- gint const y0 = (gint) Inkscape::round(y);
- gint const x1 = x0 + (gint) Inkscape::round( (y - buf->rect.y0 ) / tan_angle[Z] );
+ gint const y0 = round(y);
+ gint const x1 = x0 + round( (y - buf->rect.y0 ) / tan_angle[Z] );
gint const y1 = buf->rect.y0;
if (!scaled && (zlinenum % empspacing) != 0) {
@@ -617,8 +618,8 @@ CanvasAxonomGrid::Render (SPCanvasBuf *buf)
for (x = zstart_x_sc; x < buf->rect.x1; x += lxw_z, zlinenum++) {
gint const y0 = buf->rect.y1;
gint const y1 = buf->rect.y0;
- gint const x0 = (gint) Inkscape::round(x);
- gint const x1 = x0 + (gint) Inkscape::round( (buf->rect.y1 - buf->rect.y0) / tan_angle[Z] );
+ gint const x0 = round(x);
+ gint const x1 = x0 + round( (buf->rect.y1 - buf->rect.y0) / tan_angle[Z] );
if (!scaled && (zlinenum % empspacing) != 0) {
sp_caxonomgrid_drawline (buf, x0, y0, x1, y1, color);
diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp
index e1673c8ef..aa38a14c9 100644
--- a/src/display/canvas-grid.cpp
+++ b/src/display/canvas-grid.cpp
@@ -920,9 +920,9 @@ void
CanvasXYGrid::Render (SPCanvasBuf *buf)
{
gdouble const sxg = floor ((buf->rect.x0 - ow[Geom::X]) / sw[Geom::X]) * sw[Geom::X] + ow[Geom::X];
- gint const xlinestart = (gint) Inkscape::round((sxg - ow[Geom::X]) / sw[Geom::X]);
+ gint const xlinestart = round((sxg - ow[Geom::X]) / sw[Geom::X]);
gdouble const syg = floor ((buf->rect.y0 - ow[Geom::Y]) / sw[Geom::Y]) * sw[Geom::Y] + ow[Geom::Y];
- gint const ylinestart = (gint) Inkscape::round((syg - ow[Geom::Y]) / sw[Geom::Y]);
+ gint const ylinestart = round((syg - ow[Geom::Y]) / sw[Geom::Y]);
//set correct coloring, depending preference (when zoomed out, always major coloring or minor coloring)
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
@@ -943,7 +943,7 @@ CanvasXYGrid::Render (SPCanvasBuf *buf)
gint ylinenum;
gdouble y;
for (y = syg, ylinenum = ylinestart; y < buf->rect.y1; y += sw[Geom::Y], ylinenum++) {
- gint const y0 = (gint) Inkscape::round(y);
+ gint const y0 = round(y);
if (!scaled[Geom::Y] && (ylinenum % empspacing) != 0) {
grid_hline (buf, y0, buf->rect.x0, buf->rect.x1 - 1, color);
} else {
@@ -954,7 +954,7 @@ CanvasXYGrid::Render (SPCanvasBuf *buf)
gint xlinenum;
gdouble x;
for (x = sxg, xlinenum = xlinestart; x < buf->rect.x1; x += sw[Geom::X], xlinenum++) {
- gint const ix = (gint) Inkscape::round(x);
+ gint const ix = round(x);
if (!scaled[Geom::X] && (xlinenum % empspacing) != 0) {
grid_vline (buf, ix, buf->rect.y0, buf->rect.y1, color);
} else {
@@ -965,12 +965,12 @@ CanvasXYGrid::Render (SPCanvasBuf *buf)
gint ylinenum;
gdouble y;
for (y = syg, ylinenum = ylinestart; y < buf->rect.y1; y += sw[Geom::Y], ylinenum++) {
- gint const iy = (gint) Inkscape::round(y);
+ gint const iy = round(y);
gint xlinenum;
gdouble x;
for (x = sxg, xlinenum = xlinestart; x < buf->rect.x1; x += sw[Geom::X], xlinenum++) {
- gint const ix = (gint) Inkscape::round(x);
+ gint const ix = round(x);
if ( (!scaled[Geom::X] && (xlinenum % empspacing) != 0)
|| (!scaled[Geom::Y] && (ylinenum % empspacing) != 0)
|| ((scaled[Geom::X] || scaled[Geom::Y]) && no_emp_when_zoomed_out) )
diff --git a/src/display/guideline.cpp b/src/display/guideline.cpp
index c761fa74e..c1c3e7740 100644
--- a/src/display/guideline.cpp
+++ b/src/display/guideline.cpp
@@ -112,8 +112,8 @@ static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf)
cairo_set_line_cap(buf->ct, CAIRO_LINE_CAP_SQUARE);
cairo_set_font_size(buf->ct, 10);
- int px = (int) Inkscape::round(gl->point_on_line[Geom::X]);
- int py = (int) Inkscape::round(gl->point_on_line[Geom::Y]);
+ int px = round(gl->point_on_line[Geom::X]);
+ int py = round(gl->point_on_line[Geom::Y]);
if (gl->label) {
cairo_save(buf->ct);
@@ -126,12 +126,12 @@ static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf)
}
if (gl->is_vertical()) {
- int position = (int) Inkscape::round(gl->point_on_line[Geom::X]);
+ int position = round(gl->point_on_line[Geom::X]);
cairo_move_to(buf->ct, position + 0.5, buf->rect.y0 + 0.5);
cairo_line_to(buf->ct, position + 0.5, buf->rect.y1 - 0.5);
cairo_stroke(buf->ct);
} else if (gl->is_horizontal()) {
- int position = (int) Inkscape::round(gl->point_on_line[Geom::Y]);
+ int position = round(gl->point_on_line[Geom::Y]);
cairo_move_to(buf->ct, buf->rect.x0 + 0.5, position + 0.5);
cairo_line_to(buf->ct, buf->rect.x1 - 0.5, position + 0.5);
cairo_stroke(buf->ct);
@@ -193,9 +193,9 @@ static void sp_guideline_update(SPCanvasItem *item, Geom::Affine const &affine,
sp_canvas_item_request_update(SP_CANVAS_ITEM (gl->origin));
if (gl->is_horizontal()) {
- sp_canvas_update_bbox (item, -1000000, (int) Inkscape::round(gl->point_on_line[Geom::Y] - 16), 1000000, (int) Inkscape::round(gl->point_on_line[Geom::Y] + 1));
+ sp_canvas_update_bbox (item, -1000000, round(gl->point_on_line[Geom::Y] - 16), 1000000, round(gl->point_on_line[Geom::Y] + 1));
} else if (gl->is_vertical()) {
- sp_canvas_update_bbox (item, (int) Inkscape::round(gl->point_on_line[Geom::X]), -1000000, (int) Inkscape::round(gl->point_on_line[Geom::X] + 16), 1000000);
+ sp_canvas_update_bbox (item, round(gl->point_on_line[Geom::X]), -1000000, round(gl->point_on_line[Geom::X] + 16), 1000000);
} else {
//TODO: labels in angled guidelines are not showing up for some reason.
sp_canvas_update_bbox (item, -1000000, -1000000, 1000000, 1000000);
diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp
index 089d6de40..d09f66a2f 100644
--- a/src/display/nr-arena-glyphs.cpp
+++ b/src/display/nr-arena-glyphs.cpp
@@ -135,10 +135,10 @@ nr_arena_glyphs_update(NRArenaItem *item, NRRectL */*area*/, NRGC *gc, guint /*s
}
if (b) {
- item->bbox.x0 = static_cast<NR::ICoord>(floor(b->left()));
- item->bbox.y0 = static_cast<NR::ICoord>(floor(b->top()));
- item->bbox.x1 = static_cast<NR::ICoord>(ceil (b->right()));
- item->bbox.y1 = static_cast<NR::ICoord>(ceil (b->bottom()));
+ item->bbox.x0 = floor(b->left());
+ item->bbox.y0 = floor(b->top());
+ item->bbox.x1 = ceil (b->right());
+ item->bbox.y1 = ceil (b->bottom());
} else {
item->bbox.x0 = 0;
item->bbox.y0 = 0;
@@ -282,7 +282,8 @@ nr_arena_glyphs_group_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint s
}
-static unsigned int nr_arena_glyphs_group_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock * /*pb*/, unsigned int /*flags*/)
+static unsigned int
+nr_arena_glyphs_group_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock * /*pb*/, unsigned int /*flags*/)
{
NRArenaItem *child = 0;
@@ -352,20 +353,34 @@ static unsigned int nr_arena_glyphs_group_render(cairo_t *ct, NRArenaItem *item,
return item->state;
}
-static unsigned int nr_arena_glyphs_group_clip(cairo_t * /*ct*/, NRArenaItem *item, NRRectL * /*area*/)
+static unsigned int nr_arena_glyphs_group_clip(cairo_t *ct, NRArenaItem *item, NRRectL * /*area*/)
{
- //NRArenaGroup *group = NR_ARENA_GROUP(item);
+ NRArenaGroup *ggroup = NR_ARENA_GLYPHS_GROUP(item);
- guint ret = item->state;
+ cairo_save(ct);
+ // handle clip-rule
+ if (ggroup->style) {
+ if (ggroup->style->clip_rule.computed == SP_WIND_RULE_EVENODD) {
+ cairo_set_fill_rule(ct, CAIRO_FILL_RULE_EVEN_ODD);
+ } else {
+ cairo_set_fill_rule(ct, CAIRO_FILL_RULE_WINDING);
+ }
+ }
+ ink_cairo_transform(ct, ggroup->ctm);
+
+ for (NRArenaItem *child = ggroup->children; child != NULL; child = child->next) {
+ NRArenaGlyphs *g = NR_ARENA_GLYPHS(child);
+ Geom::PathVector const &pathv = *g->font->PathVector(g->glyph);
- // Render children fill mask
- /*
- for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
- ret = nr_arena_glyphs_fill_mask(NR_ARENA_GLYPHS(child), area, pb);
- if (!(ret & NR_ARENA_ITEM_STATE_RENDER)) return ret;
- }*/
+ cairo_save(ct);
+ ink_cairo_transform(ct, g->g_transform);
+ feed_pathvector_to_cairo(ct, pathv);
+ cairo_restore(ct);
+ }
+ cairo_fill(ct);
+ cairo_restore(ct);
- return ret;
+ return item->state;
}
static NRArenaItem *
diff --git a/src/display/nr-arena-group.cpp b/src/display/nr-arena-group.cpp
index 97f92d02d..1d552fbc2 100644
--- a/src/display/nr-arena-group.cpp
+++ b/src/display/nr-arena-group.cpp
@@ -12,9 +12,12 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include "display/canvas-bpath.h"
+#include "display/nr-arena.h"
#include "display/nr-arena-group.h"
#include "display/nr-filter.h"
#include "display/nr-filter-types.h"
+#include "display/rendermode.h"
#include "style.h"
#include "sp-filter.h"
#include "sp-filter-reference.h"
@@ -163,10 +166,9 @@ static unsigned int
nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int state, unsigned int reset)
{
unsigned int newstate;
-
NRArenaGroup *group = NR_ARENA_GROUP (item);
-
unsigned int beststate = NR_ARENA_ITEM_STATE_ALL;
+ bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
NRGC cgc(gc);
@@ -176,10 +178,10 @@ nr_arena_group_update (NRArenaItem *item, NRRectL *area, NRGC *gc, unsigned int
}
if (beststate & NR_ARENA_ITEM_STATE_BBOX) {
- nr_rect_l_set_empty (&item->bbox);
+ item->bbox = NR_RECT_L_EMPTY;
for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
if (child->visible)
- nr_rect_l_union (&item->bbox, &item->bbox, &child->drawbox);
+ nr_rect_l_union (&item->bbox, &item->bbox, outline ? &child->bbox : &child->drawbox);
}
}
@@ -234,10 +236,8 @@ static unsigned int
nr_arena_group_clip (cairo_t *ct, NRArenaItem *item, NRRectL *area)
{
NRArenaGroup *group = NR_ARENA_GROUP (item);
-
unsigned int ret = item->state;
- /* Just compose children into parent buffer */
for (NRArenaItem *child = group->children; child != NULL; child = child->next) {
ret = nr_arena_item_invoke_clip (ct, child, area);
if (ret & NR_ARENA_ITEM_STATE_INVALID) break;
diff --git a/src/display/nr-arena-image.cpp b/src/display/nr-arena-image.cpp
index 36d733eb8..a943a6214 100644
--- a/src/display/nr-arena-image.cpp
+++ b/src/display/nr-arena-image.cpp
@@ -301,7 +301,7 @@ nr_arena_image_rect (NRArenaImage *image)
Geom::Point p(image->ox, image->oy);
Geom::Point wh(vw, vh);
Geom::Rect view(p, p+wh);
- Geom::OptRect res = Geom::intersect(r, view);
+ Geom::OptRect res = r & view;
r = res ? *res : r;
}
diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp
index 526882921..9ca5a7463 100644
--- a/src/display/nr-arena-item.cpp
+++ b/src/display/nr-arena-item.cpp
@@ -21,6 +21,7 @@
#include "display/cairo-utils.h"
#include "display/cairo-templates.h"
+#include "display/canvas-arena.h"
#include "nr-arena.h"
#include "nr-arena-item.h"
#include "gc-core.h"
@@ -214,6 +215,7 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc,
{
NRGC childgc (gc);
bool filter = (item->arena->rendermode == Inkscape::RENDERMODE_NORMAL);
+ bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
@@ -242,7 +244,7 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc,
return item->state;
/* Test whether to return immediately */
if (area && (item->state & NR_ARENA_ITEM_STATE_BBOX)) {
- if (!nr_rect_l_test_intersect_ptr(area, &item->drawbox))
+ if (!nr_rect_l_test_intersect_ptr(area, outline ? &item->bbox : &item->drawbox))
return item->state;
}
@@ -275,8 +277,6 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc,
} else {
memcpy(&item->drawbox, &item->bbox, sizeof(item->bbox));
}
- // fixme: to fix the display glitches, in outline mode bbox must be a combination of
- // full item bbox and its clip and mask (after we have the API to get these)
/* Clipping */
if (item->clip) {
@@ -288,8 +288,12 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc,
item->state |= NR_ARENA_ITEM_STATE_INVALID;
return item->state;
}
- // for clipping, we need geometric bbox
- nr_rect_l_intersect (&item->drawbox, &item->drawbox, &item->clip->bbox);
+ if (outline) {
+ nr_rect_l_union(&item->bbox, &item->bbox, &item->clip->bbox);
+ } else {
+ // for clipping, we need geometric bbox
+ nr_rect_l_intersect (&item->drawbox, &item->drawbox, &item->clip->bbox);
+ }
}
/* Masking */
if (item->mask) {
@@ -298,8 +302,12 @@ nr_arena_item_invoke_update (NRArenaItem *item, NRRectL *area, NRGC *gc,
item->state |= NR_ARENA_ITEM_STATE_INVALID;
return item->state;
}
- // for masking, we need full drawbox of mask
- nr_rect_l_intersect (&item->drawbox, &item->drawbox, &item->mask->drawbox);
+ if (outline) {
+ nr_rect_l_union(&item->bbox, &item->bbox, &item->mask->bbox);
+ } else {
+ // for masking, we need full drawbox of mask
+ nr_rect_l_intersect (&item->drawbox, &item->drawbox, &item->mask->drawbox);
+ }
}
// now that we know drawbox, dirty the corresponding rect on canvas:
@@ -349,18 +357,14 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
if (!item->visible)
return item->state | NR_ARENA_ITEM_STATE_RENDER;
- // carea is the bounding box for intermediate rendering.
- // NOTE: carea might be larger than area, because of filter effects.
- NRRectL carea;
- nr_rect_l_intersect (&carea, area, &item->drawbox);
- if (nr_rect_l_test_empty(carea))
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
- if (item->filter && filter) {
- item->filter->area_enlarge (carea, item);
- nr_rect_l_intersect (&carea, &carea, &item->drawbox);
- }
-
if (outline) {
+ // intersect with bbox rather than drawbox, as we want to render things outside
+ // of the clipping path as well
+ NRRectL carea;
+ nr_rect_l_intersect (&carea, area, &item->bbox);
+ if (nr_rect_l_test_empty(carea))
+ return item->state | NR_ARENA_ITEM_STATE_RENDER;
+
// No caching in outline mode for now; investigate if it really gives any advantage with cairo.
// Also no attempts to clip anything; just render everything: item, clip, mask
// First, render the object itself
@@ -388,121 +392,143 @@ nr_arena_item_invoke_render (cairo_t *ct, NRArenaItem *item, NRRectL const *area
return item->state | NR_ARENA_ITEM_STATE_RENDER;
}
+
+ // carea is the bounding box for intermediate rendering.
+ // NOTE: carea might be larger than area, because of filter effects.
+ NRRectL carea;
+ nr_rect_l_intersect (&carea, area, &item->drawbox);
+ if (nr_rect_l_test_empty(carea))
+ return item->state | NR_ARENA_ITEM_STATE_RENDER;
+ if (item->filter && filter) {
+ item->filter->area_enlarge (carea, item);
+ nr_rect_l_intersect (&carea, &carea, &item->drawbox);
+ }
using namespace Inkscape;
- // clipping and masks
- unsigned int state;
-
- cairo_t *this_ct = ct;
- NRRectL *this_area = const_cast<NRRectL*>(area);
+ unsigned state;
+ unsigned retstate;
+ // determine whether this shape needs intermediate rendering.
bool needs_intermediate_rendering = false;
bool &nir = needs_intermediate_rendering;
bool needs_opacity = (item->opacity != 255 && !item->render_opacity);
// this item needs an intermediate rendering if:
- nir |= (item->mask != NULL); // 1. it has a mask
- nir |= (item->filter != NULL && filter); // 2. it has a filter
- nir |= needs_opacity; // 3. it is non-opaque
+ nir |= (item->clip != NULL); // 1. it has a clipping path
+ nir |= (item->mask != NULL); // 2. it has a mask
+ nir |= (item->filter != NULL && filter); // 3. it has a filter
+ nir |= needs_opacity; // 4. it is non-opaque
double opacity = static_cast<double>(item->opacity) / 255.0;
- if (needs_intermediate_rendering) {
- cairo_surface_t *intermediate = cairo_surface_create_similar(
- cairo_get_target(ct), CAIRO_CONTENT_COLOR_ALPHA,
- carea.x1 - carea.x0, carea.y1 - carea.y0);
- this_ct = cairo_create(intermediate);
- cairo_translate(this_ct, -carea.x0, -carea.y0);
- this_area = &carea;
- cairo_surface_destroy(intermediate); // the surface will be held in memory by this_ct
- } else {
- cairo_reference(this_ct);
- }
+ /* How the rendering is done.
+ *
+ * Clipping, masking and opacity are done by rendering them to a surface
+ * and then compositing the object's rendering onto it with the IN operator.
+ * The object itself is rendered to a group.
+ *
+ * Opacity is done by rendering the clipping path with an alpha
+ * value corresponding to the opacity. If there is no clipping path,
+ * the entire intermediate surface is painted with alpha corresponding
+ * to the opacity value.
+ */
- // The pipeline needs to be different for filters.
- // First we render the item into an intermediate surface. Then the filter rotates
- // the surface to user coordinates (if necessary) and runs the rendering.
- // Once that's done we retrieve the result, rotating it back to screen coords.
- // Clipping and masking happens after the filter result is ready.
- if (item->filter && filter) {
+ // short-circuit the simple case.
+ if (!needs_intermediate_rendering) {
+ state = NR_ARENA_ITEM_VIRTUAL (item, render) (ct, item, &carea, pb, flags);
+ if (state & NR_ARENA_ITEM_STATE_INVALID) {
+ item->state |= NR_ARENA_ITEM_STATE_INVALID;
+ return item->state;
+ }
+ return item->state | NR_ARENA_ITEM_STATE_RENDER;
}
- Cairo::Context cct(this_ct, true);
- Cairo::Context base_ct(ct);
- Cairo::RefPtr<Cairo::Pattern> mask;
- CairoSave clipsave(ct); // RAII for save / restore
- CairoGroup maskgroup(this_ct); // RAII for push_group / pop_group
- CairoGroup drawgroup(this_ct);
- CairoGroup maskopacitygroup(this_ct);
-
- // always clip the base context, not the one on the intermediate surface
- // this is because filters must be done before clipping
+ cairo_surface_t *intermediate = cairo_surface_create_similar(
+ cairo_get_group_target(ct), CAIRO_CONTENT_COLOR_ALPHA,
+ carea.x1 - carea.x0, carea.y1 - carea.y0);
+ cairo_t *ict = cairo_create(intermediate);
+ cairo_translate(ict, -carea.x0, -carea.y0);
+
+ // 1. Render clipping path with alpha = opacity.
+ cairo_set_source_rgba(ict, 0,0,0,opacity);
+ // Since clip can be combined with opacity, the result could be incorrect
+ // for overlapping clip children. To fix this we use the SOURCE operator
+ // instead of the default OVER.
+ cairo_set_operator(ict, CAIRO_OPERATOR_SOURCE);
if (item->clip) {
- clipsave.save();
- state = nr_arena_item_invoke_clip(ct, item->clip, const_cast<NRRectL*>(area));
+ state = nr_arena_item_invoke_clip(ict, item->clip, const_cast<NRRectL*>(area));
if (state & NR_ARENA_ITEM_STATE_INVALID) {
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
+ retstate = (item->state |= NR_ARENA_ITEM_STATE_INVALID);
+ goto cleanup;
}
- base_ct.clip();
+ } else {
+ // if there is no clipping path, fill the entire surface with alpha = opacity.
+ cairo_paint(ict);
}
+ // reset back to default
+ cairo_set_operator(ict, CAIRO_OPERATOR_OVER);
- // render mask on the intermediate context and store it
+ // 2. Render the mask if present and compose it with the clipping path + opacity.
if (item->mask) {
- maskgroup.push_with_content(CAIRO_CONTENT_COLOR_ALPHA);
- // handle opacity of a masked object by composing it with the mask
- if (needs_opacity) {
- maskopacitygroup.push();
- }
- state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (this_ct, item->mask, this_area, pb, flags);
+ cairo_push_group(ict);
+ state = NR_ARENA_ITEM_VIRTUAL (item->mask, render) (ict, item->mask, &carea, NULL, flags);
if (state & NR_ARENA_ITEM_STATE_INVALID) {
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
- }
- if (needs_opacity) {
- maskopacitygroup.pop_to_source();
- cct.paint_with_alpha(opacity);
+ retstate = (item->state |= NR_ARENA_ITEM_STATE_INVALID);
+ goto cleanup;
}
- mask = maskgroup.popmm();
- // convert luminance to alpha
- cairo_pattern_t *p = mask->cobj();
- cairo_surface_t *s;
- cairo_pattern_get_surface(p, &s);
- ink_cairo_surface_filter(s, s, MaskLuminanceToAlpha());
+ cairo_surface_t *mask_s = cairo_get_group_target(ict);
+ // Convert mask's luminance to alpha
+ ink_cairo_surface_filter(mask_s, mask_s, MaskLuminanceToAlpha());
+ cairo_pop_group_to_source(ict);
+ cairo_set_operator(ict, CAIRO_OPERATOR_IN);
+ cairo_paint(ict);
+ cairo_set_operator(ict, CAIRO_OPERATOR_OVER);
}
- // render the object (possibly to the intermediate surface)
- state = NR_ARENA_ITEM_VIRTUAL (item, render) (this_ct, item, this_area, pb, flags);
+ // 3. Render object itself.
+ cairo_push_group(ict);
+ state = NR_ARENA_ITEM_VIRTUAL (item, render) (ict, item, &carea, pb, flags);
if (state & NR_ARENA_ITEM_STATE_INVALID) {
- /* Clean up and return error */
- item->state |= NR_ARENA_ITEM_STATE_INVALID;
- return item->state;
+ retstate = (item->state |= NR_ARENA_ITEM_STATE_INVALID);
+ goto cleanup;
}
- // apply filter
+ // 4. Apply filter.
if (item->filter && filter) {
- item->filter->render(item, ct, area, this_ct, &carea);
- }
-
- if (needs_intermediate_rendering) {
- cairo_surface_t *intermediate = cairo_get_target(this_ct);
- cairo_set_source_surface(ct, intermediate, carea.x0, carea.y0);
- if (mask) {
- cairo_mask(ct, mask->cobj());
- // opacity of masked objects is handled by premultiplying the mask
+ // HACK: SPCanvasArena doesn't exist when this is called for offscreen rendering
+ // Proper fix: call this function with a drawing context class
+ // that contains information about the surface's bounds
+ NRRectL bgarea;
+ if (flags & NR_ARENA_ITEM_RENDER_NO_CACHE || !item->arena->canvasarena) {
+ bgarea = carea;
} else {
- // opacity of non-masked objects must be rendered explicitly
- if (needs_opacity) {
- cairo_paint_with_alpha(ct, opacity);
- } else {
- cairo_paint(ct);
- }
+ bgarea = NRRectL(item->arena->canvasarena->cache_area);
}
- cairo_set_source_rgba(ct,0,0,0,0);
+ item->filter->render(item, ct, &bgarea, ict, &carea);
+ // Note that because the object was rendered to a group,
+ // the internals of the filter need to use cairo_get_group_target()
+ // instead of cairo_get_target().
}
- return item->state | NR_ARENA_ITEM_STATE_RENDER;
+ // 5. Render object inside the composited mask + clip
+ cairo_pop_group_to_source(ict);
+ cairo_set_operator(ict, CAIRO_OPERATOR_IN);
+ cairo_paint(ict);
+
+ // 6. Paint the completed rendering onto the base context
+ cairo_set_source_surface(ct, intermediate, carea.x0, carea.y0);
+ cairo_paint(ct);
+ cairo_set_source_rgba(ct, 0,0,0,0);
+ // the call above is to clear a ref on the intermediate surface held by ct
+
+ retstate = item->state | NR_ARENA_ITEM_STATE_RENDER;
+
+ cleanup:
+ cairo_destroy(ict);
+ cairo_surface_destroy(intermediate);
+
+ return retstate;
}
unsigned int
@@ -511,16 +537,6 @@ nr_arena_item_invoke_clip (cairo_t *ct, NRArenaItem *item, NRRectL *area)
nr_return_val_if_fail (item != NULL, NR_ARENA_ITEM_STATE_INVALID);
nr_return_val_if_fail (NR_IS_ARENA_ITEM (item),
NR_ARENA_ITEM_STATE_INVALID);
- /* we originally short-circuited if the object state included
- * NR_ARENA_ITEM_STATE_CLIP (and showed a warning on the console);
- * anyone know why we stopped doing so?
- */
- /*nr_return_val_if_fail ((pb->area.x1 - pb->area.x0) >=
- (area->x1 - area->x0),
- NR_ARENA_ITEM_STATE_INVALID);
- nr_return_val_if_fail ((pb->area.y1 - pb->area.y0) >=
- (area->y1 - area->y0),
- NR_ARENA_ITEM_STATE_INVALID);*/
#ifdef NR_ARENA_ITEM_VERBOSE
printf ("Invoke clip by %p: %d %d - %d %d, item bbox %d %d - %d %d\n",
@@ -528,15 +544,40 @@ nr_arena_item_invoke_clip (cairo_t *ct, NRArenaItem *item, NRRectL *area)
(&item->bbox)->y0, (&item->bbox)->x1, (&item->bbox)->y1);
#endif
+ unsigned retstate = 0;
+
+ // don't bother if the object does not implement clipping (e.g. NRArenaImage)
+ if (!((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->clip)
+ return retstate;
+
if (item->visible && nr_rect_l_test_intersect_ptr(area, &item->bbox)) {
- /* Need render that item */
- if (((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->clip) {
- return ((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->
- clip (ct, item, area);
+ // The item used as the clipping path itself has a clipping path.
+ // Render this item's clipping path onto a temporary surface, then composite it with the item
+ // using the IN operator
+ if (item->clip) {
+ cairo_push_group_with_content(ct, CAIRO_CONTENT_ALPHA);
+ cairo_save(ct);
+ cairo_set_source_rgba(ct, 0,0,0,1);
+ nr_arena_item_invoke_clip(ct, item->clip, area);
+ cairo_restore(ct);
+ cairo_push_group_with_content(ct, CAIRO_CONTENT_ALPHA);
+ }
+
+ // rasterize the clipping path
+ retstate = ((NRArenaItemClass *) NR_OBJECT_GET_CLASS (item))->
+ clip (ct, item, area);
+
+ if (item->clip) {
+ cairo_pop_group_to_source(ct);
+ cairo_set_operator(ct, CAIRO_OPERATOR_IN);
+ cairo_paint(ct);
+ cairo_pop_group_to_source(ct);
+ cairo_set_operator(ct, CAIRO_OPERATOR_SOURCE);
+ cairo_paint(ct);
}
}
- return item->state;
+ return retstate;
}
NRArenaItem *
@@ -597,7 +638,8 @@ nr_arena_item_request_render (NRArenaItem *item)
nr_return_if_fail (item != NULL);
nr_return_if_fail (NR_IS_ARENA_ITEM (item));
- nr_arena_request_render_rect (item->arena, &item->drawbox);
+ bool outline = (item->arena->rendermode == Inkscape::RENDERMODE_OUTLINE);
+ nr_arena_request_render_rect (item->arena, outline ? &item->bbox : &item->drawbox);
}
/* Public */
diff --git a/src/display/nr-arena-item.h b/src/display/nr-arena-item.h
index 0fc4cbe48..d65a75ed8 100644
--- a/src/display/nr-arena-item.h
+++ b/src/display/nr-arena-item.h
@@ -15,6 +15,8 @@
#include <cairo.h>
#include <2geom/affine.h>
+#include <2geom/rect.h>
+#include "libnr/nr-forward.h"
#include "libnr/nr-rect-l.h"
#include "libnr/nr-object.h"
#include "gc-soft-ptr.h"
diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp
index eb7a30e58..6d65611bf 100644
--- a/src/display/nr-arena-shape.cpp
+++ b/src/display/nr-arena-shape.cpp
@@ -21,6 +21,7 @@
#include <2geom/svg-path-parser.h>
#include "display/cairo-utils.h"
#include "display/canvas-arena.h"
+#include "display/canvas-bpath.h"
#include "display/curve.h"
#include "display/nr-arena.h"
#include "display/nr-arena-shape.h"
@@ -223,10 +224,10 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
if (shape->curve) {
boundingbox = bounds_exact_transformed(shape->curve->get_pathvector(), gc->transform);
if (boundingbox) {
- item->bbox.x0 = static_cast<NR::ICoord>(floor((*boundingbox)[0][0])); // Floor gives the coordinate in which the point resides
- item->bbox.y0 = static_cast<NR::ICoord>(floor((*boundingbox)[1][0]));
- item->bbox.x1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[0][1])); // Ceil gives the first coordinate beyond the point
- item->bbox.y1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[1][1]));
+ item->bbox.x0 = floor((*boundingbox)[0][0]); // Floor gives the coordinate in which the point resides
+ item->bbox.y0 = floor((*boundingbox)[1][0]);
+ item->bbox.x1 = ceil ((*boundingbox)[0][1]); // Ceil gives the first coordinate beyond the point
+ item->bbox.y1 = ceil ((*boundingbox)[1][1]);
} else {
item->bbox = NR_RECT_L_EMPTY;
}
@@ -274,10 +275,10 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g
/// \todo just write item->bbox = boundingbox
if (boundingbox) {
- shape->approx_bbox.x0 = static_cast<NR::ICoord>(floor((*boundingbox)[0][0]));
- shape->approx_bbox.y0 = static_cast<NR::ICoord>(floor((*boundingbox)[1][0]));
- shape->approx_bbox.x1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[0][1]));
- shape->approx_bbox.y1 = static_cast<NR::ICoord>(ceil ((*boundingbox)[1][1]));
+ shape->approx_bbox.x0 = floor(boundingbox->left());
+ shape->approx_bbox.y0 = floor(boundingbox->top());
+ shape->approx_bbox.x1 = ceil (boundingbox->right());
+ shape->approx_bbox.y1 = ceil (boundingbox->bottom());
} else {
shape->approx_bbox = NR_RECT_L_EMPTY;
}
@@ -396,22 +397,26 @@ nr_arena_shape_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPixBlock
static guint nr_arena_shape_clip(cairo_t *ct, NRArenaItem *item, NRRectL * /*area*/)
{
- guint result = 0;
-
- // NOTE: for now this is incorrect, because it doesn't honor clip-rule,
- // and will be incorrect for nested clipping paths.
NRArenaShape *shape = NR_ARENA_SHAPE(item);
if (!shape->curve) {
- result = item->state;
- } else {
- cairo_save(ct);
- ink_cairo_transform(ct, shape->ctm);
- feed_pathvector_to_cairo(ct, shape->curve->get_pathvector());
- cairo_restore(ct);
+ return item->state;
+ }
- result = item->state;
+ cairo_save(ct);
+ // handle clip-rule
+ if (shape->style) {
+ if (shape->style->clip_rule.computed == SP_WIND_RULE_EVENODD) {
+ cairo_set_fill_rule(ct, CAIRO_FILL_RULE_EVEN_ODD);
+ } else {
+ cairo_set_fill_rule(ct, CAIRO_FILL_RULE_WINDING);
+ }
}
- return result;
+ ink_cairo_transform(ct, shape->ctm);
+ feed_pathvector_to_cairo(ct, shape->curve->get_pathvector());
+ cairo_fill(ct);
+ cairo_restore(ct);
+
+ return item->state;
}
static NRArenaItem *
diff --git a/src/display/nr-arena-shape.h b/src/display/nr-arena-shape.h
index 2ee0d24c8..7b86f7f59 100644
--- a/src/display/nr-arena-shape.h
+++ b/src/display/nr-arena-shape.h
@@ -22,6 +22,7 @@
#include "forward.h"
#include "nr-arena-item.h"
#include "nr-style.h"
+#include "libnr/nr-rect.h"
NRType nr_arena_shape_get_type (void);
diff --git a/src/display/nr-arena.cpp b/src/display/nr-arena.cpp
index 43edb6918..ce62a81dc 100644
--- a/src/display/nr-arena.cpp
+++ b/src/display/nr-arena.cpp
@@ -18,6 +18,7 @@
#include "nr-filter-types.h"
#include "preferences.h"
#include "color.h"
+#include "libnr/nr-rect.h"
static void nr_arena_class_init (NRArenaClass *klass);
static void nr_arena_init (NRArena *arena);
diff --git a/src/display/nr-filter-composite.cpp b/src/display/nr-filter-composite.cpp
index d4cf47af4..694ccaec5 100644
--- a/src/display/nr-filter-composite.cpp
+++ b/src/display/nr-filter-composite.cpp
@@ -11,7 +11,6 @@
#include <cmath>
-#include "2geom/isnan.h"
#include "display/cairo-templates.h"
#include "display/cairo-utils.h"
#include "display/nr-filter-composite.h"
diff --git a/src/display/nr-filter-displacement-map.cpp b/src/display/nr-filter-displacement-map.cpp
index fdaf2c887..15200223b 100644
--- a/src/display/nr-filter-displacement-map.cpp
+++ b/src/display/nr-filter-displacement-map.cpp
@@ -28,128 +28,6 @@ FilterPrimitive * FilterDisplacementMap::create() {
FilterDisplacementMap::~FilterDisplacementMap()
{}
-#if 0
-struct pixel_t {
- unsigned char channels[4];
- inline unsigned char operator[](int c) const { return channels[c]; }
- inline unsigned char& operator[](int c) { return channels[c]; }
- static inline pixel_t blank() {
- pixel_t p;
- for(unsigned int i=0; i<4; i++) {
- p[i] = 0;
- }
- return p;
- }
-};
-
-static inline pixel_t pixelValue(NRPixBlock const* pb, int x, int y) {
- if ( x < pb->area.x0 || x >= pb->area.x1 || y < pb->area.y0 || y >= pb->area.y1 ) return pixel_t::blank(); // This assumes anything outside the defined range is (0,0,0,0)
- pixel_t const* rowData = reinterpret_cast<pixel_t const*>(NR_PIXBLOCK_PX(pb) + (y-pb->area.y0)*pb->rs);
- return rowData[x-pb->area.x0];
-}
-
-template<bool PREMULTIPLIED>
-static pixel_t interpolatePixels(NRPixBlock const* pb, double x, double y) {
- // NOTE: The values of x and y are shifted by -0.5 (the "true" values would be x+0.5 and y+0.5).
- // This is done because otherwise the pixel values first have to be shifted by +0.5 and then by -0.5 again...
- unsigned int const sfl = 8u;
- unsigned int const sf = 1u<<sfl;
- unsigned int const sf2h = 1u<<(2u*sfl-1);
- int xi = (int)floor(x), yi = (int)floor(y);
- unsigned int xf = static_cast<unsigned int>(round(sf * (x - xi))),
- yf = static_cast<unsigned int>(round(sf * (y - yi)));
- pixel_t p00 = pixelValue(pb, xi+0, yi+0);
- pixel_t p01 = pixelValue(pb, xi+1, yi+0);
- pixel_t p10 = pixelValue(pb, xi+0, yi+1);
- pixel_t p11 = pixelValue(pb, xi+1, yi+1);
-
- /* It's a good idea to interpolate premultiplied colors:
- *
- * Consider two pixels, one being rgba(255,0,0,0), which is fully transparent,
- * and the other being rgba(0,0,255,255), or blue (fully opaque).
- * If these two colors are interpolated the expected result would be bluish pixels
- * containing no red.
- *
- * However, if our final alpha value is zero, then the RGB values aren't really determinate.
- * We might as well avoid premultiplication in this case, which still gives us a fully
- * transparent result, but with interpolated RGB parts. */
-
- pixel_t r;
- if (PREMULTIPLIED) {
- /* Premultiplied, so do simple interpolation. */
- for (unsigned i = 0; i != 4; ++i) {
- // y0,y1 have range [0,a*sf]
- unsigned const y0 = sf*p00[i] + xf*((unsigned int)p01[i]-(unsigned int)p00[i]);
- unsigned const y1 = sf*p10[i] + xf*((unsigned int)p11[i]-(unsigned int)p10[i]);
-
- unsigned const ri = sf*y0 + yf*(y1-y0); // range [0,a*sf*sf]
- r[i] = (ri + sf2h)>>(2*sfl); // range [0,a]
- }
- } else {
- /* First calculate interpolated alpha value. */
- unsigned const y0 = sf*p00[3] + xf*((unsigned int)p01[3]-(unsigned int)p00[3]); // range [0,a*sf]
- unsigned const y1 = sf*p10[3] + xf*((unsigned int)p11[3]-(unsigned int)p10[3]);
- unsigned const ra = sf*y0 + yf*(y1-y0); // range [0,a*sf*sf]
-
- if (ra==0) {
- /* Fully transparent, so do simple interpolation. */
- for (unsigned i = 0; i != 3; ++i) {
- // y0,y1 have range [0,255*sf]
- unsigned const y0 = sf*p00[i] + xf*((unsigned int)p01[i]-(unsigned int)p00[i]);
- unsigned const y1 = sf*p10[i] + xf*((unsigned int)p11[i]-(unsigned int)p10[i]);
-
- unsigned const ri = sf*y0 + yf*(y1-y0); // range [0,255*sf*sf]
- r[i] = (ri + sf2h)>>(2*sfl); // range [0,255]
- }
- r[3] = 0;
- } else {
- /* Do premultiplication ourselves. */
- for (unsigned i = 0; i != 3; ++i) {
- // Premultiplied versions. Range [0,255*a].
- unsigned const c00 = p00[i]*p00[3];
- unsigned const c01 = p01[i]*p01[3];
- unsigned const c10 = p10[i]*p10[3];
- unsigned const c11 = p11[i]*p11[3];
-
- // Interpolation.
- unsigned const y0 = sf*c00 + xf*(c01-c00); // range [0,255*a*sf]
- unsigned const y1 = sf*c10 + xf*(c11-c10); // range [0,255*a*sf]
- unsigned const ri = sf*y0 + yf*(y1-y0); // range [0,255*a*sf*sf]
- r[i] = (ri + ra/2) / ra; // range [0,255]
- }
- r[3] = (ra + sf2h)>>(2*sfl); // range [0,a]
- }
- }
-
- return r;
-}
-
-template<bool MAP_PREMULTIPLIED, bool DATA_PREMULTIPLIED>
-static void performDisplacement(NRPixBlock const* texture, NRPixBlock const* map, int Xchannel, int Ychannel, NRPixBlock* out, double scalex, double scaley) {
- bool Xneedsdemul = MAP_PREMULTIPLIED && Xchannel<3;
- bool Yneedsdemul = MAP_PREMULTIPLIED && Ychannel<3;
- if (!Xneedsdemul) scalex /= 255.0;
- if (!Yneedsdemul) scaley /= 255.0;
-
- for (int yout=out->area.y0; yout < out->area.y1; yout++){
- pixel_t const* mapRowData = reinterpret_cast<pixel_t const*>(NR_PIXBLOCK_PX(map) + (yout-map->area.y0)*map->rs);
- pixel_t* outRowData = reinterpret_cast<pixel_t*>(NR_PIXBLOCK_PX(out) + (yout-out->area.y0)*out->rs);
- for (int xout=out->area.x0; xout < out->area.x1; xout++){
- pixel_t const mapValue = mapRowData[xout-map->area.x0];
-
- double xtex = xout + (Xneedsdemul ? // Although the value of the pixel corresponds to the MIDDLE of the pixel, no +0.5 is needed because we're interpolating pixels anyway (so to get the actual pixel locations 0.5 would have to be subtracted again).
- (mapValue[3]==0?0:(scalex * (mapValue[Xchannel] - mapValue[3]*0.5) / mapValue[3])) :
- (scalex * (mapValue[Xchannel] - 127.5)));
- double ytex = yout + (Yneedsdemul ?
- (mapValue[3]==0?0:(scaley * (mapValue[Ychannel] - mapValue[3]*0.5) / mapValue[3])) :
- (scaley * (mapValue[Ychannel] - 127.5)));
-
- outRowData[xout-out->area.x0] = interpolatePixels<DATA_PREMULTIPLIED>(texture, xtex, ytex);
- }
- }
-}
-#endif
-
struct Displace {
Displace(cairo_surface_t *texture, cairo_surface_t *map,
unsigned xch, unsigned ych, double scalex, double scaley)
@@ -206,73 +84,6 @@ void FilterDisplacementMap::render_cairo(FilterSlot &slot)
cairo_surface_destroy(out);
}
-/*
-int FilterDisplacementMap::render(FilterSlot &slot, FilterUnits const &units) {
- NRPixBlock *texture = slot.get(_input);
- NRPixBlock *map = slot.get(_input2);
-
- // Bail out if either one of source images is missing
- if (!map || !texture) {
- g_warning("Missing source image for feDisplacementMap (map=%d texture=%d)", _input, _input2);
- return 1;
- }
-
- NR::IRect area = units.get_pixblock_filterarea_paraller();
- int x0 = std::max(map->area.x0,area.min()[NR::X]);
- int y0 = std::max(map->area.y0,area.min()[NR::Y]);
- int x1 = std::min(map->area.x1,area.max()[NR::X]);
- int y1 = std::min(map->area.y1,area.max()[NR::Y]);
-
- //TODO: check whether we really need this check:
- if (x1 <= x0 || y1 <= y0) return 0; //nothing to do!
-
- if (texture->mode != NR_PIXBLOCK_MODE_R8G8B8A8N && texture->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
- g_warning("Source images without an alpha channel are not supported by feDisplacementMap at the moment.");
- return 1;
- }
-
- NRPixBlock *out = new NRPixBlock;
- nr_pixblock_setup_fast(out, texture->mode, x0, y0, x1, y1, true);
-
- // convert to a suitable format
- bool free_map_on_exit = false;
- if (map->mode != NR_PIXBLOCK_MODE_R8G8B8A8N && map->mode != NR_PIXBLOCK_MODE_R8G8B8A8P) {
- NRPixBlock *original_map = map;
- map = new NRPixBlock;
- nr_pixblock_setup_fast(map, NR_PIXBLOCK_MODE_R8G8B8A8N,
- original_map->area.x0, original_map->area.y0,
- original_map->area.x1, original_map->area.y1,
- false);
- nr_blit_pixblock_pixblock(map, original_map);
- free_map_on_exit = true;
- }
- bool map_premultiplied = (map->mode == NR_PIXBLOCK_MODE_R8G8B8A8P);
- bool data_premultiplied = (out->mode == NR_PIXBLOCK_MODE_R8G8B8A8P);
-
- Geom::Affine trans = units.get_matrix_primitiveunits2pb();
- double scalex = scale * trans.expansionX();
- double scaley = scale * trans.expansionY();
-
- if (map_premultiplied && data_premultiplied) {
- performDisplacement<true,true>(texture, map, Xchannel, Ychannel, out, scalex, scaley);
- } else if (map_premultiplied && !data_premultiplied) {
- performDisplacement<true,false>(texture, map, Xchannel, Ychannel, out, scalex, scaley);
- } else if (data_premultiplied) {
- performDisplacement<false,true>(texture, map, Xchannel, Ychannel, out, scalex, scaley);
- } else {
- performDisplacement<false,false>(texture, map, Xchannel, Ychannel, out, scalex, scaley);
- }
-
- if (free_map_on_exit) {
- nr_pixblock_release(map);
- delete map;
- }
-
- out->empty = FALSE;
- slot.set(_output, out);
- return 0;
-}*/
-
void FilterDisplacementMap::set_input(int slot) {
_input = slot;
}
diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp
index fca066ad4..3a6b425e1 100644
--- a/src/display/nr-filter-gaussian.cpp
+++ b/src/display/nr-filter-gaussian.cpp
@@ -23,8 +23,6 @@
#include <omp.h>
#endif //HAVE_OPENMP
-#include "2geom/isnan.h"
-
#include "display/cairo-utils.h"
#include "display/nr-filter-primitive.h"
#include "display/nr-filter-gaussian.h"
diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp
index ce07ff086..3464fda66 100644
--- a/src/display/nr-filter-slot.cpp
+++ b/src/display/nr-filter-slot.cpp
@@ -156,7 +156,7 @@ cairo_surface_t *FilterSlot::_get_transformed_background()
{
Geom::Affine trans = _units.get_matrix_display2pb();
- cairo_surface_t *bg = cairo_get_target(_background_ct);
+ cairo_surface_t *bg = cairo_get_group_target(_background_ct);
cairo_surface_t *tbg = cairo_surface_create_similar(
bg, cairo_surface_get_content(bg),
_slot_w, _slot_h);
diff --git a/src/display/nr-filter-turbulence.cpp b/src/display/nr-filter-turbulence.cpp
index f3b03c024..60d5ce872 100644
--- a/src/display/nr-filter-turbulence.cpp
+++ b/src/display/nr-filter-turbulence.cpp
@@ -299,7 +299,6 @@ FilterTurbulence::FilterTurbulence()
, numOctaves(1)
, seed(0)
, updated(false)
- , updated_area(NR::IPoint(), NR::IPoint())
, fTileWidth(10) //guessed
, fTileHeight(10) //guessed
, fTileX(1) //guessed
diff --git a/src/display/nr-filter-turbulence.h b/src/display/nr-filter-turbulence.h
index 50161b6be..8d3639543 100644
--- a/src/display/nr-filter-turbulence.h
+++ b/src/display/nr-filter-turbulence.h
@@ -64,7 +64,6 @@ private:
bool stitchTiles;
FilterTurbulenceType type;
bool updated;
- NR::IRect updated_area;
unsigned char *pix_data;
double fTileWidth;
diff --git a/src/display/nr-filter-units.cpp b/src/display/nr-filter-units.cpp
index b1c475c41..a8686545a 100644
--- a/src/display/nr-filter-units.cpp
+++ b/src/display/nr-filter-units.cpp
@@ -158,22 +158,13 @@ Geom::Affine FilterUnits::get_matrix_user2primitiveunits() const {
return get_matrix_user2units(primitiveUnits);
}
-NR::IRect FilterUnits::get_pixblock_filterarea_paraller() const {
+Geom::IntRect FilterUnits::get_pixblock_filterarea_paraller() const {
g_assert(filter_area);
- int min_x = INT_MAX, min_y = INT_MAX, max_x = INT_MIN, max_y = INT_MIN;
Geom::Affine u2pb = get_matrix_user2pb();
-
- for (int i = 0 ; i < 4 ; i++) {
- Geom::Point p = filter_area->corner(i);
- p *= u2pb;
- if (p[X] < min_x) min_x = (int)std::floor(p[X]);
- if (p[X] > max_x) max_x = (int)std::ceil(p[X]);
- if (p[Y] < min_y) min_y = (int)std::floor(p[Y]);
- if (p[Y] > max_y) max_y = (int)std::ceil(p[Y]);
- }
- NR::IRect ret(NR::IPoint(min_x, min_y), NR::IPoint(max_x, max_y));
- return ret;
+ Geom::Rect r = *filter_area * u2pb;
+ Geom::IntRect ir = r.roundOutwards();
+ return ir;
}
FilterUnits& FilterUnits::operator=(FilterUnits const &other) {
diff --git a/src/display/nr-filter-units.h b/src/display/nr-filter-units.h
index 2fc3e5533..1cb4fdbce 100644
--- a/src/display/nr-filter-units.h
+++ b/src/display/nr-filter-units.h
@@ -133,7 +133,7 @@ public:
* NOTE: use only in filters, that define TRAIT_PARALLER in
* get_input_traits. The filter effects area may not be representable
* by simple rectangle otherwise. */
- NR::IRect get_pixblock_filterarea_paraller() const;
+ Geom::IntRect get_pixblock_filterarea_paraller() const;
FilterUnits& operator=(FilterUnits const &other);
diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp
index 6e0aa1a42..963d98654 100644
--- a/src/display/nr-filter.cpp
+++ b/src/display/nr-filter.cpp
@@ -160,7 +160,7 @@ int Filter::render(NRArenaItem const *item, cairo_t *bgct, NRRectL const *bgarea
}
}
- FilterSlot slot(const_cast<NRArenaItem*>(item), bgct, bgarea, cairo_get_target(graphic), area, units);
+ FilterSlot slot(const_cast<NRArenaItem*>(item), bgct, bgarea, cairo_get_group_target(graphic), area, units);
slot.set_quality(filterquality);
slot.set_blurquality(blurquality);
@@ -236,10 +236,10 @@ void Filter::compute_drawbox(NRArenaItem const *item, NRRectL &item_bbox) {
Geom::Rect enlarged = filter_effect_area(tmp_bbox);
enlarged = enlarged * item->ctm;
- item_bbox.x0 = (NR::ICoord) floor(enlarged.min()[X]);
- item_bbox.y0 = (NR::ICoord) floor(enlarged.min()[Y]);
- item_bbox.x1 = (NR::ICoord) ceil(enlarged.max()[X]);
- item_bbox.y1 = (NR::ICoord) ceil(enlarged.max()[Y]);
+ item_bbox.x0 = floor(enlarged.min()[X]);
+ item_bbox.y0 = floor(enlarged.min()[Y]);
+ item_bbox.x1 = ceil(enlarged.max()[X]);
+ item_bbox.y1 = ceil(enlarged.max()[Y]);
}
Geom::Rect Filter::filter_effect_area(Geom::Rect const &bbox)
diff --git a/src/display/sp-canvas-item.h b/src/display/sp-canvas-item.h
index 9dbec547e..4c731e56b 100644
--- a/src/display/sp-canvas-item.h
+++ b/src/display/sp-canvas-item.h
@@ -24,8 +24,7 @@
#include <glib-object.h>
#include <gtk/gtk.h>
#include <gdk/gdk.h>
-
-#include "2geom/rect.h"
+#include <2geom/rect.h>
G_BEGIN_DECLS
@@ -65,6 +64,7 @@ struct _SPCanvasItemClass : public GtkObjectClass {
double (* point) (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
int (* event) (SPCanvasItem *item, GdkEvent *event);
+ void (* visible_area_changed) (SPCanvasItem *item, Geom::IntRect const &old_area, Geom::IntRect const &new_area);
};
SPCanvasItem *sp_canvas_item_new(SPCanvasGroup *parent, GType type, const gchar *first_arg_name, ...);
diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp
index 37998437d..d7f34969f 100644
--- a/src/display/sp-canvas.cpp
+++ b/src/display/sp-canvas.cpp
@@ -689,6 +689,7 @@ static void sp_canvas_group_destroy (GtkObject *object);
static void sp_canvas_group_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags);
static double sp_canvas_group_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item);
static void sp_canvas_group_render (SPCanvasItem *item, SPCanvasBuf *buf);
+static void sp_canvas_group_visible_area_changed (SPCanvasItem *item, Geom::IntRect const &old_area, Geom::IntRect const &new_area);
static SPCanvasItemClass *group_parent_class;
@@ -732,6 +733,7 @@ sp_canvas_group_class_init (SPCanvasGroupClass *klass)
item_class->update = sp_canvas_group_update;
item_class->render = sp_canvas_group_render;
item_class->point = sp_canvas_group_point;
+ item_class->visible_area_changed = sp_canvas_group_visible_area_changed;
}
/**
@@ -875,6 +877,20 @@ sp_canvas_group_render (SPCanvasItem *item, SPCanvasBuf *buf)
}
}
+static void
+sp_canvas_group_visible_area_changed (SPCanvasItem *item, Geom::IntRect const &old_area, Geom::IntRect const &new_area)
+{
+ SPCanvasGroup *group = SP_CANVAS_GROUP (item);
+
+ for (GList *list = group->items; list; list = list->next) {
+ SPCanvasItem *child = (SPCanvasItem *)list->data;
+ if (child->flags & SP_CANVAS_ITEM_VISIBLE) {
+ if (SP_CANVAS_ITEM_GET_CLASS (child)->visible_area_changed)
+ SP_CANVAS_ITEM_GET_CLASS (child)->visible_area_changed (child, old_area, new_area);
+ }
+ }
+}
+
/**
* Adds an item to a canvas group.
*/
@@ -1045,7 +1061,7 @@ sp_canvas_init (SPCanvas *canvas)
#if ENABLE_LCMS
canvas->enable_cms_display_adj = false;
- canvas->cms_key = new Glib::ustring("");
+ new (&canvas->cms_key) Glib::ustring("");
#endif // ENABLE_LCMS
canvas->is_scrolling = false;
@@ -1105,6 +1121,8 @@ sp_canvas_destroy (GtkObject *object)
shutdown_transients (canvas);
+ canvas->cms_key.~ustring();
+
if (GTK_OBJECT_CLASS (canvas_parent_class)->destroy)
(* GTK_OBJECT_CLASS (canvas_parent_class)->destroy) (object);
}
@@ -1134,8 +1152,6 @@ sp_canvas_new_aa (void)
static void
sp_canvas_realize (GtkWidget *widget)
{
- SPCanvas *canvas = SP_CANVAS (widget);
-
GdkWindowAttr attributes;
attributes.window_type = GDK_WINDOW_CHILD;
attributes.x = widget->allocation.x;
@@ -1171,8 +1187,6 @@ sp_canvas_realize (GtkWidget *widget)
widget->style = gtk_style_attach (widget->style, widget->window);
gtk_widget_set_realized (widget, TRUE);
-
- canvas->pixmap_gc = gdk_gc_new (SP_CANVAS_WINDOW (canvas));
}
/**
@@ -1189,9 +1203,6 @@ sp_canvas_unrealize (GtkWidget *widget)
shutdown_transients (canvas);
- gdk_gc_destroy (canvas->pixmap_gc);
- canvas->pixmap_gc = NULL;
-
if (GTK_WIDGET_CLASS (canvas_parent_class)->unrealize)
(* GTK_WIDGET_CLASS (canvas_parent_class)->unrealize) (widget);
}
@@ -1216,8 +1227,16 @@ sp_canvas_size_allocate (GtkWidget *widget, GtkAllocation *allocation)
{
SPCanvas *canvas = SP_CANVAS (widget);
+ Geom::IntRect old_area = Geom::IntRect::from_xywh(canvas->x0, canvas->y0,
+ widget->allocation.width, widget->allocation.height);
+ Geom::IntRect new_area = Geom::IntRect::from_xywh(canvas->x0, canvas->y0,
+ allocation->width, allocation->height);
+
/* Schedule redraw of new region */
sp_canvas_resize_tiles(canvas,canvas->x0,canvas->y0,canvas->x0+allocation->width,canvas->y0+allocation->height);
+ if (SP_CANVAS_ITEM_GET_CLASS (canvas->root)->visible_area_changed)
+ SP_CANVAS_ITEM_GET_CLASS (canvas->root)->visible_area_changed (canvas->root, old_area, new_area);
+
if (allocation->width > widget->allocation.width) {
sp_canvas_request_redraw (canvas,
canvas->x0 + widget->allocation.width,
@@ -1602,7 +1621,7 @@ sp_canvas_motion (GtkWidget *widget, GdkEventMotion *event)
if (event->window != SP_CANVAS_WINDOW (canvas))
return FALSE;
- if (canvas->pixmap_gc == NULL) // canvas being deleted
+ if (canvas->root == NULL) // canvas being deleted
return FALSE;
canvas->state = event->state;
@@ -1670,7 +1689,7 @@ static void sp_canvas_paint_single_buffer(SPCanvas *canvas, int x0, int y0, int
Inkscape::Preferences *prefs = Inkscape::Preferences::get();
bool fromDisplay = prefs->getBool( "/options/displayprofile/from_display");
if ( fromDisplay ) {
- transf = Inkscape::CMSSystem::getDisplayPer( canvas->cms_key ? *(canvas->cms_key) : "" );
+ transf = Inkscape::CMSSystem::getDisplayPer( canvas->cms_key );
} else {
transf = Inkscape::CMSSystem::getDisplayTransform();
}
@@ -1857,16 +1876,6 @@ sp_canvas_paint_rect (SPCanvas *canvas, int xx0, int yy0, int xx1, int yy1)
rect.x1 = MIN (rect.x1, canvas->x0/*draw_x1*/ + GTK_WIDGET (canvas)->allocation.width);
rect.y1 = MIN (rect.y1, canvas->y0/*draw_y1*/ + GTK_WIDGET (canvas)->allocation.height);
-#ifdef DEBUG_REDRAW
- // paint the area to redraw yellow
- gdk_rgb_gc_set_foreground (canvas->pixmap_gc, 0xFFFF00);
- gdk_draw_rectangle (SP_CANVAS_WINDOW (canvas),
- canvas->pixmap_gc,
- TRUE,
- rect.x0 - canvas->x0, rect.y0 - canvas->y0,
- rect.x1 - rect.x0, rect.y1 - rect.y0);
-#endif
-
PaintRectSetup setup;
setup.canvas = canvas;
@@ -2064,7 +2073,7 @@ paint (SPCanvas *canvas)
static int
do_update (SPCanvas *canvas)
{
- if (!canvas->root || !canvas->pixmap_gc) // canvas may have already be destroyed by closing desktop during interrupted display!
+ if (!canvas->root) // canvas may have already be destroyed by closing desktop during interrupted display!
return TRUE;
if (canvas->drawing_disabled)
@@ -2150,12 +2159,17 @@ sp_canvas_scroll_to (SPCanvas *canvas, double cx, double cy, unsigned int clear,
int dx = ix - canvas->x0; // dx and dy specify the displacement (scroll) of the
int dy = iy - canvas->y0; // canvas w.r.t its previous position
+ Geom::IntRect old_area = canvas->getViewboxIntegers();
+ Geom::IntRect new_area = old_area + Geom::IntPoint(dx, dy);
+
canvas->dx0 = cx; // here the 'd' stands for double, not delta!
canvas->dy0 = cy;
canvas->x0 = ix;
canvas->y0 = iy;
sp_canvas_resize_tiles (canvas, canvas->x0, canvas->y0, canvas->x0+canvas->widget.allocation.width, canvas->y0+canvas->widget.allocation.height);
+ if (SP_CANVAS_ITEM_GET_CLASS (canvas->root)->visible_area_changed)
+ SP_CANVAS_ITEM_GET_CLASS (canvas->root)->visible_area_changed (canvas->root, old_area, new_area);
if (!clear) {
// scrolling without zoom; redraw only the newly exposed areas
@@ -2168,7 +2182,6 @@ sp_canvas_scroll_to (SPCanvas *canvas, double cx, double cy, unsigned int clear,
} else {
// scrolling as part of zoom; do nothing here - the next do_update will perform full redraw
}
-
}
/**
@@ -2301,13 +2314,15 @@ Geom::Rect SPCanvas::getViewbox() const
}
/**
- * Return canvas window coordinates as IRect (a rectangle defined by integers).
+ * Return canvas window coordinates as integer rectangle.
*/
-NR::IRect SPCanvas::getViewboxIntegers() const
+Geom::IntRect SPCanvas::getViewboxIntegers() const
{
GtkWidget const *w = GTK_WIDGET(this);
- return NR::IRect(NR::IPoint(x0, y0),
- NR::IPoint(x0 + w->allocation.width, y0 + w->allocation.height));
+ Geom::IntRect ret;
+ ret.setMin(Geom::IntPoint(x0, y0));
+ ret.setMax(Geom::IntPoint(x0 + w->allocation.width, y0 + w->allocation.height));
+ return ret;
}
inline int sp_canvas_tile_floor(int x)
diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h
index 7a6b3295e..f284afdf2 100644
--- a/src/display/sp-canvas.h
+++ b/src/display/sp-canvas.h
@@ -112,9 +112,6 @@ struct SPCanvas {
int close_enough;
- /* GC for temporary draw pixmap */
- GdkGC *pixmap_gc;
-
unsigned int need_update : 1;
unsigned int need_redraw : 1;
unsigned int need_repick : 1;
@@ -143,13 +140,13 @@ struct SPCanvas {
#if ENABLE_LCMS
bool enable_cms_display_adj;
- Glib::ustring* cms_key;
+ Glib::ustring cms_key;
#endif // ENABLE_LCMS
bool is_scrolling;
Geom::Rect getViewbox() const;
- NR::IRect getViewboxIntegers() const;
+ Geom::IntRect getViewboxIntegers() const;
};
GtkWidget *sp_canvas_new_aa();
diff --git a/src/document.cpp b/src/document.cpp
index 90fc4c635..5bcf1bf40 100644
--- a/src/document.cpp
+++ b/src/document.cpp
@@ -40,6 +40,7 @@
#include <gtk/gtk.h>
#include <string>
#include <cstring>
+#include <2geom/transforms.h>
#include "desktop.h"
#include "dir-util.h"
@@ -647,7 +648,7 @@ void SPDocument::fitToRect(Geom::Rect const &rect, bool with_margins)
Geom::Translate const tr(
Geom::Point(0, old_height - rect_with_margins.height())
- - to_2geom(rect_with_margins.min()));
+ - rect_with_margins.min());
root->translateChildItems(tr);
if(nv) {
diff --git a/src/draw-context.h b/src/draw-context.h
index 4266bdea4..17540649b 100644
--- a/src/draw-context.h
+++ b/src/draw-context.h
@@ -16,9 +16,9 @@
#include <stddef.h>
#include <sigc++/sigc++.h>
+#include <2geom/point.h>
#include "event-context.h"
#include <forward.h>
-#include <libnr/nr-point.h>
#include "live_effects/effect.h"
/* Freehand context */
diff --git a/src/dropper-context.cpp b/src/dropper-context.cpp
index e30d6b1e8..9fbbcdc27 100644
--- a/src/dropper-context.cpp
+++ b/src/dropper-context.cpp
@@ -15,11 +15,10 @@
# include <config.h>
#endif
-#include <glibmm/i18n.h>
-#include <glibmm/ustring.h>
-#include <glibmm/refptr.h>
-#include <gtkmm/clipboard.h>
-#include <gdk/gdkkeysyms.h>
+#include <glibmm.h>
+#include <gtkmm.h>
+#include <gdk/gdk.h>
+#include <2geom/transforms.h>
#include "macros.h"
#include "display/canvas-bpath.h"
diff --git a/src/dyna-draw-context.cpp b/src/dyna-draw-context.cpp
index aa7d840bc..a3a665b1c 100644
--- a/src/dyna-draw-context.cpp
+++ b/src/dyna-draw-context.cpp
@@ -34,7 +34,7 @@
#include "svg/svg.h"
#include "display/canvas-bpath.h"
#include "display/cairo-utils.h"
-#include <2geom/isnan.h>
+#include <2geom/math-utils.h>
#include <2geom/pathvector.h>
#include <2geom/bezier-utils.h>
#include "display/curve.h"
diff --git a/src/eraser-context.cpp b/src/eraser-context.cpp
index 8ac765b9e..de6c7d86f 100644
--- a/src/eraser-context.cpp
+++ b/src/eraser-context.cpp
@@ -62,7 +62,7 @@
#include "display/canvas-bpath.h"
#include "display/canvas-arena.h"
#include "livarot/Shape.h"
-#include <2geom/isnan.h>
+#include <2geom/math-utils.h>
#include <2geom/pathvector.h>
#include "eraser-context.h"
diff --git a/src/extension/implementation/implementation.h b/src/extension/implementation/implementation.h
index b9e417feb..bd3edb43b 100644
--- a/src/extension/implementation/implementation.h
+++ b/src/extension/implementation/implementation.h
@@ -19,9 +19,9 @@
#include "forward.h"
#include "extension/extension-forward.h"
#include "libnr/nr-forward.h"
-#include "libnr/nr-point.h"
#include "xml/node.h"
#include <2geom/forward.h>
+#include <2geom/point.h>
namespace Inkscape {
namespace Extension {
diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp
index 676e9aa94..642ddba5b 100644
--- a/src/gradient-chemistry.cpp
+++ b/src/gradient-chemistry.cpp
@@ -1013,7 +1013,7 @@ Geom::Point sp_item_gradient_get_coords(SPItem *item, guint point_type, guint po
Geom::Point p (0, 0);
if (!gradient)
- return from_2geom(p);
+ return p;
if (SP_IS_LINEARGRADIENT(gradient)) {
SPLinearGradient *lg = SP_LINEARGRADIENT(gradient);
@@ -1071,7 +1071,7 @@ Geom::Point sp_item_gradient_get_coords(SPItem *item, guint point_type, guint po
}
}
p *= Geom::Affine(gradient->gradientTransform) * (Geom::Affine)item->i2d_affine();
- return from_2geom(p);
+ return p;
}
diff --git a/src/gradient-context.cpp b/src/gradient-context.cpp
index 8b4d2bc37..c4bef4683 100644
--- a/src/gradient-context.cpp
+++ b/src/gradient-context.cpp
@@ -548,9 +548,9 @@ sp_gradient_context_root_handler(SPEventContext *event_context, GdkEvent *event)
dragging = true;
- Geom::Point button_dt = to_2geom(desktop->w2d(button_w));
+ Geom::Point button_dt = desktop->w2d(button_w);
if (event->button.state & GDK_SHIFT_MASK) {
- Inkscape::Rubberband::get(desktop)->start(desktop, from_2geom(button_dt));
+ Inkscape::Rubberband::get(desktop)->start(desktop, button_dt);
} else {
// remember clicked item, disregarding groups, honoring Alt; do nothing with Crtl to
// enable Ctrl+doubleclick of exactly the selected item(s)
@@ -563,7 +563,7 @@ sp_gradient_context_root_handler(SPEventContext *event_context, GdkEvent *event)
m.freeSnapReturnByRef(button_dt, Inkscape::SNAPSOURCE_NODE_HANDLE);
m.unSetup();
}
- rc->origin = from_2geom(button_dt);
+ rc->origin = button_dt;
}
ret = TRUE;
diff --git a/src/graphlayout.cpp b/src/graphlayout.cpp
index 2717c376a..57002bfb6 100644
--- a/src/graphlayout.cpp
+++ b/src/graphlayout.cpp
@@ -19,6 +19,7 @@
#include <cstring>
#include <cstdlib>
#include <float.h>
+#include <2geom/transforms.h>
#include "desktop.h"
#include "inkscape.h"
diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp
index 64aa8bc48..fdfbdb9d3 100644
--- a/src/helper/geom.cpp
+++ b/src/helper/geom.cpp
@@ -511,15 +511,15 @@ namespace Geom {
bool transform_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon) {
return
- NR_DF_TEST_CLOSE(m0[0], m1[0], epsilon) &&
- NR_DF_TEST_CLOSE(m0[1], m1[1], epsilon) &&
- NR_DF_TEST_CLOSE(m0[2], m1[2], epsilon) &&
- NR_DF_TEST_CLOSE(m0[3], m1[3], epsilon);
+ 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 NR_DF_TEST_CLOSE(m0[4], m1[4], epsilon) && NR_DF_TEST_CLOSE(m0[5], m1[5], epsilon);
+ return Geom::are_near(m0[4], m1[4], epsilon) && Geom::are_near(m0[5], m1[5], epsilon);
}
diff --git a/src/helper/geom.h b/src/helper/geom.h
index b1015b185..630d67aba 100644
--- a/src/helper/geom.h
+++ b/src/helper/geom.h
@@ -13,8 +13,8 @@
*/
#include <2geom/forward.h>
-#include <libnr/nr-forward.h>
-#include <libnr/nr-coord.h>
+#include <2geom/rect.h>
+#include <2geom/affine.h>
Geom::OptRect bounds_fast_transformed(Geom::PathVector const & pv, Geom::Affine const & t);
Geom::OptRect bounds_exact_transformed(Geom::PathVector const & pv, Geom::Affine const & t);
diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp
index 9ebbe13c7..e1ced31b4 100644
--- a/src/helper/pixbuf-ops.cpp
+++ b/src/helper/pixbuf-ops.cpp
@@ -18,6 +18,7 @@
#include <glib.h>
#include <glib/gmessages.h>
#include <png.h>
+#include <2geom/transforms.h>
#include "interface.h"
#include "helper/png-write.h"
diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp
index 4667f631b..5a20ac363 100644
--- a/src/helper/png-write.cpp
+++ b/src/helper/png-write.cpp
@@ -18,6 +18,7 @@
#include "interface.h"
#include <2geom/rect.h>
+#include <2geom/transforms.h>
#include <glib/gmessages.h>
#include <png.h>
#include "png-write.h"
diff --git a/src/helper/recthull.h b/src/helper/recthull.h
index a9cad4466..d82450ce8 100644
--- a/src/helper/recthull.h
+++ b/src/helper/recthull.h
@@ -38,7 +38,7 @@ public:
void add(Rect const &r) {
// Note that this is a hack. when convexhull actually works
// you will need to add all four points.
- _bounds = unify(_bounds, r);
+ _bounds.unionWith(r);
}
void add(RectHull const &h) {
if (h._bounds) {
diff --git a/src/libcola/cola.cpp b/src/libcola/cola.cpp
index e2a233b5e..87fbf9f79 100644
--- a/src/libcola/cola.cpp
+++ b/src/libcola/cola.cpp
@@ -2,7 +2,7 @@
#include "conjugate_gradient.h"
#include "straightener.h"
#include "shortest_paths.h"
-#include "2geom/isnan.h"
+#include <2geom/math-utils.h>
using namespace std;
diff --git a/src/libcola/gradient_projection.cpp b/src/libcola/gradient_projection.cpp
index fb8702ec7..47109a4b0 100644
--- a/src/libcola/gradient_projection.cpp
+++ b/src/libcola/gradient_projection.cpp
@@ -17,7 +17,7 @@
#include <libvpsc/constraint.h>
#include "gradient_projection.h"
#include <iostream>
-#include "2geom/isnan.h"
+#include <2geom/math-utils.h>
#include "isinf.h"
#include <math.h>
diff --git a/src/libnr/Makefile_insert b/src/libnr/Makefile_insert
index 1027e0600..57d82c8ef 100644
--- a/src/libnr/Makefile_insert
+++ b/src/libnr/Makefile_insert
@@ -3,25 +3,16 @@
ink_common_sources += \
libnr/in-svg-plane.h \
libnr/nr-convert2geom.h \
- libnr/nr-coord.h \
- libnr/nr-dim2.h \
libnr/nr-forward.h \
- libnr/nr-i-coord.h \
libnr/nr-macros.h \
libnr/nr-object.cpp \
libnr/nr-object.h \
- libnr/nr-point-fns.cpp \
- libnr/nr-point-fns.h \
- libnr/nr-point-l.h \
- libnr/nr-point-ops.h \
- libnr/nr-point.h \
+ libnr/nr-point-fns.cpp \
+ libnr/nr-point-fns.h \
libnr/nr-rect-l.cpp \
libnr/nr-rect-l.h \
libnr/nr-rect.cpp \
libnr/nr-rect.h \
- libnr/nr-rect-ops.h \
- libnr/nr-types.cpp \
- libnr/nr-types.h \
libnr/nr-values.cpp \
libnr/nr-values.h
diff --git a/src/libnr/in-svg-plane.h b/src/libnr/in-svg-plane.h
index c1937f0fc..68c9e92a0 100644
--- a/src/libnr/in-svg-plane.h
+++ b/src/libnr/in-svg-plane.h
@@ -1,8 +1,7 @@
#ifndef SEEN_LIBNR_IN_SVG_PLANE_H
#define SEEN_LIBNR_IN_SVG_PLANE_H
-#include "libnr/nr-point-fns.h"
-
+#include <2geom/point.h>
/**
* Returns true iff the coordinates of \a p are finite, non-NaN, and "small enough". Currently we
@@ -13,7 +12,7 @@
* in SVG Tiny (which uses fixed-point arithmetic).
*/
inline bool
-in_svg_plane(NR::Point const p)
+in_svg_plane(Geom::Point const &p)
{
return Geom::LInfty(p) < 1e18;
}
diff --git a/src/libnr/libnr.def b/src/libnr/libnr.def
deleted file mode 100644
index d8f224ca9..000000000
--- a/src/libnr/libnr.def
+++ /dev/null
@@ -1,89 +0,0 @@
-EXPORTS
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_TRANSFORM
- nr_R8G8B8A8_N_EMPTY_A8_RGBA32
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_N_A8
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P
- nr_R8G8B8A8_N_EMPTY_R8G8B8A8_P_A8
- nr_R8G8B8A8_N_R8G8B8A8_N_A8_RGBA32
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_A8
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_N_TRANSFORM
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P
- nr_R8G8B8A8_N_R8G8B8A8_N_R8G8B8A8_P_A8
- nr_R8G8B8A8_P_EMPTY_A8_RGBA32
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_N_A8
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P
- nr_R8G8B8A8_P_EMPTY_R8G8B8A8_P_A8
- nr_R8G8B8A8_P_R8G8B8A8_P_A8_RGBA32
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_N_A8
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P
- nr_R8G8B8A8_P_R8G8B8A8_P_R8G8B8A8_P_A8
-; nr_R8G8B8_EMPTY_A8_RGBA32
- nr_R8G8B8_R8G8B8_A8_RGBA32
- nr_R8G8B8_R8G8B8_R8G8B8A8_N
- nr_R8G8B8_R8G8B8_R8G8B8A8_P
- nr_active_object_add_listener
- nr_active_object_get_type
- nr_active_object_remove_listener_by_data
- nr_blit_pixblock_mask_rgba32
- nr_blit_pixblock_pixblock_alpha
- nr_blit_pixblock_pixblock_mask
- nr_compose_pixblock_pixblock_pixel
- nr_emit_fail_warning
- nr_flat_free_list
- nr_flat_free_one
- nr_flat_insert_sorted
- nr_flat_new_full
- nr_lgradient_renderer_setup
- nr_matrix_invert
- nr_matrix_set_rotate
- nr_matrix_set_scale
- nr_matrix_set_translate
- nr_matrix_multiply
- nr_object_check_instance_cast
- nr_object_check_instance_type
- nr_object_delete
- nr_object_get_type
- nr_object_new
- nr_object_ref
- nr_object_register_type
- nr_object_release
- nr_object_setup
- nr_object_unref
- nr_path_duplicate_transform
- nr_path_matrix_bbox_nion
- nr_path_matrix_point_bbox_wind_distance
- nr_pixblock_draw_line_rgba32
- nr_pixblock_free
- nr_pixblock_new
- nr_pixblock_release
- nr_pixblock_render_gray_noise
- nr_pixblock_render_svp_mask_or
- nr_pixblock_setup
- nr_pixblock_setup_extern
- nr_pixblock_setup_fast
- nr_pixelstore_16K_free
- nr_pixelstore_16K_new
- nr_pixelstore_4K_free
- nr_pixelstore_4K_new
- nr_pixelstore_64K_free
- nr_pixelstore_64K_new
- nr_rect_d_intersect
- nr_rect_d_matrix_transform
- nr_rect_d_union
- nr_rect_l_intersect
- nr_rect_l_union
- nr_rgradient_renderer_setup
- nr_svp_bbox
- nr_svp_free
- nr_svp_point_distance
- nr_svp_point_wind
- nr_type_is_a
- nr_vertex_free_list
- nr_vertex_free_one
- nr_vertex_new
- nr_vertex_new_xy
- nr_vertex_reverse_list
diff --git a/src/libnr/nr-convert2geom.h b/src/libnr/nr-convert2geom.h
index 75098ce2b..7e2423ea6 100644
--- a/src/libnr/nr-convert2geom.h
+++ b/src/libnr/nr-convert2geom.h
@@ -10,34 +10,14 @@
*/
#include <libnr/nr-rect.h>
-#include <libnr/nr-point.h>
-#include <2geom/affine.h>
-#include <2geom/d2.h>
-#include <2geom/transforms.h>
-#include <2geom/point.h>
+#include <2geom/rect.h>
-inline Geom::Point to_2geom(NR::Point const & _pt) {
- return Geom::Point(_pt[0], _pt[1]);
-}
-inline NR::Point from_2geom(Geom::Point const & _pt) {
- return NR::Point(_pt[0], _pt[1]);
-}
-
-inline Geom::Rect to_2geom(NR::Rect const & rect) {
- Geom::Rect rect2geom(to_2geom(rect.min()), to_2geom(rect.max()));
- return rect2geom;
-}
-inline NR::Rect from_2geom(Geom::Rect const & rect2geom) {
- NR::Rect rect(rect2geom.min(), rect2geom.max());
- return rect;
-}
-inline Geom::OptRect to_2geom(boost::optional<NR::Rect> const & rect) {
- Geom::OptRect rect2geom;
- if (!rect) {
- return rect2geom;
- }
- rect2geom = to_2geom(*rect);
- return rect2geom;
+inline Geom::OptRect to_2geom(NRRect const *nr) {
+ Geom::OptRect ret;
+ if (!nr) return ret;
+ if (nr->x1 < nr->x0 || nr->y1 < nr->y0) return ret;
+ ret = Geom::Rect(Geom::Point(nr->x0, nr->y0), Geom::Point(nr->x1, nr->y1));
+ return ret;
}
#endif
diff --git a/src/libnr/nr-coord.h b/src/libnr/nr-coord.h
deleted file mode 100644
index e094caeb3..000000000
--- a/src/libnr/nr-coord.h
+++ /dev/null
@@ -1,29 +0,0 @@
-#ifndef SEEN_NR_COORD_H
-#define SEEN_NR_COORD_H
-
-namespace NR {
-
-/**
- * A "real" type with sufficient precision for coordinates.
- *
- * You may safely assume that double (or even float) provides enough precision for storing
- * on-canvas points, and hence that double provides enough precision for dot products of
- * differences of on-canvas points.
- */
-typedef double Coord;
-
-} /* namespace NR */
-
-
-#endif /* !SEEN_NR_COORD_H */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libnr/nr-dim2.h b/src/libnr/nr-dim2.h
deleted file mode 100644
index c068bc220..000000000
--- a/src/libnr/nr-dim2.h
+++ /dev/null
@@ -1,22 +0,0 @@
-#ifndef SEEN_NR_DIM2_H
-#define SEEN_NR_DIM2_H
-
-namespace NR {
-
-enum Dim2 { X=0, Y };
-
-} /* namespace NR */
-
-
-#endif /* !SEEN_NR_DIM2_H */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libnr/nr-forward.h b/src/libnr/nr-forward.h
index 82e29030c..4895ad407 100644
--- a/src/libnr/nr-forward.h
+++ b/src/libnr/nr-forward.h
@@ -10,20 +10,10 @@
* This code is in public domain
*/
-namespace NR {
-class Matrix;
-class Point;
-class Rect;
-class rotate;
-class scale;
-class translate;
-}
-
struct NRPixBlock;
struct NRRect;
struct NRRectL;
-
#endif
/*
diff --git a/src/libnr/nr-i-coord.h b/src/libnr/nr-i-coord.h
deleted file mode 100644
index a19d2ca46..000000000
--- a/src/libnr/nr-i-coord.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef SEEN_NR_I_COORD_H
-#define SEEN_NR_I_COORD_H
-
-#include <glib/gtypes.h>
-
-namespace NR {
-
-/** An integer type with sufficient precision for coordinates. */
-typedef gint32 ICoord;
-
-} /* namespace NR */
-
-
-#endif /* !SEEN_NR_I_COORD_H */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libnr/nr-point-fns-test.h b/src/libnr/nr-point-fns-test.h
deleted file mode 100644
index df166660c..000000000
--- a/src/libnr/nr-point-fns-test.h
+++ /dev/null
@@ -1,139 +0,0 @@
-// nr-point-fns-test.h
-#include <cxxtest/TestSuite.h>
-
-#include <cassert>
-#include <cmath>
-#include <glib/gmacros.h>
-#include <stdlib.h>
-
-#include "libnr/nr-point-fns.h"
-#include "2geom/isnan.h"
-
-class NrPointFnsTest : public CxxTest::TestSuite
-{
-public:
- NrPointFnsTest() :
- setupValid(true),
- p3n4( 3.0, -4.0 ),
- p0( 0.0, 0.0 ),
- small( pow( 2.0, -1070 ) ),
- inf( 1e400 ),
- nan( inf - inf ),
- small_left( -small, 0.0 ),
- small_n3_4( -3.0 * small, 4.0 * small ),
- part_nan( 3., nan ),
- inf_left( -inf, 5.0 )
- {
- TS_ASSERT( IS_NAN(nan) );
- TS_ASSERT( !IS_NAN(small) );
-
- setupValid &= IS_NAN(nan);
- setupValid &= !IS_NAN(small);
- }
- virtual ~NrPointFnsTest() {}
-
-// createSuite and destroySuite get us per-suite setup and teardown
-// without us having to worry about static initialization order, etc.
- static NrPointFnsTest *createSuite() { return new NrPointFnsTest(); }
- static void destroySuite( NrPointFnsTest *suite ) { delete suite; }
-
-// Called before each test in this suite
- void setUp()
- {
- TS_ASSERT( setupValid );
- }
-
- bool setupValid;
- NR::Point const p3n4;
- NR::Point const p0;
- double const small;
- double const inf;
- double const nan;
-
- NR::Point const small_left;
- NR::Point const small_n3_4;
- NR::Point const part_nan;
- NR::Point const inf_left;
-
-
- void testL1(void)
- {
- TS_ASSERT_EQUALS( NR::L1(p0), 0.0 );
- TS_ASSERT_EQUALS( NR::L1(p3n4), 7.0 );
- TS_ASSERT_EQUALS( NR::L1(small_left), small );
- TS_ASSERT_EQUALS( NR::L1(inf_left), inf );
- TS_ASSERT_EQUALS( NR::L1(small_n3_4), 7.0 * small );
- TS_ASSERT(IS_NAN(NR::L1(part_nan)));
- }
-
- void testL2(void)
- {
- TS_ASSERT_EQUALS( NR::L2(p0), 0.0 );
- TS_ASSERT_EQUALS( NR::L2(p3n4), 5.0 );
- TS_ASSERT_EQUALS( NR::L2(small_left), small );
- TS_ASSERT_EQUALS( NR::L2(inf_left), inf );
- TS_ASSERT_EQUALS( NR::L2(small_n3_4), 5.0 * small );
- TS_ASSERT( IS_NAN(NR::L2(part_nan)) );
- }
-
- void testLInfty(void)
- {
- TS_ASSERT_EQUALS( NR::LInfty(p0), 0.0 );
- TS_ASSERT_EQUALS( NR::LInfty(p3n4), 4.0 );
- TS_ASSERT_EQUALS( NR::LInfty(small_left), small );
- TS_ASSERT_EQUALS( NR::LInfty(inf_left), inf );
- TS_ASSERT_EQUALS( NR::LInfty(small_n3_4), 4.0 * small );
- TS_ASSERT( IS_NAN(NR::LInfty(part_nan)) );
- }
-
- void testIsZero(void)
- {
- TS_ASSERT( NR::is_zero(p0) );
- TS_ASSERT( !NR::is_zero(p3n4) );
- TS_ASSERT( !NR::is_zero(small_left) );
- TS_ASSERT( !NR::is_zero(inf_left) );
- TS_ASSERT( !NR::is_zero(small_n3_4) );
- TS_ASSERT( !NR::is_zero(part_nan) );
- }
-
- void testAtan2(void)
- {
- TS_ASSERT_EQUALS( NR::atan2(p3n4), atan2(-4.0, 3.0) );
- TS_ASSERT_EQUALS( NR::atan2(small_left), atan2(0.0, -1.0) );
- TS_ASSERT_EQUALS( NR::atan2(small_n3_4), atan2(4.0, -3.0) );
- }
-
- void testUnitVector(void)
- {
- TS_ASSERT_EQUALS( NR::unit_vector(p3n4), NR::Point(.6, -0.8) );
- TS_ASSERT_EQUALS( NR::unit_vector(small_left), NR::Point(-1.0, 0.0) );
- TS_ASSERT_EQUALS( NR::unit_vector(small_n3_4), NR::Point(-.6, 0.8) );
- }
-
- void testIsUnitVector(void)
- {
- TS_ASSERT( !NR::is_unit_vector(p3n4) );
- TS_ASSERT( !NR::is_unit_vector(small_left) );
- TS_ASSERT( !NR::is_unit_vector(small_n3_4) );
- TS_ASSERT( !NR::is_unit_vector(part_nan) );
- TS_ASSERT( !NR::is_unit_vector(inf_left) );
- TS_ASSERT( !NR::is_unit_vector(NR::Point(.5, 0.5)) );
- TS_ASSERT( NR::is_unit_vector(NR::Point(.6, -0.8)) );
- TS_ASSERT( NR::is_unit_vector(NR::Point(-.6, 0.8)) );
- TS_ASSERT( NR::is_unit_vector(NR::Point(-1.0, 0.0)) );
- TS_ASSERT( NR::is_unit_vector(NR::Point(1.0, 0.0)) );
- TS_ASSERT( NR::is_unit_vector(NR::Point(0.0, -1.0)) );
- TS_ASSERT( NR::is_unit_vector(NR::Point(0.0, 1.0)) );
- }
-};
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libnr/nr-point-fns.cpp b/src/libnr/nr-point-fns.cpp
index cd6d6927b..a2e74c112 100644
--- a/src/libnr/nr-point-fns.cpp
+++ b/src/libnr/nr-point-fns.cpp
@@ -1,72 +1,11 @@
-#include <libnr/nr-point-fns.h>
-#include <2geom/isnan.h>
+#include "libnr/nr-point-fns.h"
-using NR::Point;
-
-/** Compute the L infinity, or maximum, norm of \a p. */
-NR::Coord NR::LInfty(Point const &p) {
- NR::Coord const a(fabs(p[0]));
- NR::Coord const b(fabs(p[1]));
- return ( a < b || IS_NAN(b)
- ? b
- : a );
-}
-
-/** Returns true iff p is a zero vector, i.e.\ Point(0, 0).
- *
- * (NaN is considered non-zero.)
- */
-bool
-NR::is_zero(Point const &p)
-{
- return ( p[0] == 0 &&
- p[1] == 0 );
-}
-
-bool
-NR::is_unit_vector(Point const &p)
-{
- return fabs(1.0 - L2(p)) <= 1e-4;
- /* The tolerance of 1e-4 is somewhat arbitrary. NR::Point::normalize is believed to return
- points well within this tolerance. I'm not aware of any callers that want a small
- tolerance; most callers would be ok with a tolerance of 0.25. */
-}
-
-NR::Coord NR::atan2(Point const p) {
- return std::atan2(p[NR::Y], p[NR::X]);
-}
-
-/** Returns a version of \a a scaled to be a unit vector (within rounding error).
- *
- * The current version tries to handle infinite coordinates gracefully,
- * but it's not clear that any callers need that.
- *
- * \pre a != Point(0, 0).
- * \pre Neither coordinate is NaN.
- * \post L2(ret) very near 1.0.
- */
-Point NR::unit_vector(Point const &a)
-{
- Point ret(a);
- ret.normalize();
- return ret;
-}
-
-NR::Point abs(NR::Point const &b)
-{
- NR::Point ret;
- for ( int i = 0 ; i < 2 ; i++ ) {
- ret[i] = fabs(b[i]);
- }
- return ret;
-}
-
-NR::Point
-snap_vector_midpoint (NR::Point p, NR::Point begin, NR::Point end, double snap)
+Geom::Point
+snap_vector_midpoint (Geom::Point const &p, Geom::Point const &begin, Geom::Point const &end, double snap)
{
- double length = NR::L2(end - begin);
- NR::Point be = (end - begin) / length;
- double r = NR::dot(p - begin, be);
+ double length = Geom::distance(begin, end);
+ Geom::Point be = (end - begin) / length;
+ double r = Geom::dot(p - begin, be);
if (r < 0.0) return begin;
if (r > length) return end;
@@ -78,11 +17,11 @@ snap_vector_midpoint (NR::Point p, NR::Point begin, NR::Point end, double snap)
}
double
-get_offset_between_points (NR::Point p, NR::Point begin, NR::Point end)
+get_offset_between_points (Geom::Point const &p, Geom::Point const &begin, Geom::Point const &end)
{
- double length = NR::L2(end - begin);
- NR::Point be = (end - begin) / length;
- double r = NR::dot(p - begin, be);
+ double length = Geom::distance(begin, end);
+ Geom::Point be = (end - begin) / length;
+ double r = Geom::dot(p - begin, be);
if (r < 0.0) return 0.0;
if (r > length) return 1.0;
@@ -90,8 +29,8 @@ get_offset_between_points (NR::Point p, NR::Point begin, NR::Point end)
return (r / length);
}
-NR::Point
-project_on_linesegment(NR::Point const p, NR::Point const p1, NR::Point const p2)
+Geom::Point
+project_on_linesegment(Geom::Point const &p, Geom::Point const &p1, Geom::Point const &p2)
{
// p_proj = projection of p on the linesegment running from p1 to p2
// p_proj = p1 + u (p2 - p1)
@@ -104,9 +43,9 @@ project_on_linesegment(NR::Point const p, NR::Point const p1, NR::Point const p2
return p;
}
- NR::Point const d1(p-p1); // delta 1
- NR::Point const d2(p2-p1); // delta 2
- double const u = (d1[NR::X] * d2[NR::X] + d1[NR::Y] * d2[NR::Y]) / (NR::L2(d2) * NR::L2(d2));
+ Geom::Point d1(p-p1); // delta 1
+ Geom::Point d2(p2-p1); // delta 2
+ double u = Geom::dot(d1, d2) / Geom::L2sq(d2);
return (p1 + u*(p2-p1));
}
diff --git a/src/libnr/nr-point-fns.h b/src/libnr/nr-point-fns.h
index 05c4f718c..b26c969aa 100644
--- a/src/libnr/nr-point-fns.h
+++ b/src/libnr/nr-point-fns.h
@@ -1,100 +1,13 @@
#ifndef __NR_POINT_OPS_H__
#define __NR_POINT_OPS_H__
-#include <libnr/nr-point-ops.h>
-#include <libnr/nr-dim2.h>
-#include <libnr/nr-macros.h>
+#include <2geom/point.h>
-namespace NR {
+Geom::Point snap_vector_midpoint (Geom::Point const &p, Geom::Point const &begin, Geom::Point const &end, double snap);
-/** Compute the L1 norm, or manhattan distance, of \a p. */
-inline Coord L1(Point const &p) {
- Coord d = 0;
- for ( int i = 0 ; i < 2 ; i++ ) {
- d += fabs(p[i]);
- }
- return d;
-}
+double get_offset_between_points (Geom::Point const &p, Geom::Point const &begin, Geom::Point const &end);
-/** Compute the L2, or euclidean, norm of \a p. */
-inline Coord L2(Point const &p) {
- return hypot(p[0], p[1]);
-}
-
-extern double LInfty(Point const &p);
-
-bool is_zero(Point const &p);
-
-bool is_unit_vector(Point const &p);
-
-extern double atan2(Point const p);
-
-inline bool point_equalp(Point const &a, Point const &b, double const eps)
-{
- return ( NR_DF_TEST_CLOSE(a[X], b[X], eps) &&
- NR_DF_TEST_CLOSE(a[Y], b[Y], eps) );
-}
-
-/** Returns p * NR::rotate_degrees(90), but more efficient.
- *
- * Angle direction in Inkscape code: If you use the traditional mathematics convention that y
- * increases upwards, then positive angles are anticlockwise as per the mathematics convention. If
- * you take the common non-mathematical convention that y increases downwards, then positive angles
- * are clockwise, as is common outside of mathematics.
- *
- * There is no rot_neg90 function: use -rot90(p) instead.
- */
-inline Point rot90(Point const &p)
-{
- return Point(-p[Y], p[X]);
-}
-
-/** Given two points and a parameter t \in [0, 1], return a point
- * proportionally from a to b by t. */
-inline Point Lerp(double const t, Point const a, Point const b)
-{
- return ( ( 1 - t ) * a
- + t * b );
-}
-
-Point unit_vector(Point const &a);
-
-inline Coord dot(Point const &a, Point const &b)
-{
- Coord ret = 0;
- for ( int i = 0 ; i < 2 ; i++ ) {
- ret += a[i] * b[i];
- }
- return ret;
-}
-
-inline Coord distance (Point const &a, Point const &b)
-{
- Coord ret = 0;
- for ( int i = 0 ; i < 2 ; i++ ) {
- ret += (a[i] - b[i]) * (a[i] - b[i]);
- }
- return sqrt (ret);
-}
-
-/** Defined as dot(a, b.cw()). */
-inline Coord cross(Point const &a, Point const &b)
-{
- Coord ret = 0;
- ret -= a[0] * b[1];
- ret += a[1] * b[0];
- return ret;
-}
-
-Point abs(Point const &b);
-
-} /* namespace NR */
-
-NR::Point snap_vector_midpoint (NR::Point p, NR::Point begin, NR::Point end, double snap);
-
-double get_offset_between_points (NR::Point p, NR::Point begin, NR::Point end);
-
-NR::Point project_on_linesegment(NR::Point const p, NR::Point const p1, NR::Point const p2);
+Geom::Point project_on_linesegment(Geom::Point const &p, Geom::Point const &p1, Geom::Point const &p2);
#endif /* !__NR_POINT_OPS_H__ */
diff --git a/src/libnr/nr-point-l.h b/src/libnr/nr-point-l.h
deleted file mode 100644
index 9bfe2c790..000000000
--- a/src/libnr/nr-point-l.h
+++ /dev/null
@@ -1,103 +0,0 @@
-#ifndef SEEN_NR_POINT_L_H
-#define SEEN_NR_POINT_L_H
-
-#include <stdexcept>
-#include <libnr/nr-i-coord.h>
-#include <libnr/nr-point.h>
-
-struct NRPointL {
- NR::ICoord x, y;
-};
-
-namespace NR {
-
-class IPoint {
-public:
- IPoint()
- { }
-
- IPoint(ICoord x, ICoord y) {
- _pt[X] = x;
- _pt[Y] = y;
- }
-
- IPoint(NRPointL const &p) {
- _pt[X] = p.x;
- _pt[Y] = p.y;
- }
-
- IPoint(IPoint const &p) {
- for (unsigned i = 0; i < 2; ++i) {
- _pt[i] = p._pt[i];
- }
- }
-
- IPoint &operator=(IPoint const &p) {
- for (unsigned i = 0; i < 2; ++i) {
- _pt[i] = p._pt[i];
- }
- return *this;
- }
-
- operator Point() {
- return Point(_pt[X], _pt[Y]);
- }
-
- ICoord operator[](unsigned i) const throw(std::out_of_range) {
- if ( i > Y ) {
- throw std::out_of_range("index out of range");
- }
- return _pt[i];
- }
-
- ICoord &operator[](unsigned i) throw(std::out_of_range) {
- if ( i > Y ) {
- throw std::out_of_range("index out of range");
- }
- return _pt[i];
- }
-
- ICoord operator[](Dim2 d) const throw() { return _pt[d]; }
- ICoord &operator[](Dim2 d) throw() { return _pt[d]; }
-
- IPoint &operator+=(IPoint const &o) {
- for ( unsigned i = 0 ; i < 2 ; ++i ) {
- _pt[i] += o._pt[i];
- }
- return *this;
- }
-
- IPoint &operator-=(IPoint const &o) {
- for ( unsigned i = 0 ; i < 2 ; ++i ) {
- _pt[i] -= o._pt[i];
- }
- return *this;
- }
-
- bool operator==(IPoint const &other) const {
- return _pt[X] == other[X] && _pt[Y] == other[Y];
- }
-
- bool operator!=(IPoint const &other) const {
- return _pt[X] != other[X] || _pt[Y] != other[Y];
- }
-
-private:
- ICoord _pt[2];
-};
-
-
-} // namespace NR
-
-#endif /* !SEEN_NR_POINT_L_H */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libnr/nr-point-ops.h b/src/libnr/nr-point-ops.h
deleted file mode 100644
index aba981803..000000000
--- a/src/libnr/nr-point-ops.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* operator functions for NR::Point. */
-#ifndef SEEN_NR_POINT_OPS_H
-#define SEEN_NR_POINT_OPS_H
-
-#include <libnr/nr-point.h>
-
-namespace NR {
-
-inline Point operator+(Point const &a, Point const &b)
-{
- Point ret;
- for (int i = 0; i < 2; i++) {
- ret[i] = a[i] + b[i];
- }
- return ret;
-}
-
-inline Point operator-(Point const &a, Point const &b)
-{
- Point ret;
- for (int i = 0; i < 2; i++) {
- ret[i] = a[i] - b[i];
- }
- return ret;
-}
-
-/** This is a rotation (sort of). */
-inline Point operator^(Point const &a, Point const &b)
-{
- Point const ret(a[0] * b[0] - a[1] * b[1],
- a[1] * b[0] + a[0] * b[1]);
- return ret;
-}
-
-inline Point operator-(Point const &a)
-{
- Point ret;
- for(unsigned i = 0; i < 2; i++) {
- ret[i] = -a[i];
- }
- return ret;
-}
-
-inline Point operator*(double const s, Point const &b)
-{
- Point ret;
- for(int i = 0; i < 2; i++) {
- ret[i] = s * b[i];
- }
- return ret;
-}
-
-inline Point operator/(Point const &b, double const d)
-{
- Point ret;
- for(int i = 0; i < 2; i++) {
- ret[i] = b[i] / d;
- }
- return ret;
-}
-
-
-inline bool operator==(Point const &a, Point const &b)
-{
- return ( ( a[X] == b[X] ) && ( a[Y] == b[Y] ) );
-}
-
-inline bool operator!=(Point const &a, Point const &b)
-{
- return ( ( a[X] != b[X] ) || ( a[Y] != b[Y] ) );
-}
-
-
-} /* namespace NR */
-
-
-#endif /* !SEEN_NR_POINT_OPS_H */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libnr/nr-point.h b/src/libnr/nr-point.h
deleted file mode 100644
index 19add7dd1..000000000
--- a/src/libnr/nr-point.h
+++ /dev/null
@@ -1,155 +0,0 @@
-#ifndef SEEN_NR_POINT_H
-#define SEEN_NR_POINT_H
-
-/** \file
- * Cartesian point class.
- */
-
-//#include <math.h>
-//#include <stdexcept>
-#include <iostream>
-//#include <iomanip>
-
-#include <libnr/nr-coord.h>
-#include <libnr/nr-dim2.h>
-#include <libnr/nr-forward.h>
-
-//#include "round.h"
-#include "decimal-round.h"
-
-#include <2geom/point.h>
-
-namespace NR {
-
-/// Cartesian point.
-class Point {
-public:
- inline Point()
- { _pt[X] = _pt[Y] = 0; }
-
- inline Point(Coord x, Coord y) {
- _pt[X] = x;
- _pt[Y] = y;
- }
-
- inline Point(Point const &p) {
- for (unsigned i = 0; i < 2; ++i) {
- _pt[i] = p._pt[i];
- }
- }
-
- inline Point(Geom::Point const &p) {
- _pt[X] = p[Geom::X];
- _pt[Y] = p[Geom::Y];
- }
-
- inline Point &operator=(Point const &p) {
- for (unsigned i = 0; i < 2; ++i) {
- _pt[i] = p._pt[i];
- }
- return *this;
- }
-
- inline Coord operator[](unsigned i) const {
- return _pt[i];
- }
-
- inline Coord &operator[](unsigned i) {
- return _pt[i];
- }
-
- Coord operator[](Dim2 d) const throw() { return _pt[d]; }
- Coord &operator[](Dim2 d) throw() { return _pt[d]; }
-
- /** Return a point like this point but rotated -90 degrees.
- (If the y axis grows downwards and the x axis grows to the
- right, then this is 90 degrees counter-clockwise.)
- **/
- Point ccw() const {
- return Point(_pt[Y], -_pt[X]);
- }
-
- /** Return a point like this point but rotated +90 degrees.
- (If the y axis grows downwards and the x axis grows to the
- right, then this is 90 degrees clockwise.)
- **/
- Point cw() const {
- return Point(-_pt[Y], _pt[X]);
- }
-
- /**
- \brief A function to lower the precision of the point
- \param places The number of decimal places that should be in
- the final number.
- */
- inline void round (int places = 0) {
- _pt[X] = (Coord)(Inkscape::decimal_round((double)_pt[X], places));
- _pt[Y] = (Coord)(Inkscape::decimal_round((double)_pt[Y], places));
- return;
- }
-
- void normalize();
-
- inline Point &operator+=(Point const &o) {
- for ( unsigned i = 0 ; i < 2 ; ++i ) {
- _pt[i] += o._pt[i];
- }
- return *this;
- }
-
- inline Point &operator-=(Point const &o) {
- for ( unsigned i = 0 ; i < 2 ; ++i ) {
- _pt[i] -= o._pt[i];
- }
- return *this;
- }
-
- inline Point &operator/=(double const s) {
- for ( unsigned i = 0 ; i < 2 ; ++i ) {
- _pt[i] /= s;
- }
- return *this;
- }
-
- inline Point &operator*=(double const s) {
- for ( unsigned i = 0 ; i < 2 ; ++i ) {
- _pt[i] *= s;
- }
- return *this;
- }
-
- Point &operator*=(Matrix const &m);
-
- inline int operator == (const Point &in_pnt) {
- return ((_pt[X] == in_pnt[X]) && (_pt[Y] == in_pnt[Y]));
- }
-
- friend inline std::ostream &operator<< (std::ostream &out_file, const NR::Point &in_pnt);
-
- inline operator Geom::Point() const { return Geom::Point(_pt[X], _pt[Y]); }
-
-private:
- Coord _pt[2];
-};
-
-/** A function to print out the Point. It just prints out the coords
- on the given output stream */
-inline std::ostream &operator<< (std::ostream &out_file, const NR::Point &in_pnt) {
- out_file << "X: " << in_pnt[X] << " Y: " << in_pnt[Y];
- return out_file;
-}
-
-} /* namespace NR */
-
-#endif /* !SEEN_NR_POINT_H */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libnr/nr-rect-l.cpp b/src/libnr/nr-rect-l.cpp
index 9d1f80988..1cb268266 100644
--- a/src/libnr/nr-rect-l.cpp
+++ b/src/libnr/nr-rect-l.cpp
@@ -1,21 +1,50 @@
-#include <libnr/nr-rect-l.h>
+#include "libnr/nr-rect-l.h"
-boost::optional<NR::Rect> NRRectL::upgrade() const {
- if (nr_rect_l_test_empty_ptr(this)) {
- return boost::optional<NR::Rect>();
+NRRectL::NRRectL()
+{
+ x0 = G_MAXINT32;
+ y0 = G_MAXINT32;
+ x1 = G_MININT32;
+ y1 = G_MININT32;
+}
+
+NRRectL::NRRectL(gint32 xmin, gint32 ymin, gint32 xmax, gint32 ymax)
+{
+ x0 = xmin;
+ y0 = ymin;
+ x1 = xmax;
+ y1 = ymax;
+}
+
+NRRectL::NRRectL(Geom::OptIntRect const &r)
+{
+ if (r) {
+ x0 = r->left();
+ y0 = r->top();
+ x1 = r->right();
+ y1 = r->bottom();
} else {
- return NR::Rect(NR::Point(x0, y0), NR::Point(x1, y1));
+ x0 = G_MAXINT32;
+ y0 = G_MAXINT32;
+ x1 = G_MININT32;
+ y1 = G_MININT32;
}
}
-namespace NR {
-
-IRect::IRect(Rect const &r) :
- _min(int(floor(r.min()[X])), int(floor(r.min()[Y]))),
- _max(int(ceil(r.min()[X])), int(ceil(r.min()[Y])))
+NRRectL::NRRectL(Geom::IntRect const &r)
{
+ x0 = r.left();
+ y0 = r.top();
+ x1 = r.right();
+ y1 = r.bottom();
}
+Geom::OptIntRect NRRectL::upgrade_2geom() const
+{
+ Geom::OptIntRect ret;
+ if (x0 > x1 || y0 > y1) return ret;
+ ret = Geom::IntRect(x0, y0, x1, y1);
+ return ret;
}
/*
diff --git a/src/libnr/nr-rect-l.h b/src/libnr/nr-rect-l.h
index 3493fa8f4..c4c5f5a6d 100644
--- a/src/libnr/nr-rect-l.h
+++ b/src/libnr/nr-rect-l.h
@@ -1,132 +1,19 @@
#ifndef SEEN_NR_RECT_L_H
#define SEEN_NR_RECT_L_H
-#include <libnr/nr-i-coord.h>
-#include <boost/optional.hpp>
-#include <libnr/nr-rect.h>
-#include <libnr/nr-point-l.h>
+#include <glib.h>
+#include <2geom/int-rect.h>
struct NRRectL {
- boost::optional<NR::Rect> upgrade() const;
- NR::ICoord x0, y0, x1, y1;
+ gint32 x0, y0, x1, y1;
+ NRRectL();
+ NRRectL(gint32 xmin, gint32 ymin, gint32 xmax, gint32 ymax);
+ explicit NRRectL(Geom::IntRect const &r);
+ explicit NRRectL(Geom::OptIntRect const &r);
+ operator Geom::OptIntRect() const { Geom::OptIntRect r = upgrade_2geom(); return r; }
+ Geom::OptIntRect upgrade_2geom() const;
};
-
-namespace NR {
-
-
-class IRect {
-public:
- IRect(const NRRectL& r) : _min(r.x0, r.y0), _max(r.x1, r.y1) {}
- IRect(const IRect& r) : _min(r._min), _max(r._max) {}
- IRect(const IPoint &p0, const IPoint &p1) : _min(p0), _max(p1) {}
-
- /** as not all Rects are representable by IRects this gives the smallest IRect that contains
- * r. */
- IRect(const Rect& r);
-
- operator Rect() {
- return Rect(Point(_min), Point(_max));
- }
-
- const IPoint &min() const { return _min; }
- const IPoint &max() const { return _max; }
-
- /** returns a vector from min to max. */
- IPoint dimensions() const;
-
- /** does this rectangle have zero area? */
- bool isEmpty() const {
- return isEmpty<X>() && isEmpty<Y>();
- }
-
- bool intersects(const IRect &r) const {
- return intersects<X>(r) && intersects<Y>(r);
- }
- bool contains(const IRect &r) const {
- return contains<X>(r) && contains<Y>(r);
- }
- bool contains(const IPoint &p) const {
- return contains<X>(p) && contains<Y>(p);
- }
-
- ICoord maxExtent() const {
- return MAX(extent<X>(), extent<Y>());
- }
-
- ICoord extent(Dim2 axis) const {
- switch (axis) {
- case X: return extent<X>();
- case Y: return extent<Y>();
- };
- }
-
- ICoord extent(unsigned i) const throw(std::out_of_range) {
- switch (i) {
- case 0: return extent<X>();
- case 1: return extent<Y>();
- default: throw std::out_of_range("Dimension out of range");
- };
- }
-
- /** Translates the rectangle by p. */
- void offset(IPoint p);
-
- /** Makes this rectangle large enough to include the point p. */
- void expandTo(IPoint p);
-
- /** Makes this rectangle large enough to include the rectangle r. */
- void expandTo(const IRect &r);
-
- /** Returns the set of points shared by both rectangles. */
- static boost::optional<IRect> intersection(const IRect &a, const IRect &b);
-
- /** Returns the smallest rectangle that encloses both rectangles. */
- static IRect union_bounds(const IRect &a, const IRect &b);
-
- bool operator==(const IRect &other) const {
- return (min() == other.min()) && (max() == other.max());
- }
-
- bool operator!=(const IRect &other) const {
- return (min() != other.min()) || (max() != other.max());
- }
-
-private:
- IRect() {}
-
- template <NR::Dim2 axis>
- ICoord extent() const {
- return _max[axis] - _min[axis];
- }
-
- template <Dim2 axis>
- bool isEmpty() const {
- return !( _min[axis] < _max[axis] );
- }
-
- template <Dim2 axis>
- bool intersects(const IRect &r) const {
- return _max[axis] >= r._min[axis] && _min[axis] <= r._max[axis];
- }
-
- template <Dim2 axis>
- bool contains(const IRect &r) const {
- return contains(r._min) && contains(r._max);
- }
-
- template <Dim2 axis>
- bool contains(const IPoint &p) const {
- return p[axis] >= _min[axis] && p[axis] <= _max[axis];
- }
-
- IPoint _min, _max;
-};
-
-
-
-} // namespace NR
-
#endif /* !SEEN_NR_RECT_L_H */
/*
diff --git a/src/libnr/nr-rect-ops.h b/src/libnr/nr-rect-ops.h
deleted file mode 100644
index 870091a94..000000000
--- a/src/libnr/nr-rect-ops.h
+++ /dev/null
@@ -1,51 +0,0 @@
-#ifndef SEEN_NR_RECT_OPS_H
-#define SEEN_NR_RECT_OPS_H
-
-/*
- * Rect operators
- *
- * Copyright 2004 MenTaLguY <mental@rydia.net>,
- * bulia byak <buliabyak@users.sf.net>
- *
- * This code is licensed under the GNU GPL; see COPYING for more information.
- */
-
-#include <libnr/nr-rect.h>
-
-namespace NR {
-
-inline Rect expand(Rect const &r, double by) {
- NR::Point const p(by, by);
- return Rect(r.min() + p, r.max() - p);
-}
-
-inline Rect expand(Rect const &r, NR::Point by) {
- return Rect(r.min() + by, r.max() - by);
-}
-
-#if 0
-inline ConvexHull operator*(Rect const &r, Matrix const &m) {
- /* FIXME: no mention of m. Should probably be made non-inline. */
- ConvexHull points(r.corner(0));
- for ( unsigned i = 1 ; i < 4 ; i++ ) {
- points.add(r.corner(i));
- }
- return points;
-}
-#endif
-
-} /* namespace NR */
-
-
-#endif /* !SEEN_NR_RECT_OPS_H */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/libnr/nr-rect.cpp b/src/libnr/nr-rect.cpp
index 8e3672e03..67857ad49 100644
--- a/src/libnr/nr-rect.cpp
+++ b/src/libnr/nr-rect.cpp
@@ -9,25 +9,9 @@
* This code is in public domain
*/
-#include "nr-rect-l.h"
#include <algorithm>
-#include "nr-point-ops.h"
-
-NRRect::NRRect(NR::Rect const &rect)
-: x0(rect.min()[NR::X]), y0(rect.min()[NR::Y]),
- x1(rect.max()[NR::X]), y1(rect.max()[NR::Y])
-{}
-
-NRRect::NRRect(boost::optional<NR::Rect> const &rect) {
- if (rect) {
- x0 = rect->min()[NR::X];
- y0 = rect->min()[NR::Y];
- x1 = rect->max()[NR::X];
- y1 = rect->max()[NR::Y];
- } else {
- nr_rect_d_set_empty(this);
- }
-}
+#include "nr-rect.h"
+#include "nr-rect-l.h"
NRRect::NRRect(Geom::OptRect const &rect) {
if (rect) {
@@ -36,20 +20,12 @@ NRRect::NRRect(Geom::OptRect const &rect) {
x1 = rect->max()[Geom::X];
y1 = rect->max()[Geom::Y];
} else {
- nr_rect_d_set_empty(this);
- }
-}
-
-boost::optional<NR::Rect> NRRect::upgrade() const {
- if (nr_rect_d_test_empty_ptr(this)) {
- return boost::optional<NR::Rect>();
- } else {
- return NR::Rect(NR::Point(x0, y0), NR::Point(x1, y1));
+ *this = NR_RECT_EMPTY;
}
}
Geom::OptRect NRRect::upgrade_2geom() const {
- if (nr_rect_d_test_empty_ptr(this)) {
+ if (x0 > x1 || y0 > y1) {
return Geom::OptRect();
} else {
return Geom::Rect(Geom::Point(x0, y0), Geom::Point(x1, y1));
@@ -65,7 +41,7 @@ Geom::OptRect NRRect::upgrade_2geom() const {
NRRectL *nr_rect_l_intersect(NRRectL *d, const NRRectL *r0, const NRRectL *r1)
{
- NR::ICoord t;
+ gint32 t;
t = std::max(r0->x0, r1->x0);
d->x1 = std::min(r0->x1, r1->x1);
d->x0 = t;
@@ -79,7 +55,7 @@ NRRectL *nr_rect_l_intersect(NRRectL *d, const NRRectL *r0, const NRRectL *r1)
NRRect *
nr_rect_d_intersect (NRRect *d, const NRRect *r0, const NRRect *r1)
{
- NR::Coord t;
+ gint32 t;
t = MAX (r0->x0, r1->x0);
d->x1 = MIN (r0->x1, r1->x1);
d->x0 = t;
@@ -100,7 +76,7 @@ nr_rect_l_subtract(NRRectL *d, NRRectL const *r0, NRRectL const *r1)
bool inside4 = nr_rect_l_test_inside(r1, r0->x0, r0->y1);
if (inside1 && inside2 && inside3) {
- nr_rect_l_set_empty (d);
+ *d = NR_RECT_L_EMPTY;
} else if (inside1 && inside2) {
d->x0 = r0->x0;
@@ -136,7 +112,7 @@ nr_rect_l_subtract(NRRectL *d, NRRectL const *r0, NRRectL const *r1)
return d;
}
-NR::ICoord nr_rect_l_area(NRRectL *r)
+gint32 nr_rect_l_area(NRRectL *r)
{
if (!r || NR_RECT_DFLS_TEST_EMPTY (r)) {
return 0;
@@ -149,7 +125,7 @@ nr_rect_d_union (NRRect *d, const NRRect *r0, const NRRect *r1)
{
if (NR_RECT_DFLS_TEST_EMPTY (r0)) {
if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
- nr_rect_d_set_empty (d);
+ *d = NR_RECT_EMPTY;
} else {
*d = *r1;
}
@@ -157,7 +133,7 @@ nr_rect_d_union (NRRect *d, const NRRect *r0, const NRRect *r1)
if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
*d = *r0;
} else {
- NR::Coord t;
+ double t;
t = MIN (r0->x0, r1->x0);
d->x1 = MAX (r0->x1, r1->x1);
d->x0 = t;
@@ -174,7 +150,7 @@ nr_rect_l_union (NRRectL *d, const NRRectL *r0, const NRRectL *r1)
{
if (NR_RECT_DFLS_TEST_EMPTY (r0)) {
if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
- nr_rect_l_set_empty (d);
+ *d = NR_RECT_L_EMPTY;
} else {
*d = *r1;
}
@@ -182,7 +158,7 @@ nr_rect_l_union (NRRectL *d, const NRRectL *r0, const NRRectL *r1)
if (NR_RECT_DFLS_TEST_EMPTY (r1)) {
*d = *r0;
} else {
- NR::ICoord t;
+ double t;
t = MIN (r0->x0, r1->x0);
d->x1 = MAX (r0->x1, r1->x1);
d->x0 = t;
@@ -195,16 +171,13 @@ nr_rect_l_union (NRRectL *d, const NRRectL *r0, const NRRectL *r1)
}
NRRect *
-nr_rect_union_pt(NRRect *dst, NR::Point const &p)
+nr_rect_union_pt(NRRect *dst, Geom::Point const &p)
{
- using NR::X;
- using NR::Y;
-
- return nr_rect_d_union_xy(dst, p[X], p[Y]);
+ return nr_rect_d_union_xy(dst, p[Geom::X], p[Geom::Y]);
}
NRRect *
-nr_rect_d_union_xy (NRRect *d, NR::Coord x, NR::Coord y)
+nr_rect_d_union_xy (NRRect *d, double x, double y)
{
if ((d->x0 <= d->x1) && (d->y0 <= d->y1)) {
d->x0 = MIN (d->x0, x);
@@ -218,147 +191,6 @@ nr_rect_d_union_xy (NRRect *d, NR::Coord x, NR::Coord y)
return d;
}
-// TODO investigate for removal:
-NRRect *nr_rect_d_matrix_transform(NRRect *d, NRRect const *const /*s*/, NR::Matrix const & /*m*/)
-{
- // defunct
- /*
- using NR::X;
- using NR::Y;
-
- if (nr_rect_d_test_empty_ptr(s)) {
- nr_rect_d_set_empty(d);
- } else {
- NR::Point const c00(NR::Point(s->x0, s->y0) * m);
- NR::Point const c01(NR::Point(s->x0, s->y1) * m);
- NR::Point const c10(NR::Point(s->x1, s->y0) * m);
- NR::Point const c11(NR::Point(s->x1, s->y1) * m);
- d->x0 = std::min(std::min(c00[X], c01[X]),
- std::min(c10[X], c11[X]));
- d->y0 = std::min(std::min(c00[Y], c01[Y]),
- std::min(c10[Y], c11[Y]));
- d->x1 = std::max(std::max(c00[X], c01[X]),
- std::max(c10[X], c11[X]));
- d->y1 = std::max(std::max(c00[Y], c01[Y]),
- std::max(c10[Y], c11[Y]));
- }*/
- return d;
-}
-
-NRRect *
-nr_rect_d_matrix_transform(NRRect *d, NRRect const *s, NR::Matrix const *m)
-{
- return nr_rect_d_matrix_transform(d, s, *m);
-}
-
-/** Enlarges the rectangle given amount of pixels to all directions */
-NRRectL *
-nr_rect_l_enlarge(NRRectL *d, int amount)
-{
- d->x0 -= amount;
- d->y0 -= amount;
- d->x1 += amount;
- d->y1 += amount;
- return d;
-}
-
-namespace NR {
-
-Rect::Rect(const Point &p0, const Point &p1)
-: _min(std::min(p0[X], p1[X]), std::min(p0[Y], p1[Y])),
- _max(std::max(p0[X], p1[X]), std::max(p0[Y], p1[Y]))
-{}
-
-/** returns the four corners of the rectangle in the correct winding order */
-Point Rect::corner(unsigned i) const {
- switch (i % 4) {
- case 0:
- return _min;
- case 1:
- return Point(_max[X], _min[Y]);
- case 2:
- return _max;
- default: /* i.e. 3 */
- return Point(_min[X], _max[Y]);
- }
-}
-
-/** returns the midpoint of this rectangle */
-Point Rect::midpoint() const {
- return ( _min + _max ) / 2;
-}
-
-Point Rect::cornerFarthestFrom(Point const &p) const {
- Point m = midpoint();
- unsigned i = 0;
- if (p[X] < m[X]) {
- i = 1;
- }
- if (p[Y] < m[Y]) {
- i = 3 - i;
- }
- return corner(i);
-}
-
-/** returns a vector from topleft to bottom right. */
-Point Rect::dimensions() const {
- return _max - _min;
-}
-
-/** Translates the rectangle by p. */
-void Rect::offset(Point p) {
- _min += p;
- _max += p;
-}
-
-/** Makes this rectangle large enough to include the point p. */
-void Rect::expandTo(Point p) {
- for ( int i=0 ; i < 2 ; i++ ) {
- _min[i] = std::min(_min[i], p[i]);
- _max[i] = std::max(_max[i], p[i]);
- }
-}
-
-void Rect::growBy(double size) {
- for ( unsigned d = 0 ; d < 2 ; d++ ) {
- _min[d] -= size;
- _max[d] += size;
- if ( _min[d] > _max[d] ) {
- _min[d] = _max[d] = ( _min[d] + _max[d] ) / 2;
- }
- }
-}
-
-/** Returns the set of points shared by both rectangles. */
-boost::optional<Rect> intersection(boost::optional<Rect> const & a, boost::optional<Rect> const & b) {
- if ( !a || !b ) {
- return boost::optional<Rect>();
- } else {
- Rect r;
- for ( int i=0 ; i < 2 ; i++ ) {
- r._min[i] = std::max(a->_min[i], b->_min[i]);
- r._max[i] = std::min(a->_max[i], b->_max[i]);
- if ( r._min[i] > r._max[i] ) {
- return boost::optional<Rect>();
- }
- }
- return r;
- }
-}
-
-/** returns the smallest rectangle containing both rectangles */
-Rect union_bounds(Rect const &a, Rect const &b) {
- Rect r;
- for ( int i=0 ; i < 2 ; i++ ) {
- r._min[i] = std::min(a._min[i], b._min[i]);
- r._max[i] = std::max(a._max[i], b._max[i]);
- }
- return r;
-}
-
-} // namespace NR
-
-
/*
Local Variables:
mode:c++
diff --git a/src/libnr/nr-rect.h b/src/libnr/nr-rect.h
index aa5921309..4931b3e10 100644
--- a/src/libnr/nr-rect.h
+++ b/src/libnr/nr-rect.h
@@ -3,8 +3,7 @@
/** \file
* Definitions of NRRect and NR::Rect types, and some associated functions \& macros.
- */
-/*
+ *//*
* Authors:
* Lauris Kaplinski <lauris@kaplinski.com>
* Nathan Hurst <njh@mail.csse.monash.edu.au>
@@ -13,251 +12,33 @@
* This code is in public domain
*/
-
#include <stdexcept>
#include <limits>
+#include <boost/optional.hpp>
#include <glib.h>
+#include <2geom/rect.h>
+#include "libnr/nr-forward.h"
#include "libnr/nr-values.h"
-#include <libnr/nr-coord.h>
-#include <libnr/nr-i-coord.h>
-#include <libnr/nr-dim2.h>
-#include <libnr/nr-point.h>
-#include "libnr/nr-point-ops.h"
#include "libnr/nr-macros.h"
-#include <boost/optional.hpp>
-#include <libnr/nr-forward.h>
-#include <2geom/rect.h>
-
-namespace NR {
-
-class Matrix;
-
-/** A rectangle is always aligned to the X and Y axis. This means it
- * can be defined using only 4 coordinates, and determining
- * intersection is very efficient. The points inside a rectangle are
- * min[dim] <= _pt[dim] <= max[dim]. A rectangle may be empty, in the
- * sense of having zero area, but it will always contain at least one
- * point. Infinities are also permitted.
- */
-class Rect {
-public:
- Rect() : _min(-_inf(), -_inf()), _max(_inf(), _inf()) {}
- Rect(Point const &p0, Point const &p1);
-
- Point const &min() const { return _min; }
- Point const &max() const { return _max; }
-
- /** returns the four corners of the rectangle in order
- * (clockwise if +Y is up, anticlockwise if +Y is down) */
- Point corner(unsigned i) const;
-
- /** returns a vector from min to max. */
- Point dimensions() const;
-
- /** returns the midpoint of this rect. */
- Point midpoint() const;
-
- Point cornerFarthestFrom(Point const &p) const;
-
- /** True iff either width or height is less than \a epsilon. */
- bool isEmpty(double epsilon=1e-6) const {
- return isEmpty<X>(epsilon) || isEmpty<Y>(epsilon);
- }
-
- bool intersects(Rect const &r) const {
- return intersects<X>(r) && intersects<Y>(r);
- }
- bool contains(Rect const &r) const {
- return contains<X>(r) && contains<Y>(r);
- }
- bool contains(Point const &p) const {
- return contains<X>(p) && contains<Y>(p);
- }
-
- double area() const {
- return extent<X>() * extent<Y>();
- }
-
- double maxExtent() const {
- return MAX(extent<X>(), extent<Y>());
- }
-
- double extent(Dim2 const axis) const {
- switch (axis) {
- case X: return extent<X>();
- case Y: return extent<Y>();
- default: g_error("invalid axis value %d", (int) axis); return 0;
- };
- }
-
- double extent(unsigned i) const throw(std::out_of_range) {
- switch (i) {
- case 0: return extent<X>();
- case 1: return extent<Y>();
- default: throw std::out_of_range("Dimension out of range");
- };
- }
-
- /**
- \brief Remove some precision from the Rect
- \param places The number of decimal places left in the end
-
- This function just calls round on the \c _min and \c _max points.
- */
- inline void round(int places = 0) {
- _min.round(places);
- _max.round(places);
- return;
- }
-
- /** Translates the rectangle by p. */
- void offset(Point p);
-
- /** Makes this rectangle large enough to include the point p. */
- void expandTo(Point p);
-
- /** Makes this rectangle large enough to include the rectangle r. */
- void expandTo(Rect const &r);
-
- inline void move_left (gdouble by) {
- _min[NR::X] += by;
- }
- inline void move_right (gdouble by) {
- _max[NR::X] += by;
- }
- inline void move_top (gdouble by) {
- _min[NR::Y] += by;
- }
- inline void move_bottom (gdouble by) {
- _max[NR::Y] += by;
- }
-
- void growBy (gdouble by);
-
- /** Scales the rect by s, with origin at 0, 0 */
- inline Rect operator*(double const s) const {
- return Rect(s * min(), s * max());
- }
-
- inline bool operator==(Rect const &in_rect) {
- return ((this->min() == in_rect.min()) && (this->max() == in_rect.max()));
- }
-
- friend inline std::ostream &operator<<(std::ostream &out_file, NR::Rect const &in_rect);
-
-private:
-// Rect(Nothing) : _min(1, 1), _max(-1, -1) {}
-
- static double _inf() {
- return std::numeric_limits<double>::infinity();
- }
-
- template <NR::Dim2 axis>
- double extent() const {
- return _max[axis] - _min[axis];
- }
-
- template <NR::Dim2 axis>
- bool isEmpty(double epsilon) const {
- return extent<axis>() < epsilon;
- }
-
- template <Dim2 axis>
- bool intersects(Rect const &r) const {
- return _max[axis] >= r._min[axis] && _min[axis] <= r._max[axis];
- }
-
- template <Dim2 axis>
- bool contains(Rect const &r) const {
- return contains(r._min) && contains(r._max);
- }
-
- template <Dim2 axis>
- bool contains(Point const &p) const {
- return p[axis] >= _min[axis] && p[axis] <= _max[axis];
- }
-
- Point _min, _max;
-
- friend boost::optional<Rect> intersection(boost::optional<Rect> const &, boost::optional<Rect> const &);
- friend Rect union_bounds(Rect const &, Rect const &);
-};
-
-/** Returns the set of points shared by both rectangles. */
-boost::optional<Rect> intersection(boost::optional<Rect> const & a, boost::optional<Rect> const & b);
-
-/** Returns the smallest rectangle that encloses both rectangles. */
-Rect union_bounds(Rect const &a, Rect const &b);
-inline Rect union_bounds(boost::optional<Rect> const & a, Rect const &b) {
- if (a) {
- return union_bounds(*a, b);
- } else {
- return b;
- }
-}
-inline Rect union_bounds(Rect const &a, boost::optional<Rect> const & b) {
- if (b) {
- return union_bounds(a, *b);
- } else {
- return a;
- }
-}
-inline boost::optional<Rect> union_bounds(boost::optional<Rect> const & a, boost::optional<Rect> const & b)
-{
- if (!a) {
- return b;
- } else if (!b) {
- return a;
- } else {
- return union_bounds(*a, *b);
- }
-}
-
-/** A function to print out the rectange if sent to an output
- stream. */
-inline std::ostream
-&operator<<(std::ostream &out_file, NR::Rect const &in_rect)
-{
- out_file << "Rectangle:\n";
- out_file << "\tMin Point -> " << in_rect.min() << "\n";
- out_file << "\tMax Point -> " << in_rect.max() << "\n";
-
- return out_file;
-}
-
-} /* namespace NR */
/* legacy rect stuff */
-
/* NULL rect is infinite */
struct NRRect {
NRRect()
: x0(0), y0(0), x1(0), y1(0)
{}
- NRRect(NR::Coord xmin, NR::Coord ymin, NR::Coord xmax, NR::Coord ymax)
+ NRRect(double xmin, double ymin, double xmax, double ymax)
: x0(xmin), y0(ymin), x1(xmax), y1(ymax)
{}
- explicit NRRect(NR::Rect const &rect);
- explicit NRRect(boost::optional<NR::Rect> const &rect);
- operator boost::optional<NR::Rect>() const { return upgrade(); }
- boost::optional<NR::Rect> upgrade() const;
explicit NRRect(Geom::OptRect const &rect);
operator Geom::OptRect() const { return upgrade_2geom(); }
Geom::OptRect upgrade_2geom() const;
- NR::Coord x0, y0, x1, y1;
+ double x0, y0, x1, y1;
};
-#define nr_rect_d_set_empty(r) (*(r) = NR_RECT_EMPTY)
-#define nr_rect_l_set_empty(r) (*(r) = NR_RECT_L_EMPTY)
-
-/** "Empty" here includes the case of zero width or zero height. */
-// TODO convert to static overloaded functions (pointer and ref) once performance can be tested:
-#define nr_rect_d_test_empty_ptr(r) ((r) && NR_RECT_DFLS_TEST_EMPTY(r))
-#define nr_rect_d_test_empty(r) NR_RECT_DFLS_TEST_EMPTY_REF(r)
-
// TODO convert to static overloaded functions (pointer and ref) once performance can be tested:
#define nr_rect_l_test_empty_ptr(r) ((r) && NR_RECT_DFLS_TEST_EMPTY(r))
#define nr_rect_l_test_empty(r) NR_RECT_DFLS_TEST_EMPTY_REF(r)
@@ -282,7 +63,7 @@ struct NRRect {
NRRectL *nr_rect_l_subtract(NRRectL *d, NRRectL const *r0, NRRectL const *r1);
// returns the area of r
-NR::ICoord nr_rect_l_area(NRRectL *r);
+gint32 nr_rect_l_area(NRRectL *r);
/* NULL values are OK for r0 and r1, but not for d */
NRRect *nr_rect_d_intersect(NRRect *d, NRRect const *r0, NRRect const *r1);
@@ -291,13 +72,9 @@ NRRectL *nr_rect_l_intersect(NRRectL *d, NRRectL const *r0, NRRectL const *r1);
NRRect *nr_rect_d_union(NRRect *d, NRRect const *r0, NRRect const *r1);
NRRectL *nr_rect_l_union(NRRectL *d, NRRectL const *r0, NRRectL const *r1);
-NRRect *nr_rect_union_pt(NRRect *dst, NR::Point const &p);
-NRRect *nr_rect_d_union_xy(NRRect *d, NR::Coord x, NR::Coord y);
-NRRectL *nr_rect_l_union_xy(NRRectL *d, NR::ICoord x, NR::ICoord y);
-
-NRRect *nr_rect_d_matrix_transform(NRRect *d, NRRect const *s, NR::Matrix const &m);
-NRRect *nr_rect_d_matrix_transform(NRRect *d, NRRect const *s, NR::Matrix const *m);
-NRRectL *nr_rect_l_enlarge(NRRectL *d, int amount);
+NRRect *nr_rect_union_pt(NRRect *dst, Geom::Point const &p);
+NRRect *nr_rect_d_union_xy(NRRect *d, double x, double y);
+NRRectL *nr_rect_l_union_xy(NRRectL *d, gint32 x, gint32 y);
#endif /* !LIBNR_NR_RECT_H_SEEN */
diff --git a/src/libnr/nr-render.h b/src/libnr/nr-render.h
deleted file mode 100644
index 84215b7a3..000000000
--- a/src/libnr/nr-render.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef __NR_RENDER_H__
-#define __NR_RENDER_H__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- *
- * This code is in public domain
- */
-
-#include <libnr/nr-pixblock.h>
-
-struct NRRenderer;
-
-typedef void (* NRRenderFunc) (NRRenderer *r, NRPixBlock *pb, NRPixBlock *m);
-
-struct NRRenderer {
- NRRenderFunc render;
-};
-
-#define nr_render(r,pb,m) ((NRRenderer *) (r))->render ((NRRenderer *) (r), (pb), (m))
-
-#endif
diff --git a/src/libnr/nr-types-test.h b/src/libnr/nr-types-test.h
deleted file mode 100644
index 77550351f..000000000
--- a/src/libnr/nr-types-test.h
+++ /dev/null
@@ -1,142 +0,0 @@
-// nr-types-test.h
-#include <cxxtest/TestSuite.h>
-
-#include "libnr/nr-types.h"
-#include "libnr/nr-point-fns.h"
-#include <cmath>
-
-class NrTypesTest : public CxxTest::TestSuite
-{
-public:
- NrTypesTest() :
- a( 1.5, 2.0 ),
- b(-2.0, 3.0),
- ab(-0.5, 5.0),
- small(pow(2.0, -1070)),
- small_left(-small, 0.0),
- smallish_3_neg4(3.0 * small, -4.0 * small)
- {}
- virtual ~NrTypesTest() {}
-
-// createSuite and destroySuite get us per-suite setup and teardown
-// without us having to worry about static initialization order, etc.
- static NrTypesTest *createSuite() { return new NrTypesTest(); }
- static void destroySuite( NrTypesTest *suite ) { delete suite; }
-
- NR::Point const a;
- NR::Point const b;
- NR::Point const ab;
- double const small;
- NR::Point const small_left;
- NR::Point const smallish_3_neg4;
-
-
- void testXYValues( void )
- {
- TS_ASSERT_EQUALS( NR::X, 0 );
- TS_ASSERT_EQUALS( NR::Y, 1 );
- }
-
- void testXYCtorAndArrayConst(void)
- {
- TS_ASSERT_EQUALS( a[NR::X], 1.5 );
- TS_ASSERT_EQUALS( a[NR::Y], 2.0 );
- }
-
- void testCopyCtor(void)
- {
- NR::Point a_copy(a);
-
- TS_ASSERT_EQUALS( a, a_copy );
- TS_ASSERT( !(a != a_copy) );
- }
-
- void testNonConstArrayOperator(void)
- {
- NR::Point a_copy(a);
- a_copy[NR::X] = -2.0;
- TS_ASSERT_DIFFERS( a_copy, a );
- TS_ASSERT_DIFFERS( a_copy, b );
- a_copy[NR::Y] = 3.0;
- TS_ASSERT_EQUALS( a_copy, b );
- }
-
- void testBinaryPlusMinus(void)
- {
- TS_ASSERT_DIFFERS( a, b );
- TS_ASSERT_EQUALS( a + b, ab );
- TS_ASSERT_EQUALS( ab - a, b );
- TS_ASSERT_EQUALS( ab - b, a );
- TS_ASSERT_DIFFERS( ab + a, b );
- }
-
- void testUnaryMinus(void)
- {
- TS_ASSERT_EQUALS( -a, NR::Point(-a[NR::X], -a[NR::Y]) );
- }
-
- void tetScaleDivide(void)
- {
- TS_ASSERT_EQUALS( -a, -1.0 * a );
- TS_ASSERT_EQUALS( a + a + a, 3.0 * a );
- TS_ASSERT_EQUALS( a / .5, 2.0 * a );
- }
-
- void testDot(void)
- {
- TS_ASSERT_EQUALS( dot(a, b), ( a[NR::X] * b[NR::X] +
- a[NR::Y] * b[NR::Y] ) );
- TS_ASSERT_EQUALS( dot(a, NR::rot90(a)), 0.0 );
- TS_ASSERT_EQUALS( dot(-a, NR::rot90(a)), 0.0 );
- }
-
- void testL1L2LInftyNorms(void)
- {
- // TODO look at TS_ASSERT_DELTA
-
- TS_ASSERT_EQUALS( L1(small_left), small );
- TS_ASSERT_EQUALS( L2(small_left), small );
- TS_ASSERT_EQUALS( LInfty(small_left), small );
-
- TS_ASSERT_EQUALS( L1(smallish_3_neg4), 7.0 * small );
- TS_ASSERT_EQUALS( L2(smallish_3_neg4), 5.0 * small );
- TS_ASSERT_EQUALS( LInfty(smallish_3_neg4), 4.0 * small );
- }
-
- void testOperatorPlusEquals(void)
- {
- NR::Point x(a);
- x += b;
- TS_ASSERT_EQUALS( x, ab );
- }
-
- void tetOperatorDivEquals(void)
- {
- NR::Point x(a);
- x /= .5;
- TS_ASSERT_EQUALS( x, a + a );
- }
-
- void testNormalize(void)
- {
- NR::Point x(small_left);
- x.normalize();
- TS_ASSERT_EQUALS( x, NR::Point(-1.0, 0.0) );
-
- x = smallish_3_neg4;
- x.normalize();
- TS_ASSERT_EQUALS( x, NR::Point(0.6, -0.8) );
- }
-
-};
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libnr/nr-types.cpp b/src/libnr/nr-types.cpp
deleted file mode 100644
index 0231c91d5..000000000
--- a/src/libnr/nr-types.cpp
+++ /dev/null
@@ -1,68 +0,0 @@
-/** \file
- * Implements NR::Point::normalize()
- */
-
-#include <libnr/nr-types.h>
-
-#include "2geom/isnan.h"
-
-/** Scales this vector to make it a unit vector (within rounding error).
- *
- * The current version tries to handle infinite coordinates gracefully,
- * but it's not clear that any callers need that.
- *
- * \pre *this != Point(0, 0).
- * \pre Neither coordinate is NaN.
- * \post L2(*this) very near 1.0.
- */
-void NR::Point::normalize() {
- double len = hypot(_pt[0], _pt[1]);
- g_return_if_fail(len != 0);
- g_return_if_fail(!IS_NAN(len));
- static double const inf = 1e400;
- if(len != inf) {
- *this /= len;
- } else {
- unsigned n_inf_coords = 0;
- /* Delay updating pt in case neither coord is infinite. */
- NR::Point tmp;
- for ( unsigned i = 0 ; i < 2 ; ++i ) {
- if ( _pt[i] == inf ) {
- ++n_inf_coords;
- tmp[i] = 1.0;
- } else if ( _pt[i] == -inf ) {
- ++n_inf_coords;
- tmp[i] = -1.0;
- } else {
- tmp[i] = 0.0;
- }
- }
- switch (n_inf_coords) {
- case 0:
- /* Can happen if both coords are near +/-DBL_MAX. */
- *this /= 4.0;
- len = hypot(_pt[0], _pt[1]);
- g_assert(len != inf);
- *this /= len;
- break;
-
- case 1:
- *this = tmp;
- break;
-
- case 2:
- *this = sqrt(0.5) * tmp;
- break;
- }
- }
-}
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libnr/nr-types.h b/src/libnr/nr-types.h
deleted file mode 100644
index 685c29342..000000000
--- a/src/libnr/nr-types.h
+++ /dev/null
@@ -1,39 +0,0 @@
-#ifndef __NR_TYPES_H__
-#define __NR_TYPES_H__
-
-/*
- * Pixel buffer rendering library
- *
- * Authors:
- * Lauris Kaplinski <lauris@kaplinski.com>
- * Class-ifying NRPoint, Nathan Hurst <njh@mail.csse.monash.edu.au>
- *
- * This code is in public domain
- */
-
-#if HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <libnr/nr-coord.h>
-#include <libnr/nr-dim2.h>
-#include <libnr/nr-i-coord.h>
-#include <libnr/nr-point.h>
-#include <libnr/nr-point-l.h>
-#include <libnr/nr-point-ops.h>
-#include <libnr/nr-rect.h>
-#include <libnr/nr-rect-l.h>
-#include <libnr/nr-forward.h>
-
-#endif /* !__NR_TYPES_H__ */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
diff --git a/src/libnr/nr-values.cpp b/src/libnr/nr-values.cpp
index 9193eff3b..06f33b13f 100644
--- a/src/libnr/nr-values.cpp
+++ b/src/libnr/nr-values.cpp
@@ -1,20 +1,18 @@
#define __NR_VALUES_C__
-#include <libnr/nr-rect-l.h>
+#include "libnr/nr-values.h"
#include "libnr/nr-rect.h"
+#include "libnr/nr-rect-l.h"
/*
The following predefined objects are for reference
and comparison.
*/
NRRect NR_RECT_EMPTY(NR_HUGE, NR_HUGE, -NR_HUGE, -NR_HUGE);
-NRRectL NR_RECT_L_EMPTY =
- {NR_HUGE_L, NR_HUGE_L, -NR_HUGE_L, -NR_HUGE_L};
-NRRectL NR_RECT_S_EMPTY =
- {NR_HUGE_S, NR_HUGE_S, -NR_HUGE_S, -NR_HUGE_S};
+NRRectL NR_RECT_L_EMPTY(NR_HUGE_L, NR_HUGE_L, -NR_HUGE_L, -NR_HUGE_L);
/** component_vectors[i] is like $e_i$ in common mathematical usage;
or equivalently $I_i$ (where $I$ is the identity matrix). */
-NR::Point const component_vectors[] = {NR::Point(1., 0.),
- NR::Point(0., 1.)};
+Geom::Point const component_vectors[] = {Geom::Point(1., 0.),
+ Geom::Point(0., 1.)};
diff --git a/src/libnr/nr-values.h b/src/libnr/nr-values.h
index f85fca690..07faec9fa 100644
--- a/src/libnr/nr-values.h
+++ b/src/libnr/nr-values.h
@@ -11,12 +11,12 @@
*/
#include <libnr/nr-forward.h>
+#include <2geom/point.h>
#define NR_EPSILON 1e-18
#define NR_HUGE 1e18
#define NR_HUGE_L (0x7fffffff)
-#define NR_HUGE_S (0x7fff)
/*
The following predefined objects are for reference
@@ -24,11 +24,10 @@ and comparison. They are defined in nr-values.cpp
*/
extern NRRect NR_RECT_EMPTY;
extern NRRectL NR_RECT_L_EMPTY;
-extern NRRectL NR_RECT_S_EMPTY;
/** component_vectors[i] has 1.0 at position i, and 0.0 elsewhere
(i.e. in the other position). */
-extern NR::Point const component_vectors[2];
+extern Geom::Point const component_vectors[2];
#endif
diff --git a/src/libnr/nr_config.h.mingw b/src/libnr/nr_config.h.mingw
deleted file mode 100644
index 6992cc6fc..000000000
--- a/src/libnr/nr_config.h.mingw
+++ /dev/null
@@ -1,12 +0,0 @@
-#define NR_SIZEOF_CHAR 1
-#define NR_SIZEOF_SHORT 2
-#define NR_SIZEOF_INT 4
-#define NR_SIZEOF_LONG 4
-
-typedef signed char NRByte;
-typedef unsigned char NRUByte;
-typedef signed short NRShort;
-typedef unsigned short NRUShort;
-typedef signed int NRLong;
-typedef unsigned long NRULong;
-
diff --git a/src/libnr/nr_config.h.win32 b/src/libnr/nr_config.h.win32
deleted file mode 100644
index e0bfbda3f..000000000
--- a/src/libnr/nr_config.h.win32
+++ /dev/null
@@ -1,14 +0,0 @@
-#define NR_SIZEOF_CHAR 1
-#define NR_SIZEOF_SHORT 2
-#define NR_SIZEOF_INT 4
-#define NR_SIZEOF_LONG 4
-
-typedef signed char NRByte;
-typedef unsigned char NRUByte;
-typedef signed short NRShort;
-typedef unsigned short NRUShort;
-typedef signed int NRLong;
-typedef unsigned long NRULong;
-
-
-
diff --git a/src/libvpsc/generate-constraints.cpp b/src/libvpsc/generate-constraints.cpp
index c57966e26..0c35ab51c 100644
--- a/src/libvpsc/generate-constraints.cpp
+++ b/src/libvpsc/generate-constraints.cpp
@@ -16,7 +16,7 @@
#include "generate-constraints.h"
#include "constraint.h"
-#include "2geom/isnan.h" /* Include last */
+#include <2geom/math-utils.h>
using std::set;
using std::vector;
diff --git a/src/livarot/Path.h b/src/livarot/Path.h
index b8041c63a..78e90c34f 100644
--- a/src/livarot/Path.h
+++ b/src/livarot/Path.h
@@ -12,9 +12,8 @@
#include <vector>
#include "LivarotDefs.h"
#include "livarot/livarot-forward.h"
-#include "libnr/nr-point.h"
#include <libnr/nr-rect-l.h>
-#include <2geom/forward.h>
+#include <2geom/point.h>
struct SPStyle;
diff --git a/src/livarot/PathSimplify.cpp b/src/livarot/PathSimplify.cpp
index fb2aa55e2..fe1981e4d 100644
--- a/src/livarot/PathSimplify.cpp
+++ b/src/livarot/PathSimplify.cpp
@@ -7,6 +7,7 @@
*/
#include <glib/gmem.h>
+#include <2geom/affine.h>
#include "livarot/Path.h"
#include "livarot/path-description.h"
diff --git a/src/livarot/Shape.cpp b/src/livarot/Shape.cpp
index 9107844be..d24e4b99d 100644
--- a/src/livarot/Shape.cpp
+++ b/src/livarot/Shape.cpp
@@ -2225,7 +2225,7 @@ double distance(Shape const *s, Geom::Point const &p)
if ( el > 0.001 ) {
double const npr = Geom::dot(d, e);
if ( npr > 0 && npr < el ) {
- double const nl = fabs( NR::cross(d, e) );
+ double const nl = fabs( Geom::cross(d, e) );
double ndot = nl * nl / el;
if ( ndot < bdot ) {
bdot = ndot;
@@ -2271,7 +2271,7 @@ bool distanceLessThanOrEqual(Shape const *s, Geom::Point const &p, double const
double const max_l1 = max_l2 * M_SQRT2;
for (int i = 0; i < s->numberOfPoints(); i++) {
Geom::Point const offset( p - s->getPoint(i).x );
- double const l1 = NR::L1(offset);
+ double const l1 = Geom::L1(offset);
if ( (l1 <= max_l2) || ((l1 <= max_l1) && (Geom::L2(offset) <= max_l2)) ) {
return true;
}
@@ -2288,7 +2288,7 @@ bool distanceLessThanOrEqual(Shape const *s, Geom::Point const &p, double const
Geom::Point const e_unit(e / el);
double const npr = Geom::dot(d, e_unit);
if ( npr > 0 && npr < el ) {
- double const nl = fabs(NR::cross(d, e_unit));
+ double const nl = fabs(Geom::cross(d, e_unit));
if ( nl <= max_l2 ) {
return true;
}
diff --git a/src/livarot/Shape.h b/src/livarot/Shape.h
index 5649ff9e4..158977897 100644
--- a/src/livarot/Shape.h
+++ b/src/livarot/Shape.h
@@ -14,8 +14,8 @@
#include <cstdlib>
#include <cstring>
#include <vector>
+#include <2geom/point.h>
-#include "libnr/nr-point.h"
#include "livarot/livarot-forward.h"
#include "livarot/LivarotDefs.h"
diff --git a/src/livarot/path-description.h b/src/livarot/path-description.h
index 1d0dfb57e..e9818b55b 100644
--- a/src/livarot/path-description.h
+++ b/src/livarot/path-description.h
@@ -1,8 +1,8 @@
#ifndef SEEN_INKSCAPE_LIVAROT_PATH_DESCRIPTION_H
#define SEEN_INKSCAPE_LIVAROT_PATH_DESCRIPTION_H
+#include <2geom/point.h>
#include "svg/stringstream.h"
-#include "libnr/nr-point.h"
// path description commands
/* FIXME: these should be unnecessary once the refactoring of the path
diff --git a/src/livarot/sweep-event.h b/src/livarot/sweep-event.h
index dab006101..5df952731 100644
--- a/src/livarot/sweep-event.h
+++ b/src/livarot/sweep-event.h
@@ -4,7 +4,7 @@
* Intersection events.
*/
-#include <libnr/nr-point.h>
+#include <2geom/point.h>
class SweepTree;
diff --git a/src/livarot/sweep-tree.h b/src/livarot/sweep-tree.h
index 4a2efe5ec..bbb027b24 100644
--- a/src/livarot/sweep-tree.h
+++ b/src/livarot/sweep-tree.h
@@ -1,8 +1,8 @@
#ifndef INKSCAPE_LIVAROT_SWEEP_TREE_H
#define INKSCAPE_LIVAROT_SWEEP_TREE_H
-#include "libnr/nr-point.h"
#include "livarot/AVL.h"
+#include <2geom/point.h>
class Shape;
class SweepEvent;
diff --git a/src/live_effects/lpe-spiro.cpp b/src/live_effects/lpe-spiro.cpp
index 54554ebb2..22974fe13 100644
--- a/src/live_effects/lpe-spiro.cpp
+++ b/src/live_effects/lpe-spiro.cpp
@@ -12,7 +12,6 @@
#include <2geom/affine.h>
#include <2geom/bezier-curve.h>
#include <2geom/hvlinesegment.h>
-#include <2geom/isnan.h>
#include "helper/geom-nodetype.h"
#include "helper/geom-curves.h"
diff --git a/src/marker.cpp b/src/marker.cpp
index e82d3d952..2354d686c 100644
--- a/src/marker.cpp
+++ b/src/marker.cpp
@@ -19,6 +19,7 @@
#include "libnr/nr-convert2geom.h"
#include <2geom/affine.h>
+#include <2geom/transforms.h>
#include "svg/svg.h"
#include "display/nr-arena-group.h"
#include "xml/repr.h"
diff --git a/src/object-edit.cpp b/src/object-edit.cpp
index 553c125a3..28c8d44db 100644
--- a/src/object-edit.cpp
+++ b/src/object-edit.cpp
@@ -35,7 +35,7 @@
#include <glibmm/i18n.h>
#include "object-edit.h"
#include "xml/repr.h"
-#include "2geom/isnan.h"
+#include <2geom/math-utils.h>
#define sp_round(v,m) (((v) < 0.0) ? ((ceil((v) / (m) - 0.5)) * (m)) : ((floor((v) / (m) + 0.5)) * (m)))
@@ -959,7 +959,7 @@ StarKnotHolderEntity1::knot_set(Geom::Point const &p, Geom::Point const &/*origi
Geom::Point const s = snap_knot_position(p);
- Geom::Point d = s - to_2geom(star->center);
+ Geom::Point d = s - star->center;
double arg1 = atan2(d);
double darg1 = arg1 - star->arg[0];
@@ -986,7 +986,7 @@ StarKnotHolderEntity2::knot_set(Geom::Point const &p, Geom::Point const &/*origi
Geom::Point const s = snap_knot_position(p);
if (star->flatsided == false) {
- Geom::Point d = s - to_2geom(star->center);
+ Geom::Point d = s - star->center;
double arg1 = atan2(d);
double darg1 = arg1 - star->arg[1];
diff --git a/src/pen-context.cpp b/src/pen-context.cpp
index 64137d56f..19e0351a3 100644
--- a/src/pen-context.cpp
+++ b/src/pen-context.cpp
@@ -38,7 +38,6 @@
#include "display/sp-ctrlline.h"
#include "display/sodipodi-ctrl.h"
#include <glibmm/i18n.h>
-#include "libnr/nr-point-ops.h"
#include "helper/units.h"
#include "macros.h"
#include "context-fns.h"
@@ -913,7 +912,7 @@ pen_redraw_all (SPPenContext *const pc)
if (last_seg) {
Geom::CubicBezier const * cubic = dynamic_cast<Geom::CubicBezier const *>( last_seg );
if ( cubic &&
- (*cubic)[2] != to_2geom(pc->p[0]) )
+ (*cubic)[2] != pc->p[0] )
{
Geom::Point p2 = (*cubic)[2];
SP_CTRL(pc->c0)->moveto(p2);
diff --git a/src/pencil-context.cpp b/src/pencil-context.cpp
index a873eb6fc..57205a436 100644
--- a/src/pencil-context.cpp
+++ b/src/pencil-context.cpp
@@ -57,10 +57,10 @@ static gint pencil_handle_button_release(SPPencilContext *const pc, GdkEventButt
static gint pencil_handle_key_press(SPPencilContext *const pc, guint const keyval, guint const state);
static gint pencil_handle_key_release(SPPencilContext *const pc, guint const keyval, guint const state);
-static void spdc_set_startpoint(SPPencilContext *pc, Geom::Point const p);
-static void spdc_set_endpoint(SPPencilContext *pc, Geom::Point const p);
+static void spdc_set_startpoint(SPPencilContext *pc, Geom::Point const &p);
+static void spdc_set_endpoint(SPPencilContext *pc, Geom::Point const &p);
static void spdc_finish_endpoint(SPPencilContext *pc);
-static void spdc_add_freehand_point(SPPencilContext *pc, Geom::Point p, guint state);
+static void spdc_add_freehand_point(SPPencilContext *pc, Geom::Point const &p, guint state);
static void fit_and_split(SPPencilContext *pc);
static void interpolate(SPPencilContext *pc);
static void sketch_interpolate(SPPencilContext *pc);
@@ -644,7 +644,7 @@ pencil_handle_key_release(SPPencilContext *const pc, guint const keyval, guint c
* Reset points and set new starting point.
*/
static void
-spdc_set_startpoint(SPPencilContext *const pc, Geom::Point const p)
+spdc_set_startpoint(SPPencilContext *const pc, Geom::Point const &p)
{
pc->npoints = 0;
pc->red_curve_is_valid = false;
@@ -664,7 +664,7 @@ spdc_set_startpoint(SPPencilContext *const pc, Geom::Point const p)
* We change RED curve.
*/
static void
-spdc_set_endpoint(SPPencilContext *const pc, Geom::Point const p)
+spdc_set_endpoint(SPPencilContext *const pc, Geom::Point const &p)
{
if (pc->npoints == 0) {
return;
@@ -716,7 +716,7 @@ spdc_finish_endpoint(SPPencilContext *const pc)
static void
-spdc_add_freehand_point(SPPencilContext *pc, Geom::Point p, guint /*state*/)
+spdc_add_freehand_point(SPPencilContext *pc, Geom::Point const &p, guint /*state*/)
{
g_assert( pc->npoints > 0 );
g_return_if_fail(unsigned(pc->npoints) < G_N_ELEMENTS(pc->p));
diff --git a/src/rect-context.cpp b/src/rect-context.cpp
index 7f32e09fa..188b5a9a3 100644
--- a/src/rect-context.cpp
+++ b/src/rect-context.cpp
@@ -281,14 +281,14 @@ static gint sp_rect_context_root_handler(SPEventContext *event_context, GdkEvent
/* Position center */
Geom::Point button_dt(desktop->w2d(button_w));
- rc->center = from_2geom(button_dt);
+ rc->center = button_dt;
/* Snap center */
SnapManager &m = desktop->namedview->snap_manager;
m.setup(desktop);
m.freeSnapReturnByRef(button_dt, Inkscape::SNAPSOURCE_NODE_HANDLE);
m.unSetup();
- rc->center = from_2geom(button_dt);
+ rc->center = button_dt;
sp_canvas_item_grab(SP_CANVAS_ITEM(desktop->acetate),
( GDK_KEY_PRESS_MASK |
diff --git a/src/rect-context.h b/src/rect-context.h
index e5d160788..b6fbb6854 100644
--- a/src/rect-context.h
+++ b/src/rect-context.h
@@ -16,8 +16,8 @@
#include <stddef.h>
#include <sigc++/sigc++.h>
+#include <2geom/point.h>
#include "event-context.h"
-#include "libnr/nr-point.h"
#define SP_TYPE_RECT_CONTEXT (sp_rect_context_get_type ())
#define SP_RECT_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_RECT_CONTEXT, SPRectContext))
diff --git a/src/removeoverlap.cpp b/src/removeoverlap.cpp
index b01ae5228..a503fea35 100644
--- a/src/removeoverlap.cpp
+++ b/src/removeoverlap.cpp
@@ -10,12 +10,13 @@
*
* Released under GNU LGPL. Read the file 'COPYING' for more information.
*/
+#include <utility>
+#include <2geom/transforms.h>
#include "util/glib-list-iterators.h"
#include "sp-item.h"
#include "sp-item-transform.h"
#include "libvpsc/generate-constraints.h"
#include "libvpsc/remove_rectangle_overlap.h"
-#include <utility>
using vpsc::Rectangle;
diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp
index 6f385b8f5..9b88077e7 100644
--- a/src/selection-chemistry.cpp
+++ b/src/selection-chemistry.cpp
@@ -777,7 +777,7 @@ enclose_items(GSList const *items)
Geom::OptRect r;
for (GSList const *i = items; i; i = i->next) {
- r = Geom::unify(r, ((SPItem *) i->data)->getBboxDesktop());
+ r.unionWith(((SPItem *) i->data)->getBboxDesktop());
}
return r;
}
diff --git a/src/selection.cpp b/src/selection.cpp
index 7564fad3a..3007a3d1f 100644
--- a/src/selection.cpp
+++ b/src/selection.cpp
@@ -375,7 +375,7 @@ Geom::OptRect Selection::bounds(SPItem::BBoxType type) const
Geom::OptRect bbox;
for ( GSList const *i = items ; i != NULL ; i = i->next ) {
- bbox = unify(bbox, SP_ITEM(i->data)->getBboxDesktop(type));
+ bbox.unionWith(SP_ITEM(i->data)->getBboxDesktop(type));
}
return bbox;
}
@@ -403,7 +403,7 @@ NRRect *Selection::boundsInDocument(NRRect *bbox, SPItem::BBoxType type) const {
Geom::OptRect Selection::boundsInDocument(SPItem::BBoxType type) const {
NRRect r;
- return to_2geom(boundsInDocument(&r, type)->upgrade());
+ return to_2geom(boundsInDocument(&r, type));
}
/** Extract the position of the center from the first selected object */
diff --git a/src/snap.cpp b/src/snap.cpp
index bf1613d2c..3e79a221e 100644
--- a/src/snap.cpp
+++ b/src/snap.cpp
@@ -19,6 +19,7 @@
*/
#include <utility>
+#include <2geom/transforms.h>
#include "sp-namedview.h"
#include "snap.h"
@@ -293,7 +294,7 @@ Geom::Point SnapManager::multipleOfGridPitch(Geom::Point const &t, Geom::Point c
// use getSnapDistance() instead of getWeightedDistance() here because the pointer's position
// doesn't tell us anything about which node to snap
success = true;
- nearest_multiple = s.getPoint() - to_2geom(grid->origin);
+ nearest_multiple = s.getPoint() - grid->origin;
nearest_distance = s.getSnapDistance();
bestSnappedPoint = s;
}
diff --git a/src/sp-clippath.cpp b/src/sp-clippath.cpp
index 147ece167..48e466628 100644
--- a/src/sp-clippath.cpp
+++ b/src/sp-clippath.cpp
@@ -89,6 +89,7 @@ void SPClipPath::build(SPObject *object, SPDocument *document, Inkscape::XML::No
if (((SPObjectClass *) SPClipPathClass::static_parent_class)->build)
((SPObjectClass *) SPClipPathClass::static_parent_class)->build(object, document, repr);
+ object->readAttr( "style" );
object->readAttr( "clipPathUnits" );
/* Register ourselves */
@@ -132,8 +133,13 @@ void SPClipPath::set(SPObject *object, unsigned int key, gchar const *value)
object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
default:
- if (((SPObjectClass *) SPClipPathClass::static_parent_class)->set) {
- ((SPObjectClass *) SPClipPathClass::static_parent_class)->set(object, key, value);
+ if (SP_ATTRIBUTE_IS_CSS(key)) {
+ sp_style_read_from_object(object->style, object);
+ object->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
+ } else {
+ if (((SPObjectClass *) SPClipPathClass::static_parent_class)->set) {
+ ((SPObjectClass *) SPClipPathClass::static_parent_class)->set(object, key, value);
+ }
}
break;
}
@@ -258,6 +264,7 @@ NRArenaItem *SPClipPath::show(NRArena *arena, unsigned int key)
t[5] = display->bbox.y0;
nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), &t);
}
+ nr_arena_group_set_style(NR_ARENA_GROUP(ai), this->style);
return ai;
}
diff --git a/src/sp-conn-end-pair.h b/src/sp-conn-end-pair.h
index 6e62b9839..98096a246 100644
--- a/src/sp-conn-end-pair.h
+++ b/src/sp-conn-end-pair.h
@@ -14,7 +14,6 @@
#include <glib/gtypes.h>
#include "forward.h"
-#include "libnr/nr-point.h"
#include <stddef.h>
#include <sigc++/connection.h>
#include <sigc++/functors/slot.h>
diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp
index 3413999a9..ab545919f 100644
--- a/src/sp-flowtext.cpp
+++ b/src/sp-flowtext.cpp
@@ -361,7 +361,10 @@ sp_flowtext_print(SPItem *item, SPPrintContext *ctx)
if (!bbox_maybe) {
return;
}
- bbox = NRRect(from_2geom(*bbox_maybe));
+ bbox.x0 = bbox_maybe->min()[Geom::X];
+ bbox.y0 = bbox_maybe->min()[Geom::Y];
+ bbox.x1 = bbox_maybe->max()[Geom::X];
+ bbox.y1 = bbox_maybe->max()[Geom::Y];
NRRect dbox;
dbox.x0 = 0.0;
diff --git a/src/sp-image.cpp b/src/sp-image.cpp
index ee70d2ca7..791e88b39 100644
--- a/src/sp-image.cpp
+++ b/src/sp-image.cpp
@@ -25,6 +25,7 @@
#include <string>
#include <glib/gstdio.h>
#include <2geom/rect.h>
+#include <2geom/transforms.h>
#include <glibmm/i18n.h>
#include "display/nr-arena-image.h"
@@ -1498,7 +1499,7 @@ static void sp_image_set_curve( SPImage *image )
} else {
NRRect rect;
sp_image_bbox(image, &rect, Geom::identity(), 0);
- Geom::Rect rect2 = to_2geom(*rect.upgrade());
+ Geom::Rect rect2 = *to_2geom(&rect);
SPCurve *c = SPCurve::new_from_rect(rect2, true);
if (image->curve) {
diff --git a/src/sp-item.cpp b/src/sp-item.cpp
index 7e5f5f96a..8e1a4d92c 100644
--- a/src/sp-item.cpp
+++ b/src/sp-item.cpp
@@ -299,7 +299,7 @@ Geom::Point SPItem::getCenter() const {
Geom::OptRect bbox = getBounds(i2d_affine());
if (bbox) {
- return to_2geom(bbox->midpoint()) + Geom::Point (transform_center_x, transform_center_y);
+ return bbox->midpoint() + Geom::Point (transform_center_x, transform_center_y);
} else {
return Geom::Point(0, 0); // something's wrong!
}
@@ -825,7 +825,7 @@ void SPItem::invoke_bbox_full( Geom::OptRect &bbox, Geom::Affine const &transfor
// would therefore be translated into empty Geom::OptRect() (see bug https://bugs.launchpad.net/inkscape/+bug/168684)
Geom::OptRect temp_bbox_new = Geom::Rect(Geom::Point(temp_bbox.x0, temp_bbox.y0), Geom::Point(temp_bbox.x1, temp_bbox.y1));
- bbox = Geom::unify(bbox, temp_bbox_new);
+ bbox.unionWith(temp_bbox_new);
}
// DEPRECATED to phase out the use of NRRect in favor of Geom::OptRect
diff --git a/src/sp-mask.cpp b/src/sp-mask.cpp
index 76efb6b4b..38599188f 100644
--- a/src/sp-mask.cpp
+++ b/src/sp-mask.cpp
@@ -13,10 +13,11 @@
#include <cstring>
#include <string>
+#include <2geom/transforms.h>
#include "display/nr-arena.h"
#include "display/nr-arena-group.h"
-#include <xml/repr.h>
+#include "xml/repr.h"
#include "enums.h"
#include "attributes.h"
diff --git a/src/sp-namedview.cpp b/src/sp-namedview.cpp
index 97fd97570..ac2d7dc1b 100644
--- a/src/sp-namedview.cpp
+++ b/src/sp-namedview.cpp
@@ -17,6 +17,7 @@
#include "config.h"
#include <cstring>
#include <string>
+#include <2geom/transforms.h>
#include "display/canvas-grid.h"
#include "display/guideline.h"
@@ -1107,8 +1108,7 @@ void SPNamedView::translateGuides(Geom::Translate const &tr) {
for (GSList *l = guides; l != NULL; l = l->next) {
SPGuide &guide = *SP_GUIDE(l->data);
Geom::Point point_on_line = guide.point_on_line;
- point_on_line[0] += tr[0];
- point_on_line[1] += tr[1];
+ point_on_line *= tr;
sp_guide_moveto(guide, point_on_line, true);
}
}
diff --git a/src/sp-offset.cpp b/src/sp-offset.cpp
index 460421492..0dd65c7b9 100644
--- a/src/sp-offset.cpp
+++ b/src/sp-offset.cpp
@@ -844,7 +844,7 @@ sp_offset_distance_to_original (SPOffset * offset, Geom::Point px)
{
// we have a new minimum distance
// now we need to wheck if px is inside or outside (for the sign)
- nx = px - to_2geom(theRes->getPoint(i).x);
+ nx = px - theRes->getPoint(i).x;
double nlen = sqrt (dot(nx , nx));
nx /= nlen;
int pb, cb, fb;
diff --git a/src/sp-root.cpp b/src/sp-root.cpp
index b1eef65d2..7d72b7695 100644
--- a/src/sp-root.cpp
+++ b/src/sp-root.cpp
@@ -19,6 +19,7 @@
#include <cstring>
#include <string>
+#include <2geom/transforms.h>
#include "svg/svg.h"
#include "display/nr-arena-group.h"
diff --git a/src/sp-text.h b/src/sp-text.h
index c98721ec9..cd103aa2a 100644
--- a/src/sp-text.h
+++ b/src/sp-text.h
@@ -19,7 +19,6 @@
#include "sp-item.h"
#include "sp-string.h"
#include "text-tag-attributes.h"
-#include "libnr/nr-point.h"
#include "libnrtype/Layout-TNG.h"
diff --git a/src/spiral-context.cpp b/src/spiral-context.cpp
index cbe7166c5..93ff48c3e 100644
--- a/src/spiral-context.cpp
+++ b/src/spiral-context.cpp
@@ -53,7 +53,7 @@ static void sp_spiral_context_set(SPEventContext *ec, Inkscape::Preferences::Ent
static gint sp_spiral_context_root_handler(SPEventContext *event_context, GdkEvent *event);
-static void sp_spiral_drag(SPSpiralContext *sc, Geom::Point p, guint state);
+static void sp_spiral_drag(SPSpiralContext *sc, Geom::Point const &p, guint state);
static void sp_spiral_finish(SPSpiralContext *sc);
static void sp_spiral_cancel(SPSpiralContext *sc);
@@ -275,7 +275,7 @@ sp_spiral_context_root_handler(SPEventContext *event_context, GdkEvent *event)
m.setup(desktop, true, sc->item);
m.freeSnapReturnByRef(motion_dt, Inkscape::SNAPSOURCE_NODE_HANDLE);
m.unSetup();
- sp_spiral_drag(sc, from_2geom(motion_dt), event->motion.state);
+ sp_spiral_drag(sc, motion_dt, event->motion.state);
gobble_motion_events(GDK_BUTTON1_MASK);
@@ -399,7 +399,7 @@ sp_spiral_context_root_handler(SPEventContext *event_context, GdkEvent *event)
return ret;
}
-static void sp_spiral_drag(SPSpiralContext *sc, Geom::Point p, guint state)
+static void sp_spiral_drag(SPSpiralContext *sc, Geom::Point const &p, guint state)
{
SPDesktop *desktop = SP_EVENT_CONTEXT(sc)->desktop;
@@ -430,7 +430,7 @@ static void sp_spiral_drag(SPSpiralContext *sc, Geom::Point p, guint state)
SnapManager &m = desktop->namedview->snap_manager;
m.setup(desktop, true, sc->item);
- Geom::Point pt2g = to_2geom(p);
+ Geom::Point pt2g = p;
m.freeSnapReturnByRef(pt2g, Inkscape::SNAPSOURCE_NODE_HANDLE);
m.unSetup();
Geom::Point const p0 = desktop->dt2doc(sc->center);
diff --git a/src/spiral-context.h b/src/spiral-context.h
index dd447dbfe..12c0b5d68 100644
--- a/src/spiral-context.h
+++ b/src/spiral-context.h
@@ -18,8 +18,8 @@
#include <gtk/gtk.h>
#include <stddef.h>
#include <sigc++/sigc++.h>
+#include <2geom/point.h>
#include "event-context.h"
-#include "libnr/nr-point.h"
#define SP_TYPE_SPIRAL_CONTEXT (sp_spiral_context_get_type ())
#define SP_SPIRAL_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_SPIRAL_CONTEXT, SPSpiralContext))
diff --git a/src/spray-context.cpp b/src/spray-context.cpp
index be0cb627f..b2d99a696 100644
--- a/src/spray-context.cpp
+++ b/src/spray-context.cpp
@@ -56,7 +56,6 @@
#include "display/canvas-arena.h"
#include "display/curve.h"
#include "livarot/Shape.h"
-#include <2geom/isnan.h>
#include <2geom/transforms.h>
#include "preferences.h"
#include "style.h"
diff --git a/src/spray-context.h b/src/spray-context.h
index 247c07130..f3564ac67 100644
--- a/src/spray-context.h
+++ b/src/spray-context.h
@@ -18,8 +18,8 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <2geom/point.h>
#include "event-context.h"
-#include <libnr/nr-point.h>
//#include "ui/widget/spray-option.h"
#include "ui/dialog/dialog.h"
diff --git a/src/star-context.cpp b/src/star-context.cpp
index 17a8e915f..878ecfbe7 100644
--- a/src/star-context.cpp
+++ b/src/star-context.cpp
@@ -225,9 +225,9 @@ sp_star_context_set (SPEventContext *ec, Inkscape::Preferences::Entry *val)
Glib::ustring path = val->getEntryName();
if (path == "magnitude") {
- sc->magnitude = NR_CLAMP(val->getInt(5), 3, 1024);
+ sc->magnitude = CLAMP(val->getInt(5), 3, 1024);
} else if (path == "proportion") {
- sc->proportion = NR_CLAMP(val->getDouble(0.5), 0.01, 2.0);
+ sc->proportion = CLAMP(val->getDouble(0.5), 0.01, 2.0);
} else if (path == "isflatsided") {
sc->isflatsided = val->getBool();
} else if (path == "rounded") {
@@ -446,7 +446,7 @@ static void sp_star_drag(SPStarContext *sc, Geom::Point p, guint state)
/* Snap corner point with no constraints */
SnapManager &m = desktop->namedview->snap_manager;
m.setup(desktop, true, sc->item);
- Geom::Point pt2g = to_2geom(p);
+ Geom::Point pt2g = p;
m.freeSnapReturnByRef(pt2g, Inkscape::SNAPSOURCE_NODE_HANDLE);
m.unSetup();
Geom::Point const p0 = desktop->dt2doc(sc->center);
diff --git a/src/star-context.h b/src/star-context.h
index d9ab8ce8f..7bcb26c41 100644
--- a/src/star-context.h
+++ b/src/star-context.h
@@ -16,8 +16,8 @@
#include <stddef.h>
#include <sigc++/sigc++.h>
+#include <2geom/point.h>
#include "event-context.h"
-#include "libnr/nr-point.h"
#define SP_TYPE_STAR_CONTEXT (sp_star_context_get_type ())
#define SP_STAR_CONTEXT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_STAR_CONTEXT, SPStarContext))
diff --git a/src/style.cpp b/src/style.cpp
index 303b347c4..44d2b0761 100644
--- a/src/style.cpp
+++ b/src/style.cpp
@@ -43,7 +43,6 @@
#include "xml/repr.h"
#include "xml/simple-document.h"
#include "unit-constants.h"
-#include "2geom/isnan.h"
#include "macros.h"
#include "preferences.h"
@@ -337,6 +336,12 @@ static SPStyleEnum const enum_enable_background[] = {
{NULL, -1}
};
+static SPStyleEnum const enum_clip_rule[] = {
+ {"nonzero", SP_WIND_RULE_NONZERO},
+ {"evenodd", SP_WIND_RULE_EVENODD},
+ {NULL, -1}
+};
+
/**
* Release callback.
*/
@@ -769,6 +774,9 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr)
SPS_READ_PENUM_IF_UNSET(&style->enable_background, repr,
"enable-background", enum_enable_background, true);
+ /* clip-rule */
+ SPS_READ_PENUM_IF_UNSET(&style->clip_rule, repr, "clip-rule", enum_clip_rule, true);
+
/* 3. Merge from parent */
if (object) {
if (object->parent) {
@@ -1151,7 +1159,9 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val)
style->object->getRepr()->setAttribute("clip-path", val);
break;
case SP_PROP_CLIP_RULE:
- g_warning("Unimplemented style property SP_PROP_CLIP_RULE: value: %s", val);
+ if (!style->clip_rule.set) {
+ sp_style_read_ienum(&style->clip_rule, val, enum_clip_rule, true);
+ }
break;
case SP_PROP_MASK:
/** \todo
@@ -1790,6 +1800,11 @@ sp_style_merge_from_parent(SPStyle *const style, SPStyle const *const parent)
if(style->enable_background.inherit) {
style->enable_background.value = parent->enable_background.value;
}
+
+ /* Clipping */
+ if (!style->clip_rule.set || style->clip_rule.inherit) {
+ style->clip_rule.computed = parent->clip_rule.computed;
+ }
}
template <typename T>
@@ -2079,7 +2094,7 @@ sp_style_merge_from_dying_parent(SPStyle *const style, SPStyle const *const pare
/* Enum values that don't have any relative settings (other than `inherit'). */
{
SPIEnum SPStyle::*const fields[] = {
- //nyi: SPStyle::clip_rule,
+ &SPStyle::clip_rule,
//nyi: SPStyle::color_interpolation,
//nyi: SPStyle::color_interpolation_filters,
//nyi: SPStyle::color_rendering,
@@ -2619,6 +2634,9 @@ sp_style_write_string(SPStyle const *const style, guint const flags)
p += sp_style_write_ienum(p, c + BMAX - p, "enable-background", enum_enable_background, &style->enable_background, NULL, flags);
+ /* clipping */
+ p += sp_style_write_ienum(p, c + BMAX - p, "clip-rule", enum_clip_rule, &style->clip_rule, NULL, flags);
+
/* fixme: */
p += sp_text_style_write(p, c + BMAX - p, style->text, flags);
@@ -2765,6 +2783,8 @@ sp_style_write_difference(SPStyle const *const from, SPStyle const *const to)
p += sp_text_style_write(p, c + BMAX - p, from->text, SP_STYLE_FLAG_IFDIFF);
+ p += sp_style_write_ienum(p, c + BMAX - p, "clip-rule", enum_clip_rule, &from->clip_rule, &to->clip_rule, SP_STYLE_FLAG_IFDIFF);
+
/** \todo
* The reason we use IFSET rather than IFDIFF is the belief that the IFDIFF
* flag is mainly only for attributes that don't handle explicit unset well.
@@ -2956,6 +2976,8 @@ sp_style_clear(SPStyle *style)
style->enable_background.value = SP_CSS_BACKGROUND_ACCUMULATE;
style->enable_background.set = false;
style->enable_background.inherit = false;
+
+ style->clip_rule.value = style->clip_rule.computed = SP_WIND_RULE_NONZERO;
}
@@ -4328,6 +4350,9 @@ sp_style_unset_property_attrs(SPObject *o)
if (style->enable_background.set) {
repr->setAttribute("enable-background", NULL);
}
+ if (style->clip_rule.set) {
+ repr->setAttribute("clip-rule", NULL);
+ }
}
/**
diff --git a/src/style.h b/src/style.h
index d82a0dd5e..b8b3d6c0d 100644
--- a/src/style.h
+++ b/src/style.h
@@ -330,9 +330,11 @@ struct SPStyle {
unsigned cursor_set : 1;
unsigned overflow_set : 1;
unsigned clip_path_set : 1;
- unsigned clip_rule_set : 1;
unsigned mask_set : 1;
+ /** clip-rule: 0 nonzero, 1 evenodd */
+ SPIEnum clip_rule;
+
/** display */
SPIEnum display;
diff --git a/src/svg-view.cpp b/src/svg-view.cpp
index 5deff7421..03056de2e 100644
--- a/src/svg-view.cpp
+++ b/src/svg-view.cpp
@@ -13,6 +13,7 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <2geom/transforms.h>
#include "display/canvas-arena.h"
#include "document.h"
#include "sp-item.h"
diff --git a/src/tweak-context.cpp b/src/tweak-context.cpp
index b4f13d16f..974197786 100644
--- a/src/tweak-context.cpp
+++ b/src/tweak-context.cpp
@@ -63,7 +63,6 @@
#include "display/canvas-arena.h"
#include "display/curve.h"
#include "livarot/Shape.h"
-#include <2geom/isnan.h>
#include <2geom/transforms.h>
#include "preferences.h"
#include "style.h"
diff --git a/src/tweak-context.h b/src/tweak-context.h
index f7f1fcf7d..cb1cf301b 100644
--- a/src/tweak-context.h
+++ b/src/tweak-context.h
@@ -13,7 +13,7 @@
*/
#include "event-context.h"
-#include <libnr/nr-point.h>
+#include <2geom/point.h>
#define SP_TYPE_TWEAK_CONTEXT (sp_tweak_context_get_type())
#define SP_TWEAK_CONTEXT(o) (G_TYPE_CHECK_INSTANCE_CAST((o), SP_TYPE_TWEAK_CONTEXT, SPTweakContext))
diff --git a/src/ui/cache/svg_preview_cache.cpp b/src/ui/cache/svg_preview_cache.cpp
index edd7c9431..cd1d65ba7 100644
--- a/src/ui/cache/svg_preview_cache.cpp
+++ b/src/ui/cache/svg_preview_cache.cpp
@@ -21,6 +21,7 @@
#include <glib/gmem.h>
#include <gtk/gtk.h>
+#include <2geom/transforms.h>
#include "sp-namedview.h"
#include "selection.h"
#include "inkscape.h"
diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp
index a2169c0b3..f7cb06263 100644
--- a/src/ui/dialog/align-and-distribute.cpp
+++ b/src/ui/dialog/align-and-distribute.cpp
@@ -20,8 +20,8 @@
# include <config.h>
#endif
+#include <2geom/transforms.h>
#include "ui/widget/spinbutton.h"
-
#include "desktop-handles.h"
#include "unclump.h"
#include "document.h"
@@ -357,7 +357,7 @@ private :
it < sorted.end();
it ++ )
{
- if (!NR_DF_TEST_CLOSE (pos, it->bbox.min()[_orientation], 1e-6)) {
+ if (!Geom::are_near(pos, it->bbox.min()[_orientation], 1e-6)) {
Geom::Point t(0.0, 0.0);
t[_orientation] = pos - it->bbox.min()[_orientation];
sp_item_move_rel(it->item, Geom::Translate(t));
@@ -380,7 +380,7 @@ private :
//new anchor position
float pos = sorted.front().anchor + i * step;
//Don't move if we are really close
- if (!NR_DF_TEST_CLOSE (pos, it.anchor, 1e-6)) {
+ if (!Geom::are_near(pos, it.anchor, 1e-6)) {
//Compute translation
Geom::Point t(0.0, 0.0);
t[_orientation] = pos - it.anchor;
diff --git a/src/ui/dialog/align-and-distribute.h b/src/ui/dialog/align-and-distribute.h
index 7c99d67c7..99b96463c 100644
--- a/src/ui/dialog/align-and-distribute.h
+++ b/src/ui/dialog/align-and-distribute.h
@@ -25,7 +25,6 @@
#include <gtkmm/table.h>
#include <gtkmm/buttonbox.h>
#include <gtkmm/label.h>
-#include "libnr/nr-dim2.h"
#include "libnr/nr-rect.h"
diff --git a/src/ui/dialog/tile.cpp b/src/ui/dialog/tile.cpp
index ae17214bf..7c7413ce5 100644
--- a/src/ui/dialog/tile.cpp
+++ b/src/ui/dialog/tile.cpp
@@ -21,6 +21,7 @@
#include <gtk/gtk.h> //for GTK_RESPONSE* types
#include <glibmm/i18n.h>
#include <gtkmm/stock.h>
+#include <2geom/transforms.h>
#include "verbs.h"
#include "preferences.h"
diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp
index 901d02240..92c8bd349 100644
--- a/src/ui/dialog/transformation.cpp
+++ b/src/ui/dialog/transformation.cpp
@@ -16,6 +16,7 @@
#include <gtkmm/stock.h>
#include <gtkmm/dialog.h>
+#include <2geom/transforms.h>
#include "document.h"
#include "desktop-handles.h"
diff --git a/src/ui/view/edit-widget-interface.h b/src/ui/view/edit-widget-interface.h
index 4ff4f92f9..577beb5ce 100644
--- a/src/ui/view/edit-widget-interface.h
+++ b/src/ui/view/edit-widget-interface.h
@@ -16,9 +16,9 @@
#ifndef INKSCAPE_UI_VIEW_EDIT_WIDGET_IFACE_H
#define INKSCAPE_UI_VIEW_EDIT_WIDGET_IFACE_H
-#include "libnr/nr-point.h"
#include "message.h"
#include <gtkmm/window.h>
+#include <2geom/point.h>
namespace Inkscape { namespace UI { namespace Widget { class Dock; } } }
diff --git a/src/ui/view/view.cpp b/src/ui/view/view.cpp
index f05e024d1..dc6307ab0 100644
--- a/src/ui/view/view.cpp
+++ b/src/ui/view/view.cpp
@@ -16,7 +16,7 @@
# include "config.h"
#endif
-#include "libnr/nr-point.h"
+#include <2geom/point.h>
#include "document.h"
#include "view.h"
#include "message-stack.h"
diff --git a/src/ui/widget/page-sizer.cpp b/src/ui/widget/page-sizer.cpp
index 5d71a4b38..f7759f103 100644
--- a/src/ui/widget/page-sizer.cpp
+++ b/src/ui/widget/page-sizer.cpp
@@ -24,6 +24,7 @@
#include <string>
#include <string.h>
#include <vector>
+#include <2geom/transforms.h>
#include "desktop-handles.h"
#include "document.h"
diff --git a/src/ui/widget/rotateable.cpp b/src/ui/widget/rotateable.cpp
index 396280aee..23d5363ef 100644
--- a/src/ui/widget/rotateable.cpp
+++ b/src/ui/widget/rotateable.cpp
@@ -9,13 +9,12 @@
* Released under GNU GPL. Read the file 'COPYING' for more information.
*/
-#include "event-context.h"
-#include "rotateable.h"
-#include "libnr/nr-point.h"
-#include "libnr/nr-point-fns.h"
#include <gtkmm/box.h>
#include <gtkmm/eventbox.h>
#include <glibmm/i18n.h>
+#include <2geom/point.h>
+#include "event-context.h"
+#include "rotateable.h"
namespace Inkscape {
namespace UI {
diff --git a/src/ui/widget/ruler.h b/src/ui/widget/ruler.h
index c315418d8..afe3a4ba7 100644
--- a/src/ui/widget/ruler.h
+++ b/src/ui/widget/ruler.h
@@ -13,7 +13,7 @@
*/
#include <gtkmm/eventbox.h>
-#include "libnr/nr-point.h"
+#include <2geom/point.h>
struct SPCanvasItem;
struct SPDesktop;
diff --git a/src/unclump.cpp b/src/unclump.cpp
index d027a6986..baeeaff76 100644
--- a/src/unclump.cpp
+++ b/src/unclump.cpp
@@ -12,6 +12,7 @@
#include <algorithm>
#include <map>
+#include <2geom/transforms.h>
#include "sp-item.h"
diff --git a/src/widgets/dash-selector.cpp b/src/widgets/dash-selector.cpp
index dead653de..3339c64d3 100644
--- a/src/widgets/dash-selector.cpp
+++ b/src/widgets/dash-selector.cpp
@@ -22,9 +22,9 @@
#include <cstring>
#include <string>
-#include <libnr/nr-macros.h>
#include <gtk/gtk.h>
#include <glibmm/i18n.h>
+#include <2geom/coord.h>
#include "style.h"
#include "dialogs/dialog-events.h"
@@ -144,7 +144,7 @@ SPDashSelector::set_dash (int ndash, double *dash, double o)
if (np == ndash) {
int j;
for (j = 0; j < ndash; j++) {
- if (!NR_DF_TEST_CLOSE (dash[j], pattern[j], delta))
+ if (!Geom::are_near(dash[j], pattern[j], delta))
break;
}
if (j == ndash) {
diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp
index 34c3ab75a..970a094a9 100644
--- a/src/widgets/desktop-widget.cpp
+++ b/src/widgets/desktop-widget.cpp
@@ -24,8 +24,9 @@
# include "config.h"
#endif
-#include <gtkmm/paned.h>
#include <gtk/gtk.h>
+#include <gtkmm.h>
+#include <2geom/rect.h>
#include "box3d-context.h"
#include "cms-system.h"
@@ -543,10 +544,8 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw )
Glib::ustring id = Inkscape::CMSSystem::getDisplayId( 0, 0 );
bool enabled = false;
- if ( dtw->canvas->cms_key ) {
- *(dtw->canvas->cms_key) = id;
- enabled = !dtw->canvas->cms_key->empty();
- }
+ dtw->canvas->cms_key = id;
+ enabled = !dtw->canvas->cms_key.empty();
cms_adjust_set_sensitive( dtw, enabled );
}
#endif // ENABLE_LCMS
@@ -807,11 +806,9 @@ void sp_dtw_color_profile_event(EgeColorProfTracker */*tracker*/, SPDesktopWidge
gint monitor = gdk_screen_get_monitor_at_window(screen, gtk_widget_get_toplevel(GTK_WIDGET(dtw))->window);
Glib::ustring id = Inkscape::CMSSystem::getDisplayId( screenNum, monitor );
bool enabled = false;
- if ( dtw->canvas->cms_key ) {
- *(dtw->canvas->cms_key) = id;
- dtw->requestCanvasUpdate();
- enabled = !dtw->canvas->cms_key->empty();
- }
+ dtw->canvas->cms_key = id;
+ dtw->requestCanvasUpdate();
+ enabled = !dtw->canvas->cms_key.empty();
cms_adjust_set_sensitive( dtw, enabled );
#endif // ENABLE_LCMS
}
@@ -1161,7 +1158,7 @@ bool SPDesktopWidget::showInfoDialog( Glib::ustring const &message )
GTK_BUTTONS_OK,
"%s", message.c_str());
gtk_window_set_title( GTK_WINDOW(dialog), _("Note:")); // probably want to take this as a parameter.
- gint response = gtk_dialog_run(GTK_DIALOG(dialog));
+ gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
}
return result;
@@ -1522,7 +1519,7 @@ sp_desktop_widget_update_hruler (SPDesktopWidget *dtw)
* the latter is used for drawing e.g. the grids and guides. Only when the viewbox
* coincides with the pixel buffer, everything will line up nicely.
*/
- NR::IRect viewbox = dtw->canvas->getViewboxIntegers();
+ Geom::IntRect viewbox = dtw->canvas->getViewboxIntegers();
double const scale = dtw->desktop->current_zoom();
double s = viewbox.min()[Geom::X] / scale - dtw->ruler_origin[Geom::X];
@@ -1538,7 +1535,7 @@ sp_desktop_widget_update_vruler (SPDesktopWidget *dtw)
* the latter is used for drawing e.g. the grids and guides. Only when the viewbox
* coincides with the pixel buffer, everything will line up nicely.
*/
- NR::IRect viewbox = dtw->canvas->getViewboxIntegers();
+ Geom::IntRect viewbox = dtw->canvas->getViewboxIntegers();
double const scale = dtw->desktop->current_zoom();
double s = viewbox.min()[Geom::Y] / -scale - dtw->ruler_origin[Geom::Y];
@@ -1887,7 +1884,7 @@ sp_desktop_widget_update_scrollbars (SPDesktopWidget *dtw, double scale)
Geom::Rect darea ( Geom::Point(-doc->getWidth(), -doc->getHeight()),
Geom::Point(2 * doc->getWidth(), 2 * doc->getHeight()) );
- Geom::OptRect deskarea = Geom::unify(darea, doc->getRoot()->getBboxDesktop());
+ Geom::OptRect deskarea = darea | doc->getRoot()->getBboxDesktop();
/* Canvas region we always show unconditionally */
Geom::Rect carea( Geom::Point(deskarea->min()[Geom::X] * scale - 64, deskarea->max()[Geom::Y] * -scale - 64),
diff --git a/src/widgets/desktop-widget.h b/src/widgets/desktop-widget.h
index 79994a299..742411fb1 100644
--- a/src/widgets/desktop-widget.h
+++ b/src/widgets/desktop-widget.h
@@ -14,7 +14,6 @@
#include <gtk/gtk.h>
-#include "libnr/nr-point.h"
#include "forward.h"
#include "sp-object.h"
#include "message.h"
@@ -23,6 +22,7 @@
#include <stddef.h>
#include <sigc++/connection.h>
+#include <2geom/point.h>
// forward declaration
typedef struct _EgeColorProfTracker EgeColorProfTracker;
diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp
index 450c5f0d9..95cb23a22 100644
--- a/src/widgets/icon.cpp
+++ b/src/widgets/icon.cpp
@@ -23,6 +23,7 @@
#include <gtkmm.h>
#include <gdkmm/pixbuf.h>
#include <glibmm/fileutils.h>
+#include <2geom/transforms.h>
#include "path-prefix.h"
#include "preferences.h"
diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp
index 5d065c3e9..3c1196e96 100644
--- a/src/widgets/toolbox.cpp
+++ b/src/widgets/toolbox.cpp
@@ -6808,11 +6808,11 @@ static void sp_text_align_mode_changed( EgeSelectOneAction *act, GObject *tbl )
unsigned writing_mode = item->style->writing_mode.value;
// below, variable names suggest horizontal move, but we check the writing direction
// and move in the corresponding axis
- int axis;
+ Geom::Dim2 axis;
if (writing_mode == SP_CSS_WRITING_MODE_LR_TB || writing_mode == SP_CSS_WRITING_MODE_RL_TB) {
- axis = NR::X;
+ axis = Geom::X;
} else {
- axis = NR::Y;
+ axis = Geom::Y;
}
Geom::OptRect bbox
@@ -6865,7 +6865,7 @@ static void sp_text_align_mode_changed( EgeSelectOneAction *act, GObject *tbl )
}
}
Geom::Point XY = SP_TEXT(item)->attributes.firstXY();
- if (axis == NR::X) {
+ if (axis == Geom::X) {
XY = XY + Geom::Point (move, 0);
} else {
XY = XY + Geom::Point (0, move);