summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: f9a2694)
raw | patch | inline | side by side (parent: f9a2694)
author | dvlierop2 <dvlierop2@users.sourceforge.net> | |
Sun, 3 Aug 2008 22:31:19 +0000 (22:31 +0000) | ||
committer | dvlierop2 <dvlierop2@users.sourceforge.net> | |
Sun, 3 Aug 2008 22:31:19 +0000 (22:31 +0000) |
index c718eb5155d5a8d3d4de060a170ecdcedbcedb0b..daf208e789787e84d91e31fd2ca2dcf4f1bc0468 100644 (file)
--- a/src/helper/geom-curves.h
+++ b/src/helper/geom-curves.h
#define INKSCAPE_HELPER_GEOM_CURVES_H\r
\r
/**\r
- * Specific curve type functions for Inkscape, not provided my lib2geom.\r
+ * Specific curve type functions for Inkscape, not provided by lib2geom.\r
*\r
* Author:\r
* Johan Engelen <goejendaagh@zonnet.nl>\r
diff --git a/src/libnr/nr-path.cpp b/src/libnr/nr-path.cpp
index 734f3426d639f7d5287be015f4a3286c6c9d421d..5f1437ef9ec987e98d977c47552d0bf0ea2d0904 100644 (file)
--- a/src/libnr/nr-path.cpp
+++ b/src/libnr/nr-path.cpp
}
}
}
-
-NArtBpath *nr_path_from_rect(NRRect const &r)
-{
- NArtBpath *path = g_new (NArtBpath, 6);
-
- path[0].code = NR_MOVETO;
- path[0].setC(3, NR::Point(r.x0, r.y0));
- path[1].code = NR_LINETO;
- path[1].setC(3, NR::Point(r.x1, r.y0));
- path[2].code = NR_LINETO;
- path[2].setC(3, NR::Point(r.x1, r.y1));
- path[3].code = NR_LINETO;
- path[3].setC(3, NR::Point(r.x0, r.y1));
- path[4].code = NR_LINETO;
- path[4].setC(3, NR::Point(r.x0, r.y0));
- path[5].code = NR_END;
-
- return path;
-}
-
diff --git a/src/libnr/nr-path.h b/src/libnr/nr-path.h
index 5e8b0e48e40e9a15daf176643d6548718ea64a91..476e89d0af84e4b3c2b318d499cf7a47b8a890e9 100644 (file)
--- a/src/libnr/nr-path.h
+++ b/src/libnr/nr-path.h
void nr_path_matrix_bbox_union(const_NRBPath *bpath, NR::Matrix const &m, NRRect *bbox);
-NArtBpath *nr_path_from_rect(NRRect const &r);
-
#endif
/*
diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp
index 80319e38c6e758fb91febb0d5436050529982743..5f65e3ff91f26b93e688d17490a5e8a4121b4456 100644 (file)
--- a/src/object-snapper.cpp
+++ b/src/object-snapper.cpp
*/
#include "svg/svg.h"
-#include "libnr/n-art-bpath.h"
#include "libnr/nr-path.h"
#include "libnr/nr-rect-ops.h"
#include "libnr/nr-point-fns.h"
-#include "libnr/n-art-bpath-2geom.h"
#include <2geom/path-intersection.h>
#include <2geom/point.h>
#include <2geom/rect.h>
#include "text-editing.h"
#include "sp-clippath.h"
#include "sp-mask.h"
+#include "helper/geom-curves.h"
Inkscape::SnapCandidate::SnapCandidate(SPItem* item, bool clip_or_mask, NR::Matrix additional_affine)
- : item(item), clip_or_mask(clip_or_mask), additional_affine(additional_affine)
-{
+ : item(item), clip_or_mask(clip_or_mask), additional_affine(additional_affine)
+{
}
Inkscape::SnapCandidate::~SnapCandidate()
-{
+{
}
Inkscape::ObjectSnapper::ObjectSnapper(SPNamedView const *nv, NR::Coord const d)
{
_candidates = new std::vector<SnapCandidate>;
_points_to_snap_to = new std::vector<NR::Point>;
- _bpaths_to_snap_to = new std::vector<NArtBpath*>;
- _paths_to_snap_to = new std::vector<Path*>;
+ _paths_to_snap_to = new std::vector<Geom::PathVector*>;
}
Inkscape::ObjectSnapper::~ObjectSnapper()
_clear_paths();
delete _paths_to_snap_to;
- delete _bpaths_to_snap_to;
}
/**
SPObject *obj = NULL;
if (clip_or_mask) { // If the current item is a clipping path or a mask
// then store the transformation of the clipped path or mask itself
- // but also take into account the additional affine of the object
- // being clipped / masked
- transform = item->transform * additional_affine;
+ // but also take into account the additional affine of the object
+ // being clipped / masked
+ transform = item->transform * additional_affine;
} else { // cannot clip or mask more than once
// The current item is not a clipping path or a mask, but might
- // still be the subject of clipping or masking itself ; if so, then
- // we should also consider that path or mask for snapping to
- obj = SP_OBJECT(item->clip_ref->getObject());
+ // still be the subject of clipping or masking itself ; if so, then
+ // we should also consider that path or mask for snapping to
+ obj = SP_OBJECT(item->clip_ref->getObject());
if (obj) {
_findCandidates(obj, it, false, bbox_to_snap, snap_dim, true, item->transform);
}
} else {
if (clip_or_mask) {
// Oh oh, this will get ugly. We cannot use sp_item_i2d_affine directly because we need to
- // insert an additional transformation in document coordinates (code copied from sp_item_i2d_affine)
- sp_item_invoke_bbox(item,
- &bbox_of_item,
- from_2geom(sp_item_i2doc_affine(item) * matrix_to_desktop(to_2geom(additional_affine), item)),
- true);
-
+ // insert an additional transformation in document coordinates (code copied from sp_item_i2d_affine)
+ sp_item_invoke_bbox(item,
+ &bbox_of_item,
+ from_2geom(sp_item_i2doc_affine(item) * matrix_to_desktop(to_2geom(additional_affine), item)),
+ true);
+
} else {
sp_item_invoke_bbox(item, &bbox_of_item, from_2geom(sp_item_i2d_affine(item)), true);
}
@@ -196,7 +193,7 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::Snapper::PointType const &
// Consider the page border for snapping
if (_snap_to_page_border) {
- _getBorderNodes(_points_to_snap_to);
+ _getBorderNodes(_points_to_snap_to);
}
for (std::vector<SnapCandidate>::const_iterator i = _candidates->begin(); i != _candidates->end(); i++) {
@@ -217,9 +214,9 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::Snapper::PointType const &
//Collect the bounding box's corners so we can snap to them
if (_snap_to_bboxnode) {
if (!(_strict_snapping && !p_is_a_bbox) || p_is_a_guide) {
- // Discard the bbox of a clipped path / mask, because we don't want to snap to both the bbox
- // of the item AND the bbox of the clipping path at the same time
- if (!(*i).clip_or_mask) {
+ // Discard the bbox of a clipped path / mask, because we don't want to snap to both the bbox
+ // of the item AND the bbox of the clipping path at the same time
+ if (!(*i).clip_or_mask) {
NR::Maybe<NR::Rect> b = sp_item_bbox_desktop(root_item, bbox_type);
if (b) {
for ( unsigned k = 0 ; k < 4 ; k++ ) {
}
if (success) {
- sc.points.push_back(s);
+ sc.points.push_back(s);
}
}
@@ -292,9 +289,12 @@ void Inkscape::ObjectSnapper::_snapTranslatingGuideToNodes(SnappedConstraints &s
}
}
+
/**
* Returns index of first NR_END bpath in array.
*/
+
+/* Obsolete
static unsigned sp_bpath_length(NArtBpath const bpath[])
{
g_return_val_if_fail(bpath != NULL, FALSE);
}
++ret;
return ret;
-}
+}*/
void Inkscape::ObjectSnapper::_collectPaths(Inkscape::Snapper::PointType const &t,
bool const &first_point) const
@@ -328,16 +328,10 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::Snapper::PointType const &
// Consider the page border for snapping
if (_snap_to_page_border) {
- NArtBpath const *border_bpath = _getBorderBPath();
- if (border_bpath != NULL) {
- // make our own copy of the const*
- NArtBpath *new_bpath;
- unsigned const len = sp_bpath_length(border_bpath);
- new_bpath = g_new(NArtBpath, len);
- memcpy(new_bpath, border_bpath, len * sizeof(NArtBpath));
-
- _bpaths_to_snap_to->push_back(new_bpath);
- }
+ Geom::PathVector *border_path = _getBorderPathv();
+ if (border_path != NULL) {
+ _paths_to_snap_to->push_back(border_path);
+ }
}
for (std::vector<SnapCandidate>::const_iterator i = _candidates->begin(); i != _candidates->end(); i++) {
@@ -382,20 +376,9 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::Snapper::PointType const &
if (!very_lenghty_prose && !very_complex_path) {
SPCurve *curve = curve_for_item(root_item);
if (curve) {
- NArtBpath *bpath = bpath_for_curve(root_item, curve, true, true,
- NR::identity(),
- (*i).additional_affine);
- // Perhaps for speed, get a reference to the Geom::pathvector, and store the transformation besides it.
- _bpaths_to_snap_to->push_back(bpath); // we will get a dupe of the path, which must be freed at some point
-
- /*std::vector<Geom::Path> pathv;
- char *svgpath = sp_svg_write_path(bpath);
- if (svgpath) {
- std::cout << "path = " << svgpath << std::endl;
- }
- g_free(svgpath);
- */
-
+ // We will get our own copy of the path, which must be freed at some point
+ Geom::PathVector *borderpathv = pathvector_for_curve(root_item, curve, true, true, Geom::identity(), to_2geom((*i).additional_affine));
+ _paths_to_snap_to->push_back(borderpathv); // Perhaps for speed, get a reference to the Geom::pathvector, and store the transformation besides it.
curve->unref();
}
}
@@ -405,13 +388,14 @@ void Inkscape::ObjectSnapper::_collectPaths(Inkscape::Snapper::PointType const &
//Add the item's bounding box to snap to
if (_snap_to_bboxpath) {
if (!(_strict_snapping && p_is_a_node)) {
- // Discard the bbox of a clipped path / mask, because we don't want to snap to both the bbox
- // of the item AND the bbox of the clipping path at the same time
- if (!(*i).clip_or_mask) {
+ // Discard the bbox of a clipped path / mask, because we don't want to snap to both the bbox
+ // of the item AND the bbox of the clipping path at the same time
+ if (!(*i).clip_or_mask) {
NRRect rect;
sp_item_invoke_bbox(root_item, &rect, i2doc, TRUE, bbox_type);
- NArtBpath *bpath = nr_path_from_rect(rect);
- _bpaths_to_snap_to->push_back(bpath);
+ Geom::Rect const rect2 = to_2geom(*rect.upgrade());
+ Geom::PathVector *path = _getPathvFromRect(rect2);
+ _paths_to_snap_to->push_back(path);
}
}
}
{
_collectPaths(t, first_point);
// Now we can finally do the real snapping, using the paths collected above
- SnappedPoint s;
- bool success = false;
/* FIXME: this seems like a hack. Perhaps Snappers should be
** in SPDesktop rather than SPNamedView?
*/
SPDesktop const *desktop = SP_ACTIVE_DESKTOP;
- NR::Point const p_doc = desktop->dt2doc(p);
+ Geom::Point const p_doc = to_2geom(desktop->dt2doc(p));
bool const node_tool_active = _snap_to_itempath && selected_path != NULL;
if (node_tool_active) {
SPCurve *curve = curve_for_item(SP_ITEM(selected_path));
if (curve) {
- NArtBpath *bpath = bpath_for_curve(SP_ITEM(selected_path), curve, true, true, NR::identity(), NR::identity());
- _bpaths_to_snap_to->push_back(bpath); // we will get a dupe of the path, which must be freed at some point
+ Geom::PathVector *pathv = pathvector_for_curve(SP_ITEM(selected_path), curve, true, true, Geom::identity(), Geom::identity()); // We will get our own copy of the path, which must be freed at some point
+ _paths_to_snap_to->push_back(pathv);
curve->unref();
}
- }
- // Convert all bpaths to Paths, because here we really must have Paths
- // (whereas in _snapPathsConstrained we will use the original bpaths)
- for (std::vector<NArtBpath*>::const_iterator k = _bpaths_to_snap_to->begin(); k != _bpaths_to_snap_to->end(); k++) {
- Path *path = bpath_to_Path(*k);
- if (path) {
- path->ConvertWithBackData(0.01); //This is extremely time consuming!
- _paths_to_snap_to->push_back(path);
- }
}
}
- for (std::vector<Path*>::const_iterator k = _paths_to_snap_to->begin(); k != _paths_to_snap_to->end(); k++) {
- if (*k) {
- bool const being_edited = (node_tool_active && (*k) == _paths_to_snap_to->back());
- //if true then this path k is currently being edited in the node tool
-
- for (unsigned i = 1 ; i < (*k)->pts.size() ; i++) {
- //pts describes a polyline approximation, which might consist of 1000s of points!
- NR::Point start_point;
- NR::Point end_point;
- NR::Maybe<Path::cut_position> o = NR::Nothing();
- if (being_edited) {
- /* If the path is being edited, then we will try to snap to each piece of the
- * path individually. We should only snap though to stationary pieces of the paths
+ for (std::vector<Geom::PathVector*>::const_iterator it_p = _paths_to_snap_to->begin(); it_p != _paths_to_snap_to->end(); it_p++) {
+ bool const being_edited = (node_tool_active && (*it_p) == _paths_to_snap_to->back());
+
+ //if true then this pathvector it_pv is currently being edited in the node tool
+ SnappedPoint s;
+ bool success = false;
+
+ // char * svgd = sp_svg_write_path(**it_p);
+ // std::cout << "Dumping the pathvector: " << svgd << std::endl;
+
+ for(Geom::PathVector::iterator it_pv = (*it_p)->begin(); it_pv != (*it_p)->end(); ++it_pv) {
+ std::vector<double> anp = (*it_pv).allNearestPoints(p_doc);
+ for (std::vector<double>::const_iterator np = anp.begin(); np != anp.end(); np++) {
+ bool c1 = true;
+ bool c2 = true;
+ Geom::Point start_pt = desktop->doc2dt((*it_pv).pointAt(floor(*np)));
+ Geom::Point end_pt = desktop->doc2dt((*it_pv).pointAt(ceil(*np)));
+ if (being_edited) {
+ /* If the path is being edited, then we should only snap though to stationary pieces of the path
* and not to the pieces that are being dragged around. This way we avoid
* self-snapping. For this we check whether the nodes at both ends of the current
* piece are unselected; if they are then this piece must be stationary
*/
- unsigned piece = (*k)->pts[i].piece;
- // Example: a cubic spline is a single piece within a path; it will be drawn using
- // a polyline, which is described by the collection of lines between the points pts[i]
- (*k)->PointAt(piece, 0, start_point);
- (*k)->PointAt(piece, 1, end_point);
- start_point = desktop->doc2dt(start_point);
- end_point = desktop->doc2dt(end_point);
g_assert(unselected_nodes != NULL);
- bool c1 = isUnselectedNode(start_point, unselected_nodes);
- bool c2 = isUnselectedNode(end_point, unselected_nodes);
- if (c1 && c2) {
- o = get_nearest_position_on_Path(*k, p_doc, i);
- }
- } else {
- /* If the path is NOT being edited, then we will try to snap to the path as a
- * whole, so we need to do this only once and we will break out at the end of
- * this for-loop iteration */
- /* Look for the nearest position on this SPItem to our snap point */
- o = get_nearest_position_on_Path(*k, p_doc);
- (*k)->PointAt(o->piece, 0, start_point);
- (*k)->PointAt(o->piece, 1, end_point);
- start_point = desktop->doc2dt(start_point);
- end_point = desktop->doc2dt(end_point);
+ c1 = isUnselectedNode(from_2geom(start_pt), unselected_nodes);
+ c2 = isUnselectedNode(from_2geom(end_pt), unselected_nodes);
}
- if (o && o->t >= 0 && o->t <= 1) {
- /* Convert the nearest point back to desktop coordinates */
- NR::Point const o_it = get_point_on_Path(*k, o->piece, o->t);
-
- /* IF YOU'RE BUG HUNTING: IT LOOKS LIKE get_point_on_Path SOMETIMES
- * RETURNS THE WRONG POINT (WITH AN OFFSET, BUT STILL ON THE PATH.
- * THIS BUG WILL NO LONGER BE ENCOUNTERED ONCE WE'VE SWITCHED TO
- * 2GEOM FOR THE OBJECT SNAPPER
- */
-
- NR::Point const o_dt = desktop->doc2dt(o_it);
- NR::Coord const dist = NR::L2(o_dt - p);
+ Geom::Point const sp_doc = (*it_pv).pointAt(*np);
+ Geom::Point const sp_dt = desktop->doc2dt(sp_doc);
+
+ if (!being_edited || (c2 && c2)) {
+ NR::Coord const dist = Geom::distance(sp_doc, p_doc);
if (dist < getSnapperTolerance()) {
- // if we snap to a straight line segment (within a path), then return this line segment
- if ((*k)->IsLineSegment(o->piece)) {
- sc.lines.push_back(Inkscape::SnappedLineSegment(o_dt, dist, getSnapperTolerance(), getSnapperAlwaysSnap(), start_point, end_point));
+ double t = MIN(*np, (*it_pv).size()); // make sure that t is within bounds;
+ //Geom::Curve const & curve = (*it_pv).at_index(int(t));
+ if(is_straight_curve((*it_pv).at_index(int(t)))) {
+ // if we snap to a line segment, then return this line segment (leaves 1 DOF for snapping)
+ sc.lines.push_back(Inkscape::SnappedLineSegment(from_2geom(sp_dt), dist, getSnapperTolerance(), getSnapperAlwaysSnap(), from_2geom(start_pt), from_2geom(end_pt)));
} else {
- // for segments other than straight lines of a path, we'll return just the closest snapped point
+ // for curves other than line segments, we'll return just the closest snapped point
+ // (this is a fully constrained snap, no degrees of freedom left)
if (dist < s.getDistance()) {
- s = SnappedPoint(o_dt, SNAPTARGET_PATH, dist, getSnapperTolerance(), getSnapperAlwaysSnap());
+ // If this curve has multiple segments, then we will return only
+ // a single snapped point
+ s = SnappedPoint(from_2geom(sp_dt), SNAPTARGET_PATH, dist, getSnapperTolerance(), getSnapperAlwaysSnap());
success = true;
}
}
}
- }
-
- // If the path is NOT being edited, then we will try to snap to the path as a whole
- // so we need to do this only once
- if (!being_edited) break;
- }
+ }
+ }
+ } // End of: for (Geom::PathVector::iterator ....)
+
+ // Return a snap point for each path in our collection.
+ // (unless we've already snapped to a line segment, see above)
+ if (success) {
+ sc.points.push_back(s);
}
- }
-
- if (success) {
- sc.points.push_back(s);
- }
+
+ }
}
/* Returns true if point is coincident with one of the unselected nodes */
cl.appendNew<Geom::LineSegment>(p_max_on_cl);
clv.push_back(cl);
- for (std::vector<NArtBpath*>::const_iterator k = _bpaths_to_snap_to->begin(); k != _bpaths_to_snap_to->end(); k++) {
+ for (std::vector<Geom::PathVector*>::const_iterator k = _paths_to_snap_to->begin(); k != _paths_to_snap_to->end(); k++) {
if (*k) {
- // convert a Path object (see src/livarot/Path.h) to a 2geom's path object (see 2geom/path.h)
- // TODO: (Diederik) Only do this once for the first point, needs some storage of pointers in a member variable
- std::vector<Geom::Path> path_2geom = BPath_to_2GeomPath(*k);
-
- Geom::CrossingSet cs = Geom::crossings(clv, path_2geom);
+ Geom::CrossingSet cs = Geom::crossings(clv, *(*k));
if (cs.size() > 0) {
// We need only the first element of cs, because cl is only a single straight linesegment
- // This first element contains a vector filled with crossings of cl with path_2geom
+ // This first element contains a vector filled with crossings of cl with *k
for (std::vector<Geom::Crossing>::const_iterator m = cs[0].begin(); m != cs[0].end(); m++) {
if ((*m).ta >= 0 && (*m).ta <= 1 ) {
// Reconstruct the point of intersection
// (within snapping range == between p_min_on_cl and p_max_on_cl == 0 < ta < 1)
NR::Coord dist = NR::L2(desktop->dt2doc(p_proj_on_cl) - p_inters);
SnappedPoint s(desktop->doc2dt(p_inters), SNAPTARGET_PATH, dist, getSnapperTolerance(), getSnapperAlwaysSnap());
- sc.points.push_back(s);
+ sc.points.push_back(s);
}
}
}
// This method is used to snap a guide to nodes, while dragging the guide around
void Inkscape::ObjectSnapper::guideSnap(SnappedConstraints &sc,
- NR::Point const &p,
- NR::Point const &guide_normal) const
+ NR::Point const &p,
+ NR::Point const &guide_normal) const
{
if ( NULL == _named_view ) {
return;
// line, or can it be located anywhere?)
_findCandidates(sp_document_root(_named_view->document), &it, true, NR::Rect(p, p), snap_dim, false, NR::identity());
- _snapTranslatingGuideToNodes(sc, Inkscape::Snapper::SNAPPOINT_GUIDE, p, guide_normal);
+ _snapTranslatingGuideToNodes(sc, Inkscape::Snapper::SNAPPOINT_GUIDE, p, guide_normal);
// _snapRotatingGuideToNodes has not been implemented yet.
}
void Inkscape::ObjectSnapper::_clear_paths() const
{
- for (std::vector<NArtBpath*>::const_iterator k = _bpaths_to_snap_to->begin(); k != _bpaths_to_snap_to->end(); k++) {
+ for (std::vector<Geom::PathVector*>::const_iterator k = _paths_to_snap_to->begin(); k != _paths_to_snap_to->end(); k++) {
g_free(*k);
}
- _bpaths_to_snap_to->clear();
-
- for (std::vector<Path*>::const_iterator k = _paths_to_snap_to->begin(); k != _paths_to_snap_to->end(); k++) {
- delete *k;
- }
_paths_to_snap_to->clear();
}
-NArtBpath const* Inkscape::ObjectSnapper::_getBorderBPath() const
+Geom::PathVector* Inkscape::ObjectSnapper::_getBorderPathv() const
{
- NArtBpath const *border_bpath = NULL;
Geom::Rect const border_rect = Geom::Rect(Geom::Point(0,0), Geom::Point(sp_document_width(_named_view->document),sp_document_height(_named_view->document)));
- SPCurve const *border_curve = SPCurve::new_from_rect(border_rect);
+ return _getPathvFromRect(border_rect);
+}
+
+Geom::PathVector* Inkscape::ObjectSnapper::_getPathvFromRect(Geom::Rect const rect) const
+{
+ SPCurve const *border_curve = SPCurve::new_from_rect(rect);
if (border_curve) {
- border_bpath = BPath_from_2GeomPath(border_curve->get_pathvector());
- }
-
- return border_bpath;
+ Geom::PathVector *dummy = new Geom::PathVector(border_curve->get_pathvector());
+ return dummy;
+ } else {
+ return NULL;
+ }
}
void Inkscape::ObjectSnapper::_getBorderNodes(std::vector<NR::Point> *points) const
{
- Geom::Coord w = sp_document_width(_named_view->document);
- Geom::Coord h = sp_document_height(_named_view->document);
- points->push_back(from_2geom(Geom::Point(0,0)));
- points->push_back(from_2geom(Geom::Point(0,h)));
- points->push_back(from_2geom(Geom::Point(w,h)));
- points->push_back(from_2geom(Geom::Point(w,0)));
+ Geom::Coord w = sp_document_width(_named_view->document);
+ Geom::Coord h = sp_document_height(_named_view->document);
+ points->push_back(from_2geom(Geom::Point(0,0)));
+ points->push_back(from_2geom(Geom::Point(0,h)));
+ points->push_back(from_2geom(Geom::Point(w,h)));
+ points->push_back(from_2geom(Geom::Point(w,0)));
}
+
/*
Local Variables:
mode:c++
diff --git a/src/object-snapper.h b/src/object-snapper.h
index 7f6221f8b3be3659e2cc0293c4436feb22fd7c58..6034660002c58fd7336d0bb421c41ca8b73a2c87 100644 (file)
--- a/src/object-snapper.h
+++ b/src/object-snapper.h
#include "sp-path.h"
#include "splivarot.h"
-
struct SPNamedView;
struct SPItem;
struct SPObject;
{
class SnapCandidate
-
+
{
public:
- SnapCandidate(SPItem* item, bool clip_or_mask, NR::Matrix _additional_affine);
- ~SnapCandidate();
-
- SPItem* item; // An item that is to be considered for snapping to
- bool clip_or_mask; // If true, then item refers to a clipping path or a mask
-
- /* To find out the absolute position of a clipping path or mask, we not only need to know
- * the transformation of the clipping path or mask itself, but also the transformation of
- * the object to which the clip or mask is being applied; that transformation is stored here
- */
- NR::Matrix additional_affine;
+ SnapCandidate(SPItem* item, bool clip_or_mask, NR::Matrix _additional_affine);
+ ~SnapCandidate();
+
+ SPItem* item; // An item that is to be considered for snapping to
+ bool clip_or_mask; // If true, then item refers to a clipping path or a mask
+
+ /* To find out the absolute position of a clipping path or mask, we not only need to know
+ * the transformation of the clipping path or mask itself, but also the transformation of
+ * the object to which the clip or mask is being applied; that transformation is stored here
+ */
+ NR::Matrix additional_affine;
};
class ObjectSnapper : public Snapper
{
public:
- ObjectSnapper(SPNamedView const *nv, NR::Coord const d);
- ~ObjectSnapper();
+ ObjectSnapper(SPNamedView const *nv, NR::Coord const d);
+ ~ObjectSnapper();
- enum DimensionToSnap {
- GUIDE_TRANSL_SNAP_X, // For snapping a vertical guide (normal in the X-direction) to objects,
- GUIDE_TRANSL_SNAP_Y, // For snapping a horizontal guide (normal in the Y-direction) to objects
- ANGLED_GUIDE_TRANSL_SNAP, // For snapping an angled guide, while translating it accross the desktop
- ANGLED_GUIDE_ROT_SNAP, // For snapping an angled guide, while rotating it around some pivot point
- TRANSL_SNAP_XY}; // All other cases; for snapping to objects, other than guides
+ enum DimensionToSnap {
+ GUIDE_TRANSL_SNAP_X, // For snapping a vertical guide (normal in the X-direction) to objects,
+ GUIDE_TRANSL_SNAP_Y, // For snapping a horizontal guide (normal in the Y-direction) to objects
+ ANGLED_GUIDE_TRANSL_SNAP, // For snapping an angled guide, while translating it accross the desktop
+ ANGLED_GUIDE_ROT_SNAP, // For snapping an angled guide, while rotating it around some pivot point
+ TRANSL_SNAP_XY}; // All other cases; for snapping to objects, other than guides
void setSnapToItemNode(bool s) {_snap_to_itemnode = s;}
- bool getSnapToItemNode() const {return _snap_to_itemnode;}
- void setSnapToItemPath(bool s) {_snap_to_itempath = s;}
- bool getSnapToItemPath() const {return _snap_to_itempath;}
- void setSnapToBBoxNode(bool s) {_snap_to_bboxnode = s;}
- bool getSnapToBBoxNode() const {return _snap_to_bboxnode;}
- void setSnapToBBoxPath(bool s) {_snap_to_bboxpath = s;}
- bool getSnapToBBoxPath() const {return _snap_to_bboxpath;}
- void setSnapToPageBorder(bool s) {_snap_to_page_border = s;}
- bool getSnapToPageBorder() const {return _snap_to_page_border;}
- void setIncludeItemCenter(bool s) {_include_item_center = s;}
- bool getIncludeItemCenter() const {return _include_item_center;}
- void setStrictSnapping(bool enabled) {_strict_snapping = enabled;}
- void guideSnap(SnappedConstraints &sc,
- NR::Point const &p,
+ bool getSnapToItemNode() const {return _snap_to_itemnode;}
+ void setSnapToItemPath(bool s) {_snap_to_itempath = s;}
+ bool getSnapToItemPath() const {return _snap_to_itempath;}
+ void setSnapToBBoxNode(bool s) {_snap_to_bboxnode = s;}
+ bool getSnapToBBoxNode() const {return _snap_to_bboxnode;}
+ void setSnapToBBoxPath(bool s) {_snap_to_bboxpath = s;}
+ bool getSnapToBBoxPath() const {return _snap_to_bboxpath;}
+ void setSnapToPageBorder(bool s) {_snap_to_page_border = s;}
+ bool getSnapToPageBorder() const {return _snap_to_page_border;}
+ void setIncludeItemCenter(bool s) {_include_item_center = s;}
+ bool getIncludeItemCenter() const {return _include_item_center;}
+ void setStrictSnapping(bool enabled) {_strict_snapping = enabled;}
+ void guideSnap(SnappedConstraints &sc,
+ NR::Point const &p,
NR::Point const &guide_normal) const;
- bool ThisSnapperMightSnap() const;
- bool GuidesMightSnap() const;
+ bool ThisSnapperMightSnap() const;
+ bool GuidesMightSnap() const;
- void freeSnap(SnappedConstraints &sc,
+ void freeSnap(SnappedConstraints &sc,
Inkscape::Snapper::PointType const &t,
NR::Point const &p,
bool const &first_point,
std::vector<SPItem const *> const *it,
std::vector<NR::Point> *unselected_nodes) const;
- void constrainedSnap(SnappedConstraints &sc,
+ void constrainedSnap(SnappedConstraints &sc,
Inkscape::Snapper::PointType const &t,
NR::Point const &p,
bool const &first_point,
std::vector<SPItem const *> const *it) const;
private:
- //store some lists of candidates, points and paths, so we don't have to rebuild them for each point we want to snap
- std::vector<SnapCandidate> *_candidates;
- std::vector<NR::Point> *_points_to_snap_to;
- std::vector<NArtBpath*> *_bpaths_to_snap_to;
- std::vector<Path*> *_paths_to_snap_to;
-
- void _findCandidates(SPObject* parent,
+ //store some lists of candidates, points and paths, so we don't have to rebuild them for each point we want to snap
+ std::vector<SnapCandidate> *_candidates;
+ std::vector<NR::Point> *_points_to_snap_to;
+ std::vector<Geom::PathVector*> *_paths_to_snap_to;
+
+ void _findCandidates(SPObject* parent,
std::vector<SPItem const *> const *it,
bool const &first_point,
NR::Rect const &bbox_to_snap,
bool const _clip_or_mask,
NR::Matrix const additional_affine) const;
- void _snapNodes(SnappedConstraints &sc,
+ void _snapNodes(SnappedConstraints &sc,
Inkscape::Snapper::PointType const &t,
NR::Point const &p,
bool const &first_point,
std::vector<NR::Point> *unselected_nodes) const;
- void _snapTranslatingGuideToNodes(SnappedConstraints &sc,
+ void _snapTranslatingGuideToNodes(SnappedConstraints &sc,
Inkscape::Snapper::PointType const &t,
NR::Point const &p,
NR::Point const &guide_normal) const;
- void _collectNodes(Inkscape::Snapper::PointType const &t,
+ void _collectNodes(Inkscape::Snapper::PointType const &t,
bool const &first_point) const;
- void _snapPaths(SnappedConstraints &sc,
+ void _snapPaths(SnappedConstraints &sc,
Inkscape::Snapper::PointType const &t,
NR::Point const &p,
bool const &first_point,
std::vector<NR::Point> *unselected_nodes,
SPPath const *selected_path) const;
- void _snapPathsConstrained(SnappedConstraints &sc,
+ void _snapPathsConstrained(SnappedConstraints &sc,
Inkscape::Snapper::PointType const &t,
NR::Point const &p,
bool const &first_point,
ConstraintLine const &c) const;
- bool isUnselectedNode(NR::Point const &point, std::vector<NR::Point> const *unselected_nodes) const;
+ bool isUnselectedNode(NR::Point const &point, std::vector<NR::Point> const *unselected_nodes) const;
- void _collectPaths(Inkscape::Snapper::PointType const &t,
+ void _collectPaths(Inkscape::Snapper::PointType const &t,
bool const &first_point) const;
- void _clear_paths() const;
- NArtBpath const* _getBorderBPath() const;
- void _getBorderNodes(std::vector<NR::Point> *points) const;
+ void _clear_paths() const;
+ Geom::PathVector* _getBorderPathv() const;
+ Geom::PathVector* _getPathvFromRect(Geom::Rect const rect) const;
+ void _getBorderNodes(std::vector<NR::Point> *points) const;
- bool _snap_to_itemnode;
- bool _snap_to_itempath;
- bool _snap_to_bboxnode;
- bool _snap_to_bboxpath;
- bool _snap_to_page_border;
+ bool _snap_to_itemnode;
+ bool _snap_to_itempath;
+ bool _snap_to_bboxnode;
+ bool _snap_to_bboxpath;
+ bool _snap_to_page_border;
- //If enabled, then bbox corners will only snap to bboxes,
- //and nodes will only snap to nodes and paths. We will not
- //snap bbox corners to nodes, or nodes to bboxes.
- //(snapping to grids and guides is not affected by this)
- bool _strict_snapping;
- bool _include_item_center;
+ //If enabled, then bbox corners will only snap to bboxes,
+ //and nodes will only snap to nodes and paths. We will not
+ //snap bbox corners to nodes, or nodes to bboxes.
+ //(snapping to grids and guides is not affected by this)
+ bool _strict_snapping;
+ bool _include_item_center;
};
}
diff --git a/src/splivarot.cpp b/src/splivarot.cpp
index b8c2bb2f0f891eca1c4d776a7fe4d0b9df30ab3e..11044ec1aa506567606a4564e5bdfbac7294c86c 100644 (file)
--- a/src/splivarot.cpp
+++ b/src/splivarot.cpp
Path_for_item(SPItem *item, bool doTransformation, bool transformFull)
{
SPCurve *curve = curve_for_item(item);
+
if (curve == NULL)
return NULL;
-
- Geom::PathVector pathv = pathvector_for_curve(item, curve, doTransformation, transformFull);
-
- Path *dest = new Path;
- dest->LoadPathVector(pathv);
-
+
+ Geom::PathVector *pathv = pathvector_for_curve(item, curve, doTransformation, transformFull, Geom::identity(), Geom::identity());
curve->unref();
+ Path *dest = new Path;
+ dest->LoadPathVector(*pathv);
+ delete pathv;
+
return dest;
}
-/*
- * This function always returns a new NArtBpath, the caller must g_free the returned path!
-*/
-NArtBpath *
-bpath_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool transformFull, NR::Matrix extraPreAffine, NR::Matrix extraPostAffine)
-{
- if (curve == NULL)
- return NULL;
-
- NArtBpath *bpath = BPath_from_2GeomPath(curve->get_pathvector());
- if (bpath == NULL) {
- return NULL;
- }
-
- NArtBpath *new_bpath; // we will get a duplicate which has to be freed at some point!
- if (doTransformation) {
- if (transformFull) {
- new_bpath = nr_artpath_affine(bpath, extraPreAffine * from_2geom(sp_item_i2doc_affine(item)) * extraPostAffine);
- } else {
- new_bpath = nr_artpath_affine(bpath, extraPreAffine * item->transform * extraPostAffine);
- }
- } else {
- new_bpath = nr_artpath_affine(bpath, extraPreAffine * NR::identity() * extraPostAffine);
- }
-
- g_free(bpath);
- return new_bpath;
-}
-
/*
* NOTE: Returns empty pathvector if curve == NULL
* TODO: see if calling this method can be optimized. All the pathvector copying might be slow.
*/
-Geom::PathVector
-pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool transformFull)
+Geom::PathVector*
+pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool transformFull, Geom::Matrix extraPreAffine, Geom::Matrix extraPostAffine)
{
if (curve == NULL)
- return Geom::PathVector();
+ return NULL;
+ Geom::PathVector *dest = new Geom::PathVector;
+ *dest = curve->get_pathvector(); // Make a copy; must be freed by the caller!
+
if (doTransformation) {
if (transformFull) {
- return (curve->get_pathvector()) * sp_item_i2doc_affine(item);
+ *dest *= extraPreAffine * sp_item_i2doc_affine(item) * extraPostAffine;
} else {
- return (curve->get_pathvector()) * to_2geom(item->transform);
+ *dest *= extraPreAffine * to_2geom(item->transform) * extraPostAffine;
}
} else {
- return curve->get_pathvector();
+ *dest *= extraPreAffine * extraPostAffine;
}
+
+ return dest;
}
SPCurve* curve_for_item(SPItem *item)
{
- if (!item) {
- return NULL;
- }
-
+ if (!item)
+ return NULL;
+
SPCurve *curve = NULL;
if (SP_IS_SHAPE(item)) {
if (SP_IS_PATH(item)) {
- curve = sp_path_get_curve_for_edit(SP_PATH(item));
+ curve = sp_path_get_curve_for_edit(SP_PATH(item));
} else {
curve = sp_shape_get_curve(SP_SHAPE(item));
}
}
else if (SP_IS_IMAGE(item))
{
- curve = sp_image_get_curve(SP_IMAGE(item));
+ curve = sp_image_get_curve(SP_IMAGE(item));
}
return curve; // do not forget to unref the curve at some point!
}
-Path *bpath_to_Path(NArtBpath const *bpath) {
+Path *bpath_to_Path(NArtBpath const *bpath)
+{
Path *dest = new Path;
dest->SetBackData(false);
{
diff --git a/src/splivarot.h b/src/splivarot.h
index eaf2425994ea6142ad0b5baf64cad2dc11bd6539..69e985ffae1a0545645365c73cffc19c5a3f9e19 100644 (file)
--- a/src/splivarot.h
+++ b/src/splivarot.h
void sp_selected_path_simplify ();
Path *Path_for_item(SPItem *item, bool doTransformation, bool transformFull = true);
-NArtBpath *bpath_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool transformFull, NR::Matrix extraPreAffine, NR::Matrix extraPostAffine);
-Geom::PathVector pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool transformFull);
+Geom::PathVector* pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool transformFull, Geom::Matrix extraPreAffine, Geom::Matrix extraPostAffine);
SPCurve *curve_for_item(SPItem *item);
NR::Maybe<Path::cut_position> get_nearest_position_on_Path(Path *path, NR::Point p, unsigned seg = 0);
NR::Point get_point_on_Path(Path *path, int piece, double t);