From f0b327ee9a4de507ac69490aeb805d25b944f6d6 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Wed, 15 Dec 2010 10:58:58 -0800 Subject: Missed a win32 fix. (bzr r9954) --- src/extension/internal/emf-win32-inout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/internal/emf-win32-inout.cpp b/src/extension/internal/emf-win32-inout.cpp index 293e9b7d8..34cdecdca 100644 --- a/src/extension/internal/emf-win32-inout.cpp +++ b/src/extension/internal/emf-win32-inout.cpp @@ -124,7 +124,7 @@ emf_print_document_to_file(SPDocument *doc, gchar const *filename) /* Create new arena */ mod->base = SP_ITEM(doc->getRoot()); mod->arena = NRArena::create(); - mod->dkey = sp_item_display_key_new(1); + mod->dkey = SPItem::display_key_new(1); mod->root = mod->base->invoke_show(mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY); /* Print document */ ret = mod->begin(doc); -- cgit v1.2.3 From 89363253b6fc2e0f1d01136fb91f039599236be2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Thu, 16 Dec 2010 20:27:26 +0100 Subject: Node tool: correctly save node skewing to undo history Fixed bugs: - https://launchpad.net/bugs/590259 (bzr r9956) --- src/ui/tool/multi-path-manipulator.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/ui/tool/multi-path-manipulator.cpp b/src/ui/tool/multi-path-manipulator.cpp index ef1c764bb..5f60f117a 100644 --- a/src/ui/tool/multi-path-manipulator.cpp +++ b/src/ui/tool/multi-path-manipulator.cpp @@ -695,6 +695,14 @@ void MultiPathManipulator::_commit(CommitEvent cps) reason = _("Scale nodes vertically"); key = "node:scale:y"; break; + case COMMIT_MOUSE_SKEW_X: + reason = _("Skew nodes horizontally"); + key = "node:skew:x"; + break; + case COMMIT_MOUSE_SKEW_Y: + reason = _("Skew nodes vertically"); + key = "node:skew:y"; + break; case COMMIT_FLIP_X: reason = _("Flip nodes horizontally"); break; -- cgit v1.2.3 From cb1e5c9cd7b8d9c44f728433d9300e04209d8585 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Thu, 16 Dec 2010 20:28:30 +0100 Subject: Node tool: fix moving multiple nodes along handles (Ctrl+Alt) Fixed bugs: - https://launchpad.net/bugs/642536 (bzr r9957) --- src/ui/tool/control-point-selection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp index 91e0bc2c2..baa53f76e 100644 --- a/src/ui/tool/control-point-selection.cpp +++ b/src/ui/tool/control-point-selection.cpp @@ -290,7 +290,7 @@ void ControlPointSelection::_pointDragged(Geom::Point &new_pos, GdkEventMotion * { Geom::Point abs_delta = new_pos - _original_positions[_grabbed_point]; double fdist = Geom::distance(_original_positions[_grabbed_point], _original_positions[_farthest_point]); - if (held_alt(*event) && fdist > 0) { + if (held_only_alt(*event) && fdist > 0) { // Sculpting for (iterator i = _points.begin(); i != _points.end(); ++i) { SelectableControlPoint *cur = (*i); -- cgit v1.2.3 From 981c5891a7cf64021d724f4b33d133f66427e18c Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Thu, 16 Dec 2010 21:11:16 +0100 Subject: Node tool: fix handle retraction with non-cusp nodes Fixed bugs: - https://launchpad.net/bugs/610817 (bzr r9958) --- src/ui/tool/node.cpp | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index 12d04dd2b..1ea994bb9 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -113,12 +113,29 @@ void Handle::move(Geom::Point const &new_pos) Handle *towards_second = node_towards ? node_towards->handleToward(_parent) : NULL; if (Geom::are_near(new_pos, _parent->position())) { - // The handle becomes degenerate. If the segment between it and the node + // The handle becomes degenerate. + // Adjust node type as necessary. + if (other->isDegenerate()) { + // If both handles become degenerate, convert to parent cusp node + _parent->setType(NODE_CUSP, false); + } else { + // Only 1 handle becomes degenerate + switch (_parent->type()) { + case NODE_AUTO: + case NODE_SYMMETRIC: + _parent->setType(NODE_SMOOTH, false); + break; + default: + // do nothing for other node types + break; + } + } + // If the segment between the handle and the node // in its direction becomes linear and there are smooth nodes // at its ends, make their handles colinear with the segment - if (towards && towards->isDegenerate()) { + if (towards && towards_second->isDegenerate()) { if (node_towards->type() == NODE_SMOOTH) { - towards_second->setDirection(*_parent, *node_towards); + towards->setDirection(*_parent, *node_towards); } if (_parent->type() == NODE_SMOOTH) { other->setDirection(*node_towards, *_parent); @@ -160,6 +177,7 @@ void Handle::move(Geom::Point const &new_pos) void Handle::setPosition(Geom::Point const &p) { + Geom::Point old_pos = position(); ControlPoint::setPosition(p); sp_ctrlline_set_coords(SP_CTRLLINE(_handle_line), _parent->position(), position()); @@ -167,15 +185,12 @@ void Handle::setPosition(Geom::Point const &p) if (Geom::are_near(position(), _parent->position())) _degenerate = true; else _degenerate = false; + if (_parent->_handles_shown && _parent->visible() && !_degenerate) { setVisible(true); } else { setVisible(false); } - // If both handles become degenerate, convert to parent cusp node - if (_parent->isDegenerate()) { - _parent->setType(NODE_CUSP, false); - } } void Handle::setLength(double len) @@ -187,7 +202,7 @@ void Handle::setLength(double len) void Handle::retract() { - setPosition(_parent->position()); + move(_parent->position()); } void Handle::setDirection(Geom::Point const &from, Geom::Point const &to) -- cgit v1.2.3 From d7f88cb16397d88cd5839bd71c1091f3332bec8a Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Thu, 16 Dec 2010 21:56:43 +0100 Subject: Node tool: fix snapping during constrained rotation of handles (bzr r9959) --- src/ui/tool/node.cpp | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index 1ea994bb9..a79a5c409 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -241,6 +241,7 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event) Geom::Point origin = _last_drag_origin(); SnapManager &sm = _desktop->namedview->snap_manager; bool snap = sm.someSnapperMightSnap(); + boost::optional ctrl_constraint; // with Alt, preserve length if (held_alt(*event)) { @@ -256,16 +257,23 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event) // note: if snapping to the original position is only desired in the original // direction of the handle, change to Ray instead of Line Geom::Line original_line(parent_pos, origin); + Geom::Line perp_line(parent_pos, parent_pos + Geom::rot90(origin - parent_pos)); Geom::Point snap_pos = parent_pos + Geom::constrain_angle( Geom::Point(0,0), new_pos - parent_pos, snaps, Geom::Point(1,0)); Geom::Point orig_pos = original_line.pointAt(original_line.nearestPoint(new_pos)); + Geom::Point perp_pos = perp_line.pointAt(perp_line.nearestPoint(new_pos)); - if (Geom::distance(snap_pos, new_pos) < Geom::distance(orig_pos, new_pos)) { - new_pos = snap_pos; - } else { - new_pos = orig_pos; + Geom::Point result = snap_pos; + ctrl_constraint = Inkscape::Snapper::SnapConstraint(parent_pos, parent_pos - snap_pos); + if (Geom::distance(orig_pos, new_pos) < Geom::distance(result, new_pos)) { + result = orig_pos; + ctrl_constraint = Inkscape::Snapper::SnapConstraint(parent_pos, parent_pos - orig_pos); } - snap = false; + if (Geom::distance(perp_pos, new_pos) < Geom::distance(result, new_pos)) { + result = perp_pos; + ctrl_constraint = Inkscape::Snapper::SnapConstraint(parent_pos, parent_pos - perp_pos); + } + new_pos = result; } std::vector unselected; @@ -279,13 +287,20 @@ void Handle::dragged(Geom::Point &new_pos, GdkEventMotion *event) } sm.setupIgnoreSelection(_desktop, true, &unselected); - Node *node_away = (this == &_parent->_front ? _parent->_prev() : _parent->_next()); + Node *node_away = _parent->nodeAwayFrom(this); if (_parent->type() == NODE_SMOOTH && Node::_is_line_segment(_parent, node_away)) { Inkscape::Snapper::SnapConstraint cl(_parent->position(), _parent->position() - node_away->position()); Inkscape::SnappedPoint p; p = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, SNAPSOURCE_NODE_HANDLE), cl); new_pos = p.getPoint(); + } else if (ctrl_constraint) { + // NOTE: this is subtly wrong. + // We should get all possible constraints and snap along them using + // multipleConstrainedSnaps, instead of first snapping to angle and the to objects + Inkscape::SnappedPoint p; + p = sm.constrainedSnap(Inkscape::SnapCandidatePoint(new_pos, SNAPSOURCE_NODE_HANDLE), *ctrl_constraint); + new_pos = p.getPoint(); } else { sm.freeSnapReturnByRef(new_pos, SNAPSOURCE_NODE_HANDLE); } -- cgit v1.2.3 From d18ee1bd701f1e78a42fc4253f7a5c4e7ece714a Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Thu, 16 Dec 2010 23:07:52 +0100 Subject: Node tool: fix snapping of node rotation center Fixed bugs: - https://launchpad.net/bugs/667072 (bzr r9960) --- src/ui/tool/node.cpp | 29 +++++++++++++++++++++++++++++ src/ui/tool/node.h | 1 + src/ui/tool/transform-handle-set.cpp | 20 +++++++++++++++++++- 3 files changed, 49 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index a79a5c409..fea02d399 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -227,6 +227,35 @@ char const *Handle::handle_type_to_localized_string(NodeType type) } } +bool Handle::_eventHandler(GdkEvent *event) +{ + switch (event->type) + { + case GDK_KEY_PRESS: + switch (shortcut_key(event->key)) + { + case GDK_s: + case GDK_S: + if (held_only_shift(event->key) && _parent->_type == NODE_CUSP) { + // when Shift+S is pressed when hovering over a handle belonging to a cusp node, + // hold this handle in place; otherwise process normally + // this handle is guaranteed not to be degenerate + other()->move(_parent->position() - (position() - _parent->position())); + _parent->setType(NODE_SMOOTH, false); + _parent->_pm().update(); // magic triple combo to add undo event + _parent->_pm().writeXML(); + _parent->_pm()._commit(_("Change node type")); + return true; + } + break; + default: break; + } + default: break; + } + + return ControlPoint::_eventHandler(event); +} + bool Handle::grabbed(GdkEventMotion *) { _saved_other_pos = other()->position(); diff --git a/src/ui/tool/node.h b/src/ui/tool/node.h index 0194f5053..b5d4d88f2 100644 --- a/src/ui/tool/node.h +++ b/src/ui/tool/node.h @@ -102,6 +102,7 @@ public: protected: Handle(NodeSharedData const &data, Geom::Point const &initial_pos, Node *parent); + virtual bool _eventHandler(GdkEvent *event); virtual void dragged(Geom::Point &, GdkEventMotion *); virtual bool grabbed(GdkEventMotion *); virtual void ungrabbed(GdkEventButton *); diff --git a/src/ui/tool/transform-handle-set.cpp b/src/ui/tool/transform-handle-set.cpp index ef93a3767..cafd592a3 100644 --- a/src/ui/tool/transform-handle-set.cpp +++ b/src/ui/tool/transform-handle-set.cpp @@ -18,6 +18,8 @@ #include "desktop-handles.h" #include "display/sodipodi-ctrlrect.h" #include "preferences.h" +#include "snap.h" +#include "sp-namedview.h" #include "ui/tool/commit-events.h" #include "ui/tool/control-point.h" #include "ui/tool/event-utils.h" @@ -473,7 +475,23 @@ public: } protected: - + virtual void dragged(Geom::Point &new_pos, GdkEventMotion *event) { + SnapManager &sm = _desktop->namedview->snap_manager; + sm.setup(_desktop); + bool snap = !held_shift(*event) && sm.someSnapperMightSnap(); + if (held_control(*event)) { + // constrain to axes + Geom::Point origin = _last_drag_origin(); + std::vector constraints; + constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, Geom::Point(1, 0))); + constraints.push_back(Inkscape::Snapper::SnapConstraint(origin, Geom::Point(0, 1))); + new_pos = sm.multipleConstrainedSnaps(Inkscape::SnapCandidatePoint(new_pos, + SNAPSOURCE_ROTATION_CENTER), constraints, held_shift(*event)).getPoint(); + } else if (snap) { + sm.freeSnapReturnByRef(new_pos, SNAPSOURCE_ROTATION_CENTER); + } + sm.unSetup(); + } virtual Glib::ustring _getTip(unsigned /*state*/) { return C_("Transform handle tip", "Rotation center: drag to change the origin of transforms"); -- cgit v1.2.3 From 3a38979f6034517961c09e0af5a3028f0d6d7a52 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Fri, 17 Dec 2010 00:01:36 +0100 Subject: Node tool: fix Tab and Shift+Tab (bzr r9961) --- src/ui/tool/multi-path-manipulator.cpp | 73 +++++++++++++++++++++++++++++++++- src/ui/tool/path-manipulator.cpp | 59 +-------------------------- src/ui/tool/path-manipulator.h | 4 +- 3 files changed, 76 insertions(+), 60 deletions(-) (limited to 'src') diff --git a/src/ui/tool/multi-path-manipulator.cpp b/src/ui/tool/multi-path-manipulator.cpp index 5f60f117a..082ac194b 100644 --- a/src/ui/tool/multi-path-manipulator.cpp +++ b/src/ui/tool/multi-path-manipulator.cpp @@ -210,7 +210,78 @@ void MultiPathManipulator::selectSubpaths() void MultiPathManipulator::shiftSelection(int dir) { - invokeForAll(&PathManipulator::shiftSelection, dir); + if (empty()) return; + + // 1. find last selected node + // 2. select the next node; if the last node or nothing is selected, + // select first node + MapType::iterator last_i; + SubpathList::iterator last_j; + NodeList::iterator last_k; + bool anything_found = false; + + for (MapType::iterator i = _mmap.begin(); i != _mmap.end(); ++i) { + SubpathList &sp = i->second->subpathList(); + for (SubpathList::iterator j = sp.begin(); j != sp.end(); ++j) { + for (NodeList::iterator k = (*j)->begin(); k != (*j)->end(); ++k) { + if (k->selected()) { + last_i = i; + last_j = j; + last_k = k; + anything_found = true; + // when tabbing backwards, we want the first node + if (dir == -1) goto exit_loop; + } + } + } + } + exit_loop: + + // NOTE: we should not assume the _selection contains only nodes + // in future it might also contain handles and other types of control points + // this is why we use a flag instead in the loop above, instead of calling + // selection.empty() + if (!anything_found) { + // select first / last node + // this should never fail because there must be at least 1 non-empty manipulator + if (dir == 1) { + _selection.insert((*_mmap.begin()->second->subpathList().begin())->begin().ptr()); + } else { + _selection.insert((--(*--(--_mmap.end())->second->subpathList().end())->end()).ptr()); + } + return; + } + + // three levels deep - w00t! + if (dir == 1) { + if (++last_k == (*last_j)->end()) { + // here, last_k points to the node to be selected + ++last_j; + if (last_j == last_i->second->subpathList().end()) { + ++last_i; + if (last_i == _mmap.end()) { + last_i = _mmap.begin(); + } + last_j = last_i->second->subpathList().begin(); + } + last_k = (*last_j)->begin(); + } + } else { + if (!last_k || last_k == (*last_j)->begin()) { + if (last_j == last_i->second->subpathList().begin()) { + if (last_i == _mmap.begin()) { + last_i = _mmap.end(); + } + --last_i; + last_j = last_i->second->subpathList().end(); + } + --last_j; + last_k = (*last_j)->end(); + } + --last_k; + } + _selection.clear(); + _selection.insert(last_k.ptr()); } void MultiPathManipulator::invertSelectionInSubpaths() diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index 5ae9c4137..7c60efbab 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -215,7 +215,7 @@ void PathManipulator::clear() /** Select all nodes in subpaths that have something selected. */ void PathManipulator::selectSubpaths() { - for (std::list::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) { + for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) { NodeList::iterator sp_start = (*i)->begin(), sp_end = (*i)->end(); for (NodeList::iterator j = sp_start; j != sp_end; ++j) { if (j->selected()) { @@ -229,63 +229,6 @@ void PathManipulator::selectSubpaths() } } -/** Move the selection forward or backward by one node in each subpath, based on the sign - * of the parameter. */ -void PathManipulator::shiftSelection(int dir) -{ - if (dir == 0) return; - if (_num_selected == 0) { - // select the first node of the path. - SubpathList::iterator s = _subpaths.begin(); - if (s == _subpaths.end()) return; - NodeList::iterator n = (*s)->begin(); - if (n != (*s)->end()) - _selection.insert(n.ptr()); - return; - } - // We cannot do any tricks here, like iterating in different directions based on - // the sign and only setting the selection of nodes behind us, because it would break - // for closed paths. - for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) { - std::deque sels; // I hope this is specialized for bools! - unsigned num = 0; - - for (NodeList::iterator j = (*i)->begin(); j != (*i)->end(); ++j) { - sels.push_back(j->selected()); - _selection.erase(j.ptr()); - ++num; - } - if (num == 0) continue; // should never happen! zero-node subpaths are not allowed - - num = 0; - // In closed subpath, shift the selection cyclically. In an open one, - // let the selection 'slide into nothing' at ends. - if (dir > 0) { - if ((*i)->closed()) { - bool last = sels.back(); - sels.pop_back(); - sels.push_front(last); - } else { - sels.push_front(false); - } - } else { - if ((*i)->closed()) { - bool first = sels.front(); - sels.pop_front(); - sels.push_back(first); - } else { - sels.push_back(false); - num = 1; - } - } - - for (NodeList::iterator j = (*i)->begin(); j != (*i)->end(); ++j) { - if (sels[num]) _selection.insert(j.ptr()); - ++num; - } - } -} - /** Invert selection in the selected subpaths. */ void PathManipulator::invertSelectionInSubpaths() { diff --git a/src/ui/tool/path-manipulator.h b/src/ui/tool/path-manipulator.h index 87b88fc77..8a0167e59 100644 --- a/src/ui/tool/path-manipulator.h +++ b/src/ui/tool/path-manipulator.h @@ -65,7 +65,6 @@ public: SPPath *item() { return _path; } void selectSubpaths(); - void shiftSelection(int dir); void invertSelectionInSubpaths(); void insertNodes(); @@ -94,6 +93,9 @@ public: NodeList::iterator extremeNode(NodeList::iterator origin, bool search_selected, bool search_unselected, bool closest); + // this is necessary for Tab-selection in MultiPathManipulator + SubpathList &subpathList() { return _subpaths; } + static bool is_item_type(void *item); private: typedef NodeList Subpath; -- cgit v1.2.3 From 69059080428adb8b6258a6d5de15f0028c4444f8 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Fri, 17 Dec 2010 00:16:33 +0100 Subject: Node tool: special case node duplication for endnodes - select new endnode (bzr r9962) --- src/ui/tool/path-manipulator.cpp | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index 7c60efbab..ea7f3412d 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -275,22 +275,31 @@ void PathManipulator::duplicateNodes() NodeList::iterator k = j.next(); Node *n = new Node(_multi_path_manipulator._path_data.node_data, *j); - // Move the new node to the bottom of the Z-order. This way you can drag all - // nodes that were selected before this operation without deselecting - // everything because there is a new node above. - n->sink(); + if (k) { + // Move the new node to the bottom of the Z-order. This way you can drag all + // nodes that were selected before this operation without deselecting + // everything because there is a new node above. + n->sink(); + } n->front()->setPosition(*j->front()); j->front()->retract(); j->setType(NODE_CUSP, false); (*i)->insert(k, n); - // We need to manually call the selection change callback to refresh - // the handle display correctly. - // This call changes num_selected, but we call this once for a selected node - // and once for an unselected node, so in the end the number stays correct. - _selectionChanged(j.ptr(), true); - _selectionChanged(n, false); + if (k) { + // We need to manually call the selection change callback to refresh + // the handle display correctly. + // This call changes num_selected, but we call this once for a selected node + // and once for an unselected node, so in the end the number stays correct. + _selectionChanged(j.ptr(), true); + _selectionChanged(n, false); + } else { + // select the new end node instead of the node just before it + _selection.erase(j.ptr()); + _selection.insert(n); + break; // this was the end node, nothing more to do + } } } } -- cgit v1.2.3 From 5982a91e8e0aea5871c36350b888693340e54c9d Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Thu, 16 Dec 2010 20:12:30 -0800 Subject: Simple first pass for rough timing (bzr r9955.1.1) --- src/verbs.cpp | 2 +- src/widgets/desktop-widget.cpp | 49 +++++++++++++++++++++++++++ src/widgets/icon.cpp | 76 +++++++++++++++++++++++++++++++----------- 3 files changed, 106 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/verbs.cpp b/src/verbs.cpp index a218e85db..c1726ecd4 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -2314,7 +2314,7 @@ Verb *Verb::_base_verbs[] = { new EditVerb(SP_VERB_EDIT_CLEAR_ALL, "EditClearAll", N_("Clea_r All"), N_("Delete all objects from document"), NULL), new EditVerb(SP_VERB_EDIT_SELECT_ALL, "EditSelectAll", N_("Select Al_l"), - N_("Select all objects or all nodes"), GTK_STOCK_SELECT_ALL), + N_("Select all objects or all nodes"), "fooble"),//GTK_STOCK_SELECT_ALL), new EditVerb(SP_VERB_EDIT_SELECT_ALL_IN_ALL_LAYERS, "EditSelectAllInAllLayers", N_("Select All in All La_yers"), N_("Select all objects in all visible and unlocked layers"), INKSCAPE_ICON_EDIT_SELECT_ALL_LAYERS), new EditVerb(SP_VERB_EDIT_INVERT, "EditInvert", N_("In_vert Selection"), diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 7a3e337de..57e58cd5e 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -121,6 +121,30 @@ static void sp_dtw_sticky_zoom_toggled (GtkMenuItem *item, gpointer data); SPViewWidgetClass *dtw_parent_class; +static GTimer *baseTimer = 0; +static bool timeReported = false; + +static void timeGoing(gchar const* id) +{ + if ( !baseTimer ) { + g_message("Starting time at point [%s]", id); + baseTimer = g_timer_new(); + } +} + +static void checkTime(gchar const* msg) +{ + if ( baseTimer && !timeReported ) { + timeReported = true; + g_timer_stop(baseTimer); + gulong msCount = 0; + gdouble secs = g_timer_elapsed( baseTimer, &msCount ); + g_message("Time ended at %2.3f with [%s]", secs, msg); + } +} + + + class CMSPrefWatcher { public: CMSPrefWatcher() : @@ -250,6 +274,7 @@ GType SPDesktopWidget::getType(void) { static GtkType type = 0; if (!type) { + timeGoing("SPDesktopWidget::getType"); GTypeInfo info = { sizeof(SPDesktopWidgetClass), 0, // base_init @@ -273,6 +298,7 @@ GType SPDesktopWidget::getType(void) static void sp_desktop_widget_class_init (SPDesktopWidgetClass *klass) { + timeGoing("sp_desktop_widget_class_init"); dtw_parent_class = (SPViewWidgetClass*)gtk_type_class (SP_TYPE_VIEW_WIDGET); GtkObjectClass *object_class = (GtkObjectClass *) klass; @@ -289,6 +315,7 @@ sp_desktop_widget_class_init (SPDesktopWidgetClass *klass) */ void SPDesktopWidget::init( SPDesktopWidget *dtw ) { + timeGoing("SPDesktopWidget::init"); GtkWidget *widget; GtkWidget *tbl; GtkWidget *canvas_tbl; @@ -564,6 +591,28 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) gtk_widget_show_all (dtw->vbox); gtk_widget_grab_focus (GTK_WIDGET(dtw->canvas)); + + { + g_message("FIRE UP"); + + gtk_widget_add_events( eventbox, GDK_STRUCTURE_MASK ); + + gboolean fooMap(GtkWidget *widget, GdkEvent *event, gpointer userData); + g_signal_connect( G_OBJECT(eventbox), "map-event", G_CALLBACK(fooMap), dtw ); + + void fooReal(GtkWidget *widget, gpointer userData); + g_signal_connect( G_OBJECT(eventbox), "map-event", G_CALLBACK(fooReal), dtw ); + } +} + +gboolean fooMap(GtkWidget *widget, GdkEvent *event, gpointer userData) { + checkTime( "MAP"); + return FALSE; +} + +void fooReal(GtkWidget *widget, gpointer userData) +{ + checkTime("REALIZE"); } /** diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index 15900d340..d8d684614 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -20,6 +20,7 @@ #include #include #include +#include #include "path-prefix.h" #include "preferences.h" @@ -542,8 +543,7 @@ static void setupLegacyNaming() { legacyNames["zoom"] ="sticky_zoom"; } -static GtkWidget * -sp_icon_new_full( Inkscape::IconSize lsize, gchar const *name ) +static GtkWidget *sp_icon_new_full( Inkscape::IconSize lsize, gchar const *name ) { static bool dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpGtk"); @@ -1203,6 +1203,7 @@ bool prerender_icon(gchar const *name, GtkIconSize lsize, unsigned psize) { bool loadNeeded = false; static bool dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpGtk"); + static bool useCache = Inkscape::Preferences::get()->getBool("/debug/icons/useCache"); Glib::ustring key = icon_cache_key(name, psize); if ( !get_cached_pixbuf(key) ) { @@ -1211,28 +1212,62 @@ bool prerender_icon(gchar const *name, GtkIconSize lsize, unsigned psize) if (dump) { g_message("prerender_icon [%s] %d:%d", name, lsize, psize); } - guchar* px = load_svg_pixels(name, lsize, psize); - if ( !px ) { - // check for a fallback name - if ( legacyNames.find(name) != legacyNames.end() ) { - if ( dump ) { - g_message("load_svg_pixels([%s]=%s, %d, %d)", name, legacyNames[name].c_str(), lsize, psize); + // In file encoding: + std::string iconCacheDir = Glib::build_filename(Glib::build_filename(Glib::get_user_cache_dir(), "inkscape"), "icons"); + std::string potentialFile = Glib::build_filename( iconCacheDir, name ); + potentialFile += ".png"; + + bool dataLoaded = false; + if ( useCache && Glib::file_test(potentialFile, Glib::FILE_TEST_EXISTS) && Glib::file_test(potentialFile, Glib::FILE_TEST_IS_REGULAR) ) { + Glib::RefPtr pb = Gdk::Pixbuf::create_from_file(potentialFile); + if (pb) { + dataLoaded = true; + GdkPixbuf *obj = pb->gobj(); + g_object_ref(obj); + pb_cache[key] = obj; + addToIconSet(obj, name, lsize, psize); + loadNeeded = true; + if (internalNames.find(name) == internalNames.end()) { + internalNames.insert(name); } - px = load_svg_pixels(legacyNames[name].c_str(), lsize, psize); } } - if (px) { - GdkPixbuf* pb = gdk_pixbuf_new_from_data( px, GDK_COLORSPACE_RGB, TRUE, 8, - psize, psize, psize * 4, - reinterpret_cast(g_free), NULL ); - pb_cache[key] = pb; - addToIconSet(pb, name, lsize, psize); - loadNeeded = true; - if (internalNames.find(name) == internalNames.end()) { - internalNames.insert(name); + + if (!dataLoaded) { + guchar* px = load_svg_pixels(name, lsize, psize); + if ( !px ) { + // check for a fallback name + if ( legacyNames.find(name) != legacyNames.end() ) { + if ( dump ) { + g_message("load_svg_pixels([%s]=%s, %d, %d)", name, legacyNames[name].c_str(), lsize, psize); + } + px = load_svg_pixels(legacyNames[name].c_str(), lsize, psize); + } + } + if (px) { + GdkPixbuf* pb = gdk_pixbuf_new_from_data( px, GDK_COLORSPACE_RGB, TRUE, 8, + psize, psize, psize * 4, + reinterpret_cast(g_free), NULL ); + pb_cache[key] = pb; + addToIconSet(pb, name, lsize, psize); + loadNeeded = true; + if (internalNames.find(name) == internalNames.end()) { + internalNames.insert(name); + } + if (useCache) { + g_object_ref(pb); + Glib::RefPtr ppp = Glib::wrap(pb); + try { + ppp->save( potentialFile, "png" ); + } catch ( Glib::FileError &ex ) { + g_warning("FileError [%s]", ex.what().c_str()); + } catch ( Gdk::PixbufError &ex ) { + g_warning("PixbufError [%s]", ex.what().c_str()); + } + } + } else if (dump) { + g_message("XXXXXXXXXXXXXXXXXXXXXXXXXXXXX error!!! pixels not found for '%s'", name); } - } else if (dump) { - g_message("XXXXXXXXXXXXXXXXXXXXXXXXXXXXX error!!! pixels not found for '%s'", name); } } else if (dump) { @@ -1249,6 +1284,7 @@ static GdkPixbuf *sp_icon_image_load_svg(gchar const *name, GtkIconSize lsize, u // did we already load this icon at this scale/size? GdkPixbuf* pb = get_cached_pixbuf(key); if (!pb) { + g_message("YYYYYYYYYYYYY YYYYYYYYYYYYYYY two load_svg_pixels(%s, %d, %d)", name, lsize, psize); guchar *px = load_svg_pixels(name, lsize, psize); if (px) { pb = gdk_pixbuf_new_from_data(px, GDK_COLORSPACE_RGB, TRUE, 8, -- cgit v1.2.3 From c3051ca878d6120911d9ca6534dfd63ad80cb19d Mon Sep 17 00:00:00 2001 From: Kris De Gussem Date: Fri, 17 Dec 2010 17:06:36 +0100 Subject: Mnemonics in fill and stroke dialog and menu (bzr r9964) --- src/ui/dialog/fill-and-stroke.cpp | 2 +- src/ui/widget/filter-effect-chooser.cpp | 2 +- src/ui/widget/object-composite-settings.cpp | 3 ++- src/verbs.cpp | 2 +- 4 files changed, 5 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/fill-and-stroke.cpp b/src/ui/dialog/fill-and-stroke.cpp index 0c234003e..19bcadc00 100644 --- a/src/ui/dialog/fill-and-stroke.cpp +++ b/src/ui/dialog/fill-and-stroke.cpp @@ -54,7 +54,7 @@ FillAndStroke::FillAndStroke() contents->pack_start(_notebook, true, true); - _notebook.append_page(_page_fill, _createPageTabLabel(_("Fill"), INKSCAPE_ICON_OBJECT_FILL)); + _notebook.append_page(_page_fill, _createPageTabLabel(_("_Fill"), INKSCAPE_ICON_OBJECT_FILL)); _notebook.append_page(_page_stroke_paint, _createPageTabLabel(_("Stroke _paint"), INKSCAPE_ICON_OBJECT_STROKE)); _notebook.append_page(_page_stroke_style, _createPageTabLabel(_("Stroke st_yle"), INKSCAPE_ICON_OBJECT_STROKE_STYLE)); diff --git a/src/ui/widget/filter-effect-chooser.cpp b/src/ui/widget/filter-effect-chooser.cpp index 309730600..aba3a18e8 100644 --- a/src/ui/widget/filter-effect-chooser.cpp +++ b/src/ui/widget/filter-effect-chooser.cpp @@ -23,7 +23,7 @@ namespace Widget { SimpleFilterModifier::SimpleFilterModifier(int flags) : _lb_blend(_("_Blend mode:")), - _lb_blur(_("Blur:"), Gtk::ALIGN_LEFT), + _lb_blur(_("_Blur:"), Gtk::ALIGN_LEFT, Gtk::ALIGN_CENTER, true), _blend(BlendModeConverter, SP_ATTR_INVALID, false), _blur(0, 0, 100, 1, 0.01, 1) { diff --git a/src/ui/widget/object-composite-settings.cpp b/src/ui/widget/object-composite-settings.cpp index 1de425da3..997c2f0dc 100644 --- a/src/ui/widget/object-composite-settings.cpp +++ b/src/ui/widget/object-composite-settings.cpp @@ -60,7 +60,7 @@ ObjectCompositeSettings::ObjectCompositeSettings(unsigned int verb_code, char co _opacity_tag(Glib::ustring(history_prefix) + ":opacity"), _opacity_vbox(false, 0), _opacity_label_box(false, 0), - _opacity_label(_("Opacity (%):"), 0.0, 1.0, true), + _opacity_label(_("_Opacity (%):"), 0.0, 1.0, true), _opacity_adjustment(100.0, 0.0, 100.0, 1.0, 1.0, 0.0), _opacity_hscale(_opacity_adjustment), _opacity_spin_button(_opacity_adjustment, 0.01, 1), @@ -86,6 +86,7 @@ ObjectCompositeSettings::ObjectCompositeSettings(unsigned int verb_code, char co _opacity_hscale.set_draw_value(false); _opacity_hscale.set_update_policy(Gtk::UPDATE_DELAYED); _opacity_adjustment.signal_value_changed().connect(sigc::mem_fun(*this, &ObjectCompositeSettings::_opacityValueChanged)); + _opacity_label.set_mnemonic_widget(_opacity_hscale); show_all_children(); diff --git a/src/verbs.cpp b/src/verbs.cpp index a218e85db..4cdad7d36 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -2437,7 +2437,7 @@ Verb *Verb::_base_verbs[] = { N_("Raise the current layer"), INKSCAPE_ICON_LAYER_RAISE), new LayerVerb(SP_VERB_LAYER_LOWER, "LayerLower", N_("_Lower Layer"), N_("Lower the current layer"), INKSCAPE_ICON_LAYER_LOWER), - new LayerVerb(SP_VERB_LAYER_DUPLICATE, "LayerDuplicate", N_("Duplicate Current Layer"), + new LayerVerb(SP_VERB_LAYER_DUPLICATE, "LayerDuplicate", N_("D_uplicate Current Layer"), N_("Duplicate an existing layer"), NULL), new LayerVerb(SP_VERB_LAYER_DELETE, "LayerDelete", N_("_Delete Current Layer"), N_("Delete the current layer"), INKSCAPE_ICON_LAYER_DELETE), -- cgit v1.2.3 From f827bacbbab8d98adb460dc85279d584fee6435c Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 17 Dec 2010 20:54:08 -0800 Subject: Simple tracking of time to display dialogs and main window. (bzr r9966) --- src/dialogs/text-edit.cpp | 12 +++ src/dialogs/xml-tree.cpp | 13 ++- src/ui/dialog/dialog-manager.cpp | 18 +++- src/util/Makefile_insert | 2 + src/util/ege-appear-time-tracker.cpp | 162 +++++++++++++++++++++++++++++++++++ src/util/ege-appear-time-tracker.h | 89 +++++++++++++++++++ src/widgets/desktop-widget.cpp | 18 ++++ 7 files changed, 311 insertions(+), 3 deletions(-) create mode 100644 src/util/ege-appear-time-tracker.cpp create mode 100644 src/util/ege-appear-time-tracker.h (limited to 'src') diff --git a/src/dialogs/text-edit.cpp b/src/dialogs/text-edit.cpp index 61f56e3f7..d741e2de0 100644 --- a/src/dialogs/text-edit.cpp +++ b/src/dialogs/text-edit.cpp @@ -49,8 +49,10 @@ extern "C" { #include "svg/css-ostringstream.h" #include "widgets/icon.h" #include +#include "util/ege-appear-time-tracker.h" using Inkscape::DocumentUndo; +using ege::AppearTimeTracker; #define VB_MARGIN 4 #define MIN_ONSCREEN_DISTANCE 50 @@ -139,6 +141,9 @@ text_view_focus_out (GtkWidget */*w*/, GdkEventKey */*event*/, gpointer data) void sp_text_edit_dialog (void) { + bool wantTiming = Inkscape::Preferences::get()->getBool("/dialogs/debug/trackAppear", false); + GTimer *timer = wantTiming ? g_timer_new() : 0; + if (!dlg) { gchar title[500]; @@ -457,6 +462,13 @@ sp_text_edit_dialog (void) sp_text_edit_dialog_read_selection (dlg, TRUE, TRUE); } + if ( wantTiming ) { + // Time tracker takes ownership of the timer. + AppearTimeTracker *tracker = new AppearTimeTracker(timer, GTK_WIDGET(dlg), "DialogText"); + tracker->setAutodelete(true); + timer = 0; + } + gtk_window_present ((GtkWindow *) dlg); } // end of sp_text_edit_dialog() diff --git a/src/dialogs/xml-tree.cpp b/src/dialogs/xml-tree.cpp index c90cde490..d25bdad72 100644 --- a/src/dialogs/xml-tree.cpp +++ b/src/dialogs/xml-tree.cpp @@ -41,8 +41,10 @@ #include "../widgets/sp-xmlview-attr-list.h" #include "../widgets/sp-xmlview-content.h" #include "../widgets/sp-xmlview-tree.h" +#include "util/ege-appear-time-tracker.h" using Inkscape::DocumentUndo; +using ege::AppearTimeTracker; #define MIN_ONSCREEN_DISTANCE 50 @@ -178,11 +180,13 @@ void attr_reset_context(gint attr) void sp_xml_tree_dialog() { SPDesktop *desktop = SP_ACTIVE_DESKTOP; - if (!desktop) { return; } + bool wantTiming = Inkscape::Preferences::get()->getBool("/dialogs/debug/trackAppear", false); + GTimer *timer = wantTiming ? g_timer_new() : 0; + if (dlg == NULL) { // very long block @@ -604,6 +608,13 @@ void sp_xml_tree_dialog() tree_reset_context(); } // end of if (dlg == NULL) + if ( wantTiming ) { + // Time tracker takes ownership of the timer. + AppearTimeTracker *tracker = new AppearTimeTracker(timer, GTK_WIDGET(dlg), "DialogXMLEditor"); + tracker->setAutodelete(true); + timer = 0; + } + gtk_window_present((GtkWindow *) dlg); g_assert(desktop != NULL); diff --git a/src/ui/dialog/dialog-manager.cpp b/src/ui/dialog/dialog-manager.cpp index ff31c91c4..0c49690cc 100644 --- a/src/ui/dialog/dialog-manager.cpp +++ b/src/ui/dialog/dialog-manager.cpp @@ -42,6 +42,7 @@ #include "ui/dialog/floating-behavior.h" #include "ui/dialog/dock-behavior.h" //#include "ui/dialog/print-colors-preview-dialog.h" +#include "util/ege-appear-time-tracker.h" #include "preferences.h" #ifdef ENABLE_SVG_FONTS @@ -232,10 +233,23 @@ void DialogManager::showDialog(gchar const *name) { * Shows the named dialog, creating it if necessary. */ void DialogManager::showDialog(GQuark name) { - Dialog *dialog=getDialog(name); - if (dialog) { + bool wantTiming = Inkscape::Preferences::get()->getBool("/dialogs/debug/trackAppear", false); + GTimer *timer = (wantTiming) ? g_timer_new() : 0; // if needed, must be created/started before getDialog() + Dialog *dialog = getDialog(name); + if ( dialog ) { + if ( wantTiming ) { + gchar const * nameStr = g_quark_to_string(name); + ege::AppearTimeTracker *tracker = new ege::AppearTimeTracker(timer, dialog->gobj(), nameStr); + tracker->setAutodelete(true); + timer = 0; + } dialog->present(); } + + if ( timer ) { + g_timer_destroy(timer); + timer = 0; + } } } // namespace Dialog diff --git a/src/util/Makefile_insert b/src/util/Makefile_insert index d2f005531..deff951d4 100644 --- a/src/util/Makefile_insert +++ b/src/util/Makefile_insert @@ -5,6 +5,8 @@ ink_common_sources += \ util/compose.hpp \ util/copy.h \ util/enums.h \ + util/ege-appear-time-tracker.cpp \ + util/ege-appear-time-tracker.h \ util/ege-tags.h \ util/ege-tags.cpp \ util/filter-list.h \ diff --git a/src/util/ege-appear-time-tracker.cpp b/src/util/ege-appear-time-tracker.cpp new file mode 100644 index 000000000..d53e86742 --- /dev/null +++ b/src/util/ege-appear-time-tracker.cpp @@ -0,0 +1,162 @@ +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.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/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Appear Time Tracker. + * + * The Initial Developer of the Original Code is + * Jon A. Cruz. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + + +#include "ege-appear-time-tracker.h" +#include +#include + + +namespace ege +{ + +namespace { + +void unhookHandler( gulong &id, GtkWidget *obj ) +{ + if ( id ) { + if ( obj ) { + g_signal_handler_disconnect( G_OBJECT(obj), id ); + } + id = 0; + } +} + +} // namespace + + +AppearTimeTracker::AppearTimeTracker(GTimer *timer, GtkWidget *widget, gchar const* name) : + _name(name ? name : ""), + _timer(timer), + _widget(widget), + _topMost(widget), + _autodelete(false), + _mapId(0), + _realizeId(0), + _hierarchyId(0) + +{ + while (_topMost->parent) { + _topMost = _topMost->parent; + } + _mapId = g_signal_connect( G_OBJECT(_topMost), "map-event", G_CALLBACK(mapCB), this ); + _realizeId = g_signal_connect( G_OBJECT(_topMost), "realize", G_CALLBACK(realizeCB), this ); + _hierarchyId = g_signal_connect( G_OBJECT(_widget), "hierarchy-changed", G_CALLBACK(hierarchyCB), this ); +} + +AppearTimeTracker::~AppearTimeTracker() +{ + if ( _timer ) { + g_timer_destroy(_timer); + _timer = 0; + } + + unhookHandler( _mapId, _topMost ); + unhookHandler( _realizeId, _topMost ); + unhookHandler( _hierarchyId, _widget ); +} + +void AppearTimeTracker::stop() { + if (_timer) { + g_timer_stop(_timer); + } +} + +void AppearTimeTracker::setAutodelete(bool autodelete) +{ + if ( autodelete != _autodelete ) { + _autodelete = autodelete; + } +} + +void AppearTimeTracker::report(gchar const* msg) +{ + gulong msCount = 0; + gdouble secs = g_timer_elapsed( _timer, &msCount ); + g_message("Time ended at %2.3f with [%s] on [%s]", secs, msg, _name.c_str()); +} + +void AppearTimeTracker::handleHierarchyChange( GtkWidget * /*prevTop*/ ) +{ + GtkWidget *newTop = _widget; + while (newTop->parent) { + newTop = newTop->parent; + } + + if ( newTop != _topMost ) { + unhookHandler( _mapId, _topMost ); + unhookHandler( _realizeId, _topMost ); + + _topMost = newTop; + _mapId = g_signal_connect( G_OBJECT(_topMost), "map-event", G_CALLBACK(mapCB), this ); + _realizeId = g_signal_connect( G_OBJECT(_topMost), "realize", G_CALLBACK(realizeCB), this ); + } +} + +gboolean AppearTimeTracker::mapCB(GtkWidget * /*widget*/, GdkEvent * /*event*/, gpointer userData) +{ + AppearTimeTracker *tracker = reinterpret_cast(userData); + tracker->report("MAP"); + if ( tracker->_autodelete ) { + delete tracker; + } + return FALSE; +} + +void AppearTimeTracker::realizeCB(GtkWidget * /*widget*/, gpointer userData) +{ + AppearTimeTracker *tracker = reinterpret_cast(userData); + tracker->report("REALIZE"); +} + +void AppearTimeTracker::hierarchyCB(GtkWidget * /*widget*/, GtkWidget *prevTop, gpointer userData) +{ + AppearTimeTracker *tracker = reinterpret_cast(userData); + tracker->handleHierarchyChange( prevTop ); +} + +} // namespace ege + +/* + 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/util/ege-appear-time-tracker.h b/src/util/ege-appear-time-tracker.h new file mode 100644 index 000000000..b5ea8b5d2 --- /dev/null +++ b/src/util/ege-appear-time-tracker.h @@ -0,0 +1,89 @@ +#ifndef SEEN_APPEAR_TIME_TRACKER_H +#define SEEN_APPEAR_TIME_TRACKER_H + +/* ***** BEGIN LICENSE BLOCK ***** + * Version: MPL 1.1/GPL 2.0/LGPL 2.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/ + * + * Software distributed under the License is distributed on an "AS IS" basis, + * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License + * for the specific language governing rights and limitations under the + * License. + * + * The Original Code is Appear Time Tracker. + * + * The Initial Developer of the Original Code is + * Jon A. Cruz. + * Portions created by the Initial Developer are Copyright (C) 2010 + * the Initial Developer. All Rights Reserved. + * + * Contributor(s): + * + * Alternatively, the contents of this file may be used under the terms of + * either the GNU General Public License Version 2 or later (the "GPL"), or + * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), + * in which case the provisions of the GPL or the LGPL are applicable instead + * of those above. If you wish to allow use of your version of this file only + * under the terms of either the GPL or the LGPL, and not to allow others to + * use your version of this file under the terms of the MPL, indicate your + * decision by deleting the provisions above and replace them with the notice + * and other provisions required by the GPL or the LGPL. If you do not delete + * the provisions above, a recipient may use your version of this file under + * the terms of any one of the MPL, the GPL or the LGPL. + * + * ***** END LICENSE BLOCK ***** */ + +#include +#include + +typedef union _GdkEvent GdkEvent; +typedef struct _GtkWidget GtkWidget; + +namespace ege +{ + +class AppearTimeTracker { +public: + AppearTimeTracker(GTimer *timer, GtkWidget *widget, gchar const* name); + ~AppearTimeTracker(); + + void stop(); + + bool isAutodelete() const { return _autodelete; } + void setAutodelete(bool autodelete); + +private: + Glib::ustring _name; + GTimer *_timer; + GtkWidget *_widget; + GtkWidget *_topMost; + bool _autodelete; + gulong _mapId; + gulong _realizeId; + gulong _hierarchyId; + + static gboolean mapCB(GtkWidget *widget, GdkEvent *event, gpointer userData); + static void realizeCB(GtkWidget *widget, gpointer userData); + static void hierarchyCB(GtkWidget *widget, GtkWidget *prevTop, gpointer userData); + + void report(gchar const* msg); + void handleHierarchyChange( GtkWidget *prevTop ); +}; + +} // namespace ege + +#endif // SEEN_APPEAR_TIME_TRACKER_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/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 7a3e337de..3509a1040 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -56,6 +56,7 @@ #include "ui/widget/layer-selector.h" #include "ui/widget/selected-style.h" #include "ui/uxmanager.h" +#include "util/ege-appear-time-tracker.h" // We're in the "widgets" directory, so no need to explicitly prefix these: #include "button.h" @@ -73,6 +74,7 @@ using Inkscape::round; using Inkscape::UnitTracker; using Inkscape::UI::UXManager; using Inkscape::UI::ToolboxFactory; +using ege::AppearTimeTracker; #ifdef WITH_INKBOARD #endif @@ -243,6 +245,8 @@ SPDesktopWidget::window_get_pointer() return Geom::Point(x,y); } +static GTimer *overallTimer = 0; + /** * Registers SPDesktopWidget class and returns its type number. */ @@ -263,6 +267,8 @@ GType SPDesktopWidget::getType(void) 0 // value_table }; type = g_type_register_static(SP_TYPE_VIEW_WIDGET, "SPDesktopWidget", &info, static_cast(0)); + // Begin a timer to watch for the first desktop to appear on-screen + overallTimer = g_timer_new(); } return type; } @@ -564,6 +570,18 @@ void SPDesktopWidget::init( SPDesktopWidget *dtw ) gtk_widget_show_all (dtw->vbox); gtk_widget_grab_focus (GTK_WIDGET(dtw->canvas)); + + // If this is the first desktop created, report the time it takes to show up + if ( overallTimer ) { + if ( prefs->getBool("/dialogs/debug/trackAppear", false) ) { + // Time tracker takes ownership of the timer. + AppearTimeTracker *tracker = new AppearTimeTracker(overallTimer, GTK_WIDGET(dtw), "first SPDesktopWidget"); + tracker->setAutodelete(true); + } else { + g_timer_destroy(overallTimer); + } + overallTimer = 0; + } } /** -- cgit v1.2.3 From 66671b66f982b675f17ac5ea940f2b2daf4bfa25 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 17 Dec 2010 22:11:52 -0800 Subject: Prune initial timer work. (bzr r9955.1.3) --- src/widgets/desktop-widget.cpp | 27 --------------------------- 1 file changed, 27 deletions(-) (limited to 'src') diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 4620b1532..3509a1040 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -123,30 +123,6 @@ static void sp_dtw_sticky_zoom_toggled (GtkMenuItem *item, gpointer data); SPViewWidgetClass *dtw_parent_class; -static GTimer *baseTimer = 0; -static bool timeReported = false; - -static void timeGoing(gchar const* id) -{ - if ( !baseTimer ) { - g_message("Starting time at point [%s]", id); - baseTimer = g_timer_new(); - } -} - -static void checkTime(gchar const* msg) -{ - if ( baseTimer && !timeReported ) { - timeReported = true; - g_timer_stop(baseTimer); - gulong msCount = 0; - gdouble secs = g_timer_elapsed( baseTimer, &msCount ); - g_message("Time ended at %2.3f with [%s]", secs, msg); - } -} - - - class CMSPrefWatcher { public: CMSPrefWatcher() : @@ -278,7 +254,6 @@ GType SPDesktopWidget::getType(void) { static GtkType type = 0; if (!type) { - timeGoing("SPDesktopWidget::getType"); GTypeInfo info = { sizeof(SPDesktopWidgetClass), 0, // base_init @@ -304,7 +279,6 @@ GType SPDesktopWidget::getType(void) static void sp_desktop_widget_class_init (SPDesktopWidgetClass *klass) { - timeGoing("sp_desktop_widget_class_init"); dtw_parent_class = (SPViewWidgetClass*)gtk_type_class (SP_TYPE_VIEW_WIDGET); GtkObjectClass *object_class = (GtkObjectClass *) klass; @@ -321,7 +295,6 @@ sp_desktop_widget_class_init (SPDesktopWidgetClass *klass) */ void SPDesktopWidget::init( SPDesktopWidget *dtw ) { - timeGoing("SPDesktopWidget::init"); GtkWidget *widget; GtkWidget *tbl; GtkWidget *canvas_tbl; -- cgit v1.2.3 From c1e346a68272b99fce380ea860fda0a70d3cf8e0 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Fri, 17 Dec 2010 22:22:17 -0800 Subject: Use subdirectories with icon sizes. Perform work only when cache loading is enabled. (bzr r9955.1.4) --- src/widgets/icon.cpp | 59 +++++++++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index d8d684614..70dee457c 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -1198,6 +1198,19 @@ void Inkscape::queueIconPrerender( Glib::ustring const &name, Inkscape::IconSize } } +static std::map sizePaths; + +static std::string getDestDir( unsigned psize ) +{ + if ( sizePaths.find(psize) == sizePaths.end() ) { + gchar *tmp = g_strdup_printf("%dx%d", psize, psize); + sizePaths[psize] = tmp; + g_free(tmp); + } + + return sizePaths[psize]; +} + // returns true if icon needed preloading, false if nothing was done bool prerender_icon(gchar const *name, GtkIconSize lsize, unsigned psize) { @@ -1212,23 +1225,36 @@ bool prerender_icon(gchar const *name, GtkIconSize lsize, unsigned psize) if (dump) { g_message("prerender_icon [%s] %d:%d", name, lsize, psize); } - // In file encoding: - std::string iconCacheDir = Glib::build_filename(Glib::build_filename(Glib::get_user_cache_dir(), "inkscape"), "icons"); - std::string potentialFile = Glib::build_filename( iconCacheDir, name ); - potentialFile += ".png"; - + + std::string potentialFile; bool dataLoaded = false; - if ( useCache && Glib::file_test(potentialFile, Glib::FILE_TEST_EXISTS) && Glib::file_test(potentialFile, Glib::FILE_TEST_IS_REGULAR) ) { - Glib::RefPtr pb = Gdk::Pixbuf::create_from_file(potentialFile); - if (pb) { - dataLoaded = true; - GdkPixbuf *obj = pb->gobj(); - g_object_ref(obj); - pb_cache[key] = obj; - addToIconSet(obj, name, lsize, psize); - loadNeeded = true; - if (internalNames.find(name) == internalNames.end()) { - internalNames.insert(name); + if ( useCache ) { + // In file encoding: + std::string iconCacheDir = Glib::build_filename(Glib::build_filename(Glib::get_user_cache_dir(), "inkscape"), "icons"); + std::string subpart = getDestDir(psize); + if (subpart.empty()) { + g_message("Is empty"); + } + std::string subdir = Glib::build_filename( iconCacheDir, subpart ); + if ( !Glib::file_test(subdir, Glib::FILE_TEST_EXISTS) ) { + g_message("NEED SUB OF [%s]", subdir.c_str()); + g_mkdir_with_parents( subdir.c_str(), 0x1ED ); + } + potentialFile = Glib::build_filename( subdir, name ); + potentialFile += ".png"; + + if ( Glib::file_test(potentialFile, Glib::FILE_TEST_EXISTS) && Glib::file_test(potentialFile, Glib::FILE_TEST_IS_REGULAR) ) { + Glib::RefPtr pb = Gdk::Pixbuf::create_from_file(potentialFile); + if (pb) { + dataLoaded = true; + GdkPixbuf *obj = pb->gobj(); + g_object_ref(obj); + pb_cache[key] = obj; + addToIconSet(obj, name, lsize, psize); + loadNeeded = true; + if (internalNames.find(name) == internalNames.end()) { + internalNames.insert(name); + } } } } @@ -1284,7 +1310,6 @@ static GdkPixbuf *sp_icon_image_load_svg(gchar const *name, GtkIconSize lsize, u // did we already load this icon at this scale/size? GdkPixbuf* pb = get_cached_pixbuf(key); if (!pb) { - g_message("YYYYYYYYYYYYY YYYYYYYYYYYYYYY two load_svg_pixels(%s, %d, %d)", name, lsize, psize); guchar *px = load_svg_pixels(name, lsize, psize); if (px) { pb = gdk_pixbuf_new_from_data(px, GDK_COLORSPACE_RGB, TRUE, 8, -- cgit v1.2.3 From ce100a7a97d72a20337973219c7919b1d4bb0d45 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 18 Dec 2010 10:05:01 -0800 Subject: Fix fallback icon loading order for icons with legacy names. (bzr r9955.1.5) --- src/widgets/icon.cpp | 161 ++++++++++++++++++++++----------------------------- 1 file changed, 70 insertions(+), 91 deletions(-) (limited to 'src') diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index 70dee457c..7c8beeb75 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -1037,13 +1037,15 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, -struct svg_doc_cache_t +class SVGDocCache { +public: + SVGDocCache( SPDocument *doc, NRArenaItem *root ) : doc(doc), root(root) {} SPDocument *doc; NRArenaItem *root; }; -static std::map doc_cache; +static std::map doc_cache; static std::map pb_cache; Glib::ustring icon_cache_key(gchar const *name, unsigned psize) @@ -1079,92 +1081,59 @@ static std::list &icons_svg_paths() } // this function renders icons from icons.svg and returns the pixels. -static guchar *load_svg_pixels(gchar const *name, +static guchar *load_svg_pixels(std::list const &names, unsigned /*lsize*/, unsigned psize) { - SPDocument *doc = NULL; - NRArenaItem *root = NULL; - svg_doc_cache_t *info = NULL; - + bool const dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpSvg"); std::list &sources = icons_svg_paths(); // Try each document in turn until we successfully load the icon from one - guchar *px=NULL; - for (std::list::iterator i = sources.begin(); i != sources.end() && !px; ++i) { + guchar *px = NULL; + for (std::list::iterator i = sources.begin(); (i != sources.end()) && !px; ++i) { gchar *doc_filename = *i; + SVGDocCache *info = 0; // Did we already load this doc? Glib::ustring key(doc_filename); - info = 0; { - std::map::iterator i = doc_cache.find(key); + std::map::iterator i = doc_cache.find(key); if ( i != doc_cache.end() ) { info = i->second; } } - /* Try to load from document. */ - if (!info && - Inkscape::IO::file_test( doc_filename, G_FILE_TEST_IS_REGULAR ) && - (doc = SPDocument::createNewDoc( doc_filename, FALSE )) ) { - - //g_message("Loaded icon file %s", doc_filename); - // prep the document - doc->ensureUpToDate(); - /* Create new arena */ - NRArena *arena = NRArena::create(); - /* Create ArenaItem and set transform */ - unsigned visionkey = SPItem::display_key_new(1); - /* fixme: Memory manage root if needed (Lauris) */ - // This needs to be fixed indeed; this leads to a memory leak of a few megabytes these days - // because shapes are being rendered which are not being freed - // Valgrind output: - /*==7014== 1,548,344 bytes in 599 blocks are possibly lost in loss record 20,361 of 20,362 - ==7014== at 0x4A05974: operator new(unsigned long) (vg_replace_malloc.c:220) - ==7014== by 0x4F1015: __gnu_cxx::new_allocator::allocate(unsigned long, void const*) (new_allocator.h:89) - ==7014== by 0x4F02AC: std::_Vector_base >::_M_allocate(unsigned long) (stl_vector.h:140) - ==7014== by 0xCF62D7: std::vector >::_M_fill_insert(__gnu_cxx::__normal_iterator > >, unsigned long, Shape::point_data const&) (vector.tcc:414) - ==7014== by 0xCF4D45: std::vector >::insert(__gnu_cxx::__normal_iterator > >, unsigned long, Shape::point_data const&) (stl_vector.h:851) - ==7014== by 0xCF3DCD: std::vector >::resize(unsigned long, Shape::point_data) (stl_vector.h:557) - ==7014== by 0xCEA771: Shape::AddPoint(Geom::Point) (Shape.cpp:326) - ==7014== by 0xD0F413: Shape::ConvertToShape(Shape*, fill_typ, bool) (ShapeSweep.cpp:257) - ==7014== by 0x5ECD4F: nr_arena_shape_update_stroke(NRArenaShape*, NRGC*, NRRectL*) (nr-arena-shape.cpp:651) - ==7014== by 0x5EE0DA: nr_arena_shape_render(_cairo*, NRArenaItem*, NRRectL*, NRPixBlock*, unsigned int) (nr-arena-shape.cpp:862) - ==7014== by 0x5E72FB: nr_arena_item_invoke_render(_cairo*, NRArenaItem*, NRRectL const*, NRPixBlock*, unsigned int) (nr-arena-item.cpp:578) - ==7014== by 0x5E9DDE: nr_arena_group_render(_cairo*, NRArenaItem*, NRRectL*, NRPixBlock*, unsigned int) (nr-arena-group.cpp:228) - ==7014== by 0x5E72FB: nr_arena_item_invoke_render(_cairo*, NRArenaItem*, NRRectL const*, NRPixBlock*, unsigned int) (nr-arena-item.cpp:578) - ==7014== by 0x5E9DDE: nr_arena_group_render(_cairo*, NRArenaItem*, NRRectL*, NRPixBlock*, unsigned int) (nr-arena-group.cpp:228) - ==7014== by 0x5E72FB: nr_arena_item_invoke_render(_cairo*, NRArenaItem*, NRRectL const*, NRPixBlock*, unsigned int) (nr-arena-item.cpp:578) - */ - root = SP_ITEM(doc->getRoot())->invoke_show(arena, visionkey, SP_ITEM_SHOW_DISPLAY ); - - // store into the cache - info = new svg_doc_cache_t; - g_assert(info); - - info->doc=doc; - info->root=root; - doc_cache[key]=info; + // Try to load from document. + if (!info && Inkscape::IO::file_test( doc_filename, G_FILE_TEST_IS_REGULAR ) ) { + SPDocument *doc = SPDocument::createNewDoc( doc_filename, FALSE ); + if ( doc ) { + if ( dump ) { + g_message("Loaded icon file %s", doc_filename); + } + // prep the document + doc->ensureUpToDate(); + + // Create new arena + NRArena *arena = NRArena::create(); + + // Create ArenaItem and set transform + unsigned visionkey = SPItem::display_key_new(1); + // fixme: Memory manage root if needed (Lauris) + // This needs to be fixed indeed; this leads to a memory leak of a few megabytes these days + // because shapes are being rendered which are not being freed + NRArenaItem *root = SP_ITEM(doc->getRoot())->invoke_show( arena, visionkey, SP_ITEM_SHOW_DISPLAY ); + + // store into the cache + info = new SVGDocCache(doc, root); + doc_cache[key] = info; + } } if (info) { - doc=info->doc; - root=info->root; - } - - // move on to the next document if we couldn't get anything - if (!info && !doc) { - continue; + for (std::list::const_iterator it = names.begin(); !px && (it != names.end()); ++it ) { + px = sp_icon_doc_icon( info->doc, info->root, it->c_str(), psize ); + } } - - px = sp_icon_doc_icon( doc, root, name, psize ); -// if (px) { -// g_message("Found icon %s in %s", name, doc_filename); -// } } -// if (!px) { -// g_message("Not found icon %s", name); -// } return px; } @@ -1232,44 +1201,52 @@ bool prerender_icon(gchar const *name, GtkIconSize lsize, unsigned psize) // In file encoding: std::string iconCacheDir = Glib::build_filename(Glib::build_filename(Glib::get_user_cache_dir(), "inkscape"), "icons"); std::string subpart = getDestDir(psize); - if (subpart.empty()) { - g_message("Is empty"); - } std::string subdir = Glib::build_filename( iconCacheDir, subpart ); if ( !Glib::file_test(subdir, Glib::FILE_TEST_EXISTS) ) { - g_message("NEED SUB OF [%s]", subdir.c_str()); g_mkdir_with_parents( subdir.c_str(), 0x1ED ); } potentialFile = Glib::build_filename( subdir, name ); potentialFile += ".png"; if ( Glib::file_test(potentialFile, Glib::FILE_TEST_EXISTS) && Glib::file_test(potentialFile, Glib::FILE_TEST_IS_REGULAR) ) { - Glib::RefPtr pb = Gdk::Pixbuf::create_from_file(potentialFile); - if (pb) { - dataLoaded = true; - GdkPixbuf *obj = pb->gobj(); - g_object_ref(obj); - pb_cache[key] = obj; - addToIconSet(obj, name, lsize, psize); - loadNeeded = true; - if (internalNames.find(name) == internalNames.end()) { - internalNames.insert(name); + bool badFile = false; + try { + Glib::RefPtr pb = Gdk::Pixbuf::create_from_file(potentialFile); + if (pb) { + dataLoaded = true; + GdkPixbuf *obj = pb->gobj(); + g_object_ref(obj); + pb_cache[key] = obj; + addToIconSet(obj, name, lsize, psize); + loadNeeded = true; + if (internalNames.find(name) == internalNames.end()) { + internalNames.insert(name); + } } + } catch ( Glib::FileError &ex ) { + g_warning("FileError [%s]", ex.what().c_str()); + badFile = true; + } catch ( Gdk::PixbufError &ex ) { + g_warning("PixbufError [%s]", ex.what().c_str()); + // Invalid contents. Remove cached item + badFile = true; + } + if ( badFile ) { + g_remove(potentialFile.c_str()); } } } if (!dataLoaded) { - guchar* px = load_svg_pixels(name, lsize, psize); - if ( !px ) { - // check for a fallback name - if ( legacyNames.find(name) != legacyNames.end() ) { - if ( dump ) { - g_message("load_svg_pixels([%s]=%s, %d, %d)", name, legacyNames[name].c_str(), lsize, psize); - } - px = load_svg_pixels(legacyNames[name].c_str(), lsize, psize); + std::list names; + names.push_back(name); + if ( legacyNames.find(name) != legacyNames.end() ) { + names.push_back(legacyNames[name]); + if ( dump ) { + g_message("load_svg_pixels([%s] = %s, %d, %d)", name, legacyNames[name].c_str(), lsize, psize); } } + guchar* px = load_svg_pixels(names, lsize, psize); if (px) { GdkPixbuf* pb = gdk_pixbuf_new_from_data( px, GDK_COLORSPACE_RGB, TRUE, 8, psize, psize, psize * 4, @@ -1310,7 +1287,9 @@ static GdkPixbuf *sp_icon_image_load_svg(gchar const *name, GtkIconSize lsize, u // did we already load this icon at this scale/size? GdkPixbuf* pb = get_cached_pixbuf(key); if (!pb) { - guchar *px = load_svg_pixels(name, lsize, psize); + std::list names; + names.push_back(name); + guchar *px = load_svg_pixels(names, lsize, psize); if (px) { pb = gdk_pixbuf_new_from_data(px, GDK_COLORSPACE_RGB, TRUE, 8, psize, psize, psize * 4, -- cgit v1.2.3 From 304b6faeadb88b331f8395c105714f7924b9a7cf Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 18 Dec 2010 10:53:34 -0800 Subject: Add missing include\. (bzr r9955.1.6) --- src/widgets/icon.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index 7c8beeb75..46c7fdf90 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -18,6 +18,7 @@ #include #include +#include #include #include #include -- cgit v1.2.3 From 415933e6c0f092bb1ec732cc61ddee0ceeb043e0 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 18 Dec 2010 11:50:04 -0800 Subject: Fix other fallback icon lookup. (bzr r9955.1.7) --- src/widgets/icon.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index 46c7fdf90..99acbb8ca 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -56,7 +56,7 @@ static void sp_icon_style_set( GtkWidget *widget, GtkStyle *previous_style ); static void sp_icon_theme_changed( SPIcon *icon ); static GdkPixbuf *sp_icon_image_load_pixmap(gchar const *name, unsigned lsize, unsigned psize); -static GdkPixbuf *sp_icon_image_load_svg(gchar const *name, GtkIconSize lsize, unsigned psize); +static GdkPixbuf *sp_icon_image_load_svg(std::list const &names, GtkIconSize lsize, unsigned psize); static void sp_icon_overlay_pixels( guchar *px, int width, int height, int stride, unsigned r, unsigned g, unsigned b ); @@ -230,14 +230,17 @@ GdkPixbuf* renderup( gchar const* name, Inkscape::IconSize lsize, unsigned psize pb = gtk_icon_theme_load_icon(theme, name, psize, (GtkIconLookupFlags) 0, NULL); } if (!pb) { - pb = sp_icon_image_load_svg( name, Inkscape::getRegisteredIconSize(lsize), psize ); - if (!pb && (legacyNames.find(name) != legacyNames.end())) { + std::list names; + names.push_back(name); + if ( legacyNames.find(name) != legacyNames.end() ) { if ( Inkscape::Preferences::get()->getBool("/debug/icons/dumpSvg") ) { g_message("Checking fallback [%s]->[%s]", name, legacyNames[name].c_str()); } - pb = sp_icon_image_load_svg( legacyNames[name].c_str(), Inkscape::getRegisteredIconSize(lsize), psize ); + names.push_back(legacyNames[name]); } + pb = sp_icon_image_load_svg( names, Inkscape::getRegisteredIconSize(lsize), psize ); + // if this was loaded from SVG, add it as a builtin icon if (pb) { gtk_icon_theme_add_builtin_icon(name, psize, pb); @@ -286,7 +289,7 @@ static void sp_icon_theme_changed( SPIcon *icon ) static void imageMapCB(GtkWidget* widget, gpointer user_data); static void imageMapNamedCB(GtkWidget* widget, gpointer user_data); static bool prerender_icon(gchar const *name, GtkIconSize lsize, unsigned psize); -static Glib::ustring icon_cache_key(gchar const *name, unsigned psize); +static Glib::ustring icon_cache_key(Glib::ustring const &name, unsigned psize); static GdkPixbuf *get_cached_pixbuf(Glib::ustring const &key); static void setupLegacyNaming() { @@ -1049,9 +1052,9 @@ public: static std::map doc_cache; static std::map pb_cache; -Glib::ustring icon_cache_key(gchar const *name, unsigned psize) +Glib::ustring icon_cache_key(Glib::ustring const & name, unsigned psize) { - Glib::ustring key=name; + Glib::ustring key = name; key += ":"; key += psize; return key; @@ -1281,22 +1284,20 @@ bool prerender_icon(gchar const *name, GtkIconSize lsize, unsigned psize) return loadNeeded; } -static GdkPixbuf *sp_icon_image_load_svg(gchar const *name, GtkIconSize lsize, unsigned psize) +static GdkPixbuf *sp_icon_image_load_svg(std::list const &names, GtkIconSize lsize, unsigned psize) { - Glib::ustring key = icon_cache_key(name, psize); + Glib::ustring key = icon_cache_key(*names.begin(), psize); // did we already load this icon at this scale/size? GdkPixbuf* pb = get_cached_pixbuf(key); if (!pb) { - std::list names; - names.push_back(name); guchar *px = load_svg_pixels(names, lsize, psize); if (px) { pb = gdk_pixbuf_new_from_data(px, GDK_COLORSPACE_RGB, TRUE, 8, psize, psize, psize * 4, (GdkPixbufDestroyNotify)g_free, NULL); pb_cache[key] = pb; - addToIconSet(pb, name, lsize, psize); + addToIconSet(pb, names.begin()->c_str(), lsize, psize); } } -- cgit v1.2.3 From 427a888cb886bf68bf12377cf7f53b78178e46b9 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 18 Dec 2010 14:43:10 -0800 Subject: C++-ification. (bzr r9955.1.8) --- src/widgets/icon.cpp | 244 ++++++++++++++++++++++++++------------------------- src/widgets/icon.h | 26 ++++-- 2 files changed, 146 insertions(+), 124 deletions(-) (limited to 'src') diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index 99acbb8ca..3b9b47425 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -34,36 +34,58 @@ #include "icon.h" -static gboolean icon_prerender_task(gpointer data); -static void addPreRender( GtkIconSize lsize, gchar const *name ); +struct IconImpl { + static void classInit(SPIconClass *klass); + static void init(SPIcon *icon); -static void sp_icon_class_init(SPIconClass *klass); -static void sp_icon_init(SPIcon *icon); -static void sp_icon_dispose(GObject *object); + static GtkWidget *newFull( Inkscape::IconSize lsize, gchar const *name ); -static void sp_icon_reset(SPIcon *icon); -static void sp_icon_clear(SPIcon *icon); + static void dispose(GObject *object); -static void sp_icon_size_request(GtkWidget *widget, GtkRequisition *requisition); -static void sp_icon_size_allocate(GtkWidget *widget, GtkAllocation *allocation); -static int sp_icon_expose(GtkWidget *widget, GdkEventExpose *event); + static void reset(SPIcon *icon); + static void clear(SPIcon *icon); -static void sp_icon_paint(SPIcon *icon, GdkRectangle const *area); + static void sizeRequest(GtkWidget *widget, GtkRequisition *requisition); + static void sizeAllocate(GtkWidget *widget, GtkAllocation *allocation); + static int expose(GtkWidget *widget, GdkEventExpose *event); -static void sp_icon_screen_changed( GtkWidget *widget, GdkScreen *previous_screen ); -static void sp_icon_style_set( GtkWidget *widget, GtkStyle *previous_style ); -static void sp_icon_theme_changed( SPIcon *icon ); + static void paint(SPIcon *icon, GdkRectangle const *area); -static GdkPixbuf *sp_icon_image_load_pixmap(gchar const *name, unsigned lsize, unsigned psize); -static GdkPixbuf *sp_icon_image_load_svg(std::list const &names, GtkIconSize lsize, unsigned psize); + static void screenChanged( GtkWidget *widget, GdkScreen *previous_screen ); + static void styleSet( GtkWidget *widget, GtkStyle *previous_style ); + static void themeChanged( SPIcon *icon ); -static void sp_icon_overlay_pixels( guchar *px, int width, int height, int stride, - unsigned r, unsigned g, unsigned b ); + static int getPhysSize(int size); + static void fetchPixbuf( SPIcon *icon ); -static void injectCustomSize(); + static gboolean prerenderTask(gpointer data); + static void addPreRender( GtkIconSize lsize, gchar const *name ); + static GdkPixbuf* renderup( gchar const* name, Inkscape::IconSize lsize, unsigned psize ); + + + static GdkPixbuf *loadPixmap(gchar const *name, unsigned lsize, unsigned psize); + static GdkPixbuf *loadSvg(std::list const &names, GtkIconSize lsize, unsigned psize); + + static void overlayPixels( guchar *px, int width, int height, int stride, + unsigned r, unsigned g, unsigned b ); + + static void injectCustomSize(); + + static void imageMapCB(GtkWidget* widget, gpointer user_data); + static void imageMapNamedCB(GtkWidget* widget, gpointer user_data); + static bool prerenderIcon(gchar const *name, GtkIconSize lsize, unsigned psize); + + static void setupLegacyNaming(); + +private: + static GtkWidgetClass *parent_class; + static std::map legacyNames; +}; + +GtkWidgetClass *IconImpl::parent_class = 0; +std::map IconImpl::legacyNames; -static GtkWidgetClass *parent_class; static bool sizeDirty = true; @@ -79,8 +101,6 @@ static GtkIconSize iconSizeLookup[] = { GTK_ICON_SIZE_MENU, // for Inkscape::ICON_SIZE_DECORATION }; -static std::map legacyNames; - class IconCacheItem { public: @@ -95,8 +115,7 @@ public: static std::map > iconSetCache; static std::set internalNames; -GType -sp_icon_get_type() +GType SPIcon::getType() { static GType type = 0; if (!type) { @@ -104,12 +123,12 @@ sp_icon_get_type() sizeof(SPIconClass), NULL, NULL, - (GClassInitFunc) sp_icon_class_init, + reinterpret_cast(IconImpl::classInit), NULL, NULL, sizeof(SPIcon), 0, - (GInstanceInitFunc) sp_icon_init, + reinterpret_cast(IconImpl::init), NULL }; type = g_type_register_static(GTK_TYPE_WIDGET, "SPIcon", &info, (GTypeFlags)0); @@ -117,8 +136,7 @@ sp_icon_get_type() return type; } -static void -sp_icon_class_init(SPIconClass *klass) +void IconImpl::classInit(SPIconClass *klass) { GObjectClass *object_class; GtkWidgetClass *widget_class; @@ -128,18 +146,16 @@ sp_icon_class_init(SPIconClass *klass) parent_class = (GtkWidgetClass*)g_type_class_peek_parent(klass); - object_class->dispose = sp_icon_dispose; + object_class->dispose = IconImpl::dispose; - widget_class->size_request = sp_icon_size_request; - widget_class->size_allocate = sp_icon_size_allocate; - widget_class->expose_event = sp_icon_expose; - widget_class->screen_changed = sp_icon_screen_changed; - widget_class->style_set = sp_icon_style_set; + widget_class->size_request = IconImpl::sizeRequest; + widget_class->size_allocate = IconImpl::sizeAllocate; + widget_class->expose_event = IconImpl::expose; + widget_class->screen_changed = IconImpl::screenChanged; + widget_class->style_set = IconImpl::styleSet; } - -static void -sp_icon_init(SPIcon *icon) +void IconImpl::init(SPIcon *icon) { GTK_WIDGET_FLAGS(icon) |= GTK_NO_WINDOW; icon->lsize = Inkscape::ICON_SIZE_BUTTON; @@ -148,11 +164,10 @@ sp_icon_init(SPIcon *icon) icon->pb = 0; } -static void -sp_icon_dispose(GObject *object) +void IconImpl::dispose(GObject *object) { SPIcon *icon = SP_ICON(object); - sp_icon_clear(icon); + clear(icon); if ( icon->name ) { g_free( icon->name ); icon->name = 0; @@ -161,32 +176,32 @@ sp_icon_dispose(GObject *object) ((GObjectClass *) (parent_class))->dispose(object); } -static void sp_icon_reset( SPIcon *icon ) { +void IconImpl::reset( SPIcon *icon ) +{ icon->psize = 0; - sp_icon_clear(icon); + clear(icon); } -static void sp_icon_clear( SPIcon *icon ) { +void IconImpl::clear( SPIcon *icon ) +{ if (icon->pb) { g_object_unref(G_OBJECT(icon->pb)); icon->pb = NULL; } } -static void -sp_icon_size_request(GtkWidget *widget, GtkRequisition *requisition) +void IconImpl::sizeRequest(GtkWidget *widget, GtkRequisition *requisition) { SPIcon const *icon = SP_ICON(widget); int const size = ( icon->psize ? icon->psize - : sp_icon_get_phys_size(icon->lsize) ); + : getPhysSize(icon->lsize) ); requisition->width = size; requisition->height = size; } -static void -sp_icon_size_allocate(GtkWidget *widget, GtkAllocation *allocation) +void IconImpl::sizeAllocate(GtkWidget *widget, GtkAllocation *allocation) { widget->allocation = *allocation; @@ -195,34 +210,37 @@ sp_icon_size_allocate(GtkWidget *widget, GtkAllocation *allocation) } } -static int sp_icon_expose(GtkWidget *widget, GdkEventExpose *event) +int IconImpl::expose(GtkWidget *widget, GdkEventExpose *event) { if ( GTK_WIDGET_DRAWABLE(widget) ) { SPIcon *icon = SP_ICON(widget); if ( !icon->pb ) { - sp_icon_fetch_pixbuf( icon ); + fetchPixbuf( icon ); } - sp_icon_paint(SP_ICON(widget), &event->area); + paint(icon, &event->area); } return TRUE; } -static GdkPixbuf* renderup( gchar const* name, Inkscape::IconSize lsize, unsigned psize ); - // PUBLIC CALL: void sp_icon_fetch_pixbuf( SPIcon *icon ) +{ + return IconImpl::fetchPixbuf(icon); +} + +void IconImpl::fetchPixbuf( SPIcon *icon ) { if ( icon ) { if ( !icon->pb ) { - icon->psize = sp_icon_get_phys_size(icon->lsize); + icon->psize = getPhysSize(icon->lsize); icon->pb = renderup(icon->name, icon->lsize, icon->psize); } } } -GdkPixbuf* renderup( gchar const* name, Inkscape::IconSize lsize, unsigned psize ) { +GdkPixbuf* IconImpl::renderup( gchar const* name, Inkscape::IconSize lsize, unsigned psize ) { GtkIconTheme *theme = gtk_icon_theme_get_default(); GdkPixbuf *pb = 0; @@ -239,7 +257,7 @@ GdkPixbuf* renderup( gchar const* name, Inkscape::IconSize lsize, unsigned psize names.push_back(legacyNames[name]); } - pb = sp_icon_image_load_svg( names, Inkscape::getRegisteredIconSize(lsize), psize ); + pb = loadSvg( names, Inkscape::getRegisteredIconSize(lsize), psize ); // if this was loaded from SVG, add it as a builtin icon if (pb) { @@ -247,7 +265,7 @@ GdkPixbuf* renderup( gchar const* name, Inkscape::IconSize lsize, unsigned psize } } if (!pb) { - pb = sp_icon_image_load_pixmap( name, lsize, psize ); + pb = loadPixmap( name, lsize, psize ); } if ( !pb ) { // TODO: We should do something more useful if we can't load the image. @@ -256,43 +274,40 @@ GdkPixbuf* renderup( gchar const* name, Inkscape::IconSize lsize, unsigned psize return pb; } -static void sp_icon_screen_changed( GtkWidget *widget, GdkScreen *previous_screen ) +void IconImpl::screenChanged( GtkWidget *widget, GdkScreen *previous_screen ) { if ( GTK_WIDGET_CLASS( parent_class )->screen_changed ) { GTK_WIDGET_CLASS( parent_class )->screen_changed( widget, previous_screen ); } SPIcon *icon = SP_ICON(widget); - sp_icon_theme_changed(icon); + themeChanged(icon); } -static void sp_icon_style_set( GtkWidget *widget, GtkStyle *previous_style ) +void IconImpl::styleSet( GtkWidget *widget, GtkStyle *previous_style ) { if ( GTK_WIDGET_CLASS( parent_class )->style_set ) { GTK_WIDGET_CLASS( parent_class )->style_set( widget, previous_style ); } SPIcon *icon = SP_ICON(widget); - sp_icon_theme_changed(icon); + themeChanged(icon); } -static void sp_icon_theme_changed( SPIcon *icon ) +void IconImpl::themeChanged( SPIcon *icon ) { bool const dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpSvg"); if ( dump ) { g_message("Got a change bump for this icon"); } sizeDirty = true; - sp_icon_reset(icon); + reset(icon); gtk_widget_queue_draw( GTK_WIDGET(icon) ); } -static void imageMapCB(GtkWidget* widget, gpointer user_data); -static void imageMapNamedCB(GtkWidget* widget, gpointer user_data); -static bool prerender_icon(gchar const *name, GtkIconSize lsize, unsigned psize); static Glib::ustring icon_cache_key(Glib::ustring const &name, unsigned psize); static GdkPixbuf *get_cached_pixbuf(Glib::ustring const &key); -static void setupLegacyNaming() { +void IconImpl::setupLegacyNaming() { legacyNames["document-import"] ="file_import"; legacyNames["document-export"] ="file_export"; legacyNames["document-import-ocal"] ="ocal_import"; @@ -547,7 +562,7 @@ static void setupLegacyNaming() { legacyNames["zoom"] ="sticky_zoom"; } -static GtkWidget *sp_icon_new_full( Inkscape::IconSize lsize, gchar const *name ) +GtkWidget *IconImpl::newFull( Inkscape::IconSize lsize, gchar const *name ) { static bool dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpGtk"); @@ -603,8 +618,8 @@ static GtkWidget *sp_icon_new_full( Inkscape::IconSize lsize, gchar const *name g_signal_connect( G_OBJECT(widget), "map", G_CALLBACK(imageMapNamedCB), GINT_TO_POINTER(0) ); if ( Inkscape::Preferences::get()->getBool("/options/iconrender/named_nodelay") ) { - int psize = sp_icon_get_phys_size(lsize); - prerender_icon(name, mappedSize, psize); + int psize = getPhysSize(lsize); + prerenderIcon(name, mappedSize, psize); } else { addPreRender( mappedSize, name ); } @@ -622,7 +637,7 @@ static GtkWidget *sp_icon_new_full( Inkscape::IconSize lsize, gchar const *name SPIcon *icon = (SPIcon *)g_object_new(SP_TYPE_ICON, NULL); icon->lsize = lsize; icon->name = g_strdup(name); - icon->psize = sp_icon_get_phys_size(lsize); + icon->psize = getPhysSize(lsize); widget = GTK_WIDGET(icon); } @@ -630,17 +645,17 @@ static GtkWidget *sp_icon_new_full( Inkscape::IconSize lsize, gchar const *name return widget; } -GtkWidget * -sp_icon_new( Inkscape::IconSize lsize, gchar const *name ) +// PUBLIC CALL: +GtkWidget *sp_icon_new( Inkscape::IconSize lsize, gchar const *name ) { - return sp_icon_new_full( lsize, name ); + return IconImpl::newFull( lsize, name ); } // PUBLIC CALL: Gtk::Widget *sp_icon_get_icon( Glib::ustring const &oid, Inkscape::IconSize size ) { Gtk::Widget *result = 0; - GtkWidget *widget = sp_icon_new_full( static_cast(Inkscape::getRegisteredIconSize(size)), oid.c_str() ); + GtkWidget *widget = IconImpl::newFull( static_cast(Inkscape::getRegisteredIconSize(size)), oid.c_str() ); if ( widget ) { if ( GTK_IS_IMAGE(widget) ) { @@ -654,22 +669,7 @@ Gtk::Widget *sp_icon_get_icon( Glib::ustring const &oid, Inkscape::IconSize size return result; } -GtkIconSize -sp_icon_get_gtk_size(int size) -{ - static GtkIconSize sizemap[64] = {(GtkIconSize)0}; - size = CLAMP(size, 4, 63); - if (!sizemap[size]) { - static int count = 0; - char c[64]; - g_snprintf(c, 64, "InkscapeIcon%d", count++); - sizemap[size] = gtk_icon_size_register(c, size, size); - } - return sizemap[size]; -} - - -static void injectCustomSize() +void IconImpl::injectCustomSize() { // TODO - still need to handle the case of theme changes and resize, especially as we can't re-register a string. if ( !sizeMapDone ) @@ -700,7 +700,7 @@ static void injectCustomSize() GtkIconSize Inkscape::getRegisteredIconSize( Inkscape::IconSize size ) { GtkIconSize other = GTK_ICON_SIZE_MENU; - injectCustomSize(); + IconImpl::injectCustomSize(); size = CLAMP( size, Inkscape::ICON_SIZE_MENU, Inkscape::ICON_SIZE_DECORATION ); if ( size == Inkscape::ICON_SIZE_DECORATION ) { other = gtk_icon_size_from_name("inkscape-decoration"); @@ -714,6 +714,11 @@ GtkIconSize Inkscape::getRegisteredIconSize( Inkscape::IconSize size ) // PUBLIC CALL: int sp_icon_get_phys_size(int size) +{ + return IconImpl::getPhysSize(size); +} + +int IconImpl::getPhysSize(int size) { static bool init = false; static int lastSys[Inkscape::ICON_SIZE_DECORATION + 1]; @@ -828,7 +833,7 @@ int sp_icon_get_phys_size(int size) return vals[size]; } -static void sp_icon_paint(SPIcon *icon, GdkRectangle const */*area*/) +void IconImpl::paint(SPIcon *icon, GdkRectangle const */*area*/) { GtkWidget &widget = *GTK_WIDGET(icon); GdkPixbuf *image = icon->pb; @@ -864,7 +869,7 @@ static void sp_icon_paint(SPIcon *icon, GdkRectangle const */*area*/) } } -GdkPixbuf *sp_icon_image_load_pixmap(gchar const *name, unsigned /*lsize*/, unsigned psize) +GdkPixbuf *IconImpl::loadPixmap(gchar const *name, unsigned /*lsize*/, unsigned psize) { gchar *path = (gchar *) g_strdup_printf("%s/%s.png", INKSCAPE_PIXMAPDIR, name); // TODO: bulia, please look over @@ -912,9 +917,8 @@ GdkPixbuf *sp_icon_image_load_pixmap(gchar const *name, unsigned /*lsize*/, unsi } // takes doc, root, icon, and icon name to produce pixels -extern "C" guchar * -sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, - gchar const *name, unsigned psize ) +extern "C" guchar *sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, + gchar const *name, unsigned psize ) { bool const dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpSvg"); guchar *px = NULL; @@ -1030,7 +1034,7 @@ sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, nr_pixblock_release(&B); if ( Inkscape::Preferences::get()->getBool("/debug/icons/overlaySvg") ) { - sp_icon_overlay_pixels( px, psize, psize, 4 * psize, 0x00, 0x00, 0xff ); + IconImpl::overlayPixels( px, psize, psize, 4 * psize, 0x00, 0x00, 0xff ); } } } @@ -1161,13 +1165,13 @@ void Inkscape::queueIconPrerender( Glib::ustring const &name, Inkscape::IconSize if (!stockFound && !themedFound ) { gint trySize = CLAMP( static_cast(lsize), 0, static_cast(G_N_ELEMENTS(iconSizeLookup) - 1) ); if ( !sizeMapDone ) { - injectCustomSize(); + IconImpl::injectCustomSize(); } GtkIconSize mappedSize = iconSizeLookup[trySize]; - int psize = sp_icon_get_phys_size(lsize); + int psize = IconImpl::getPhysSize(lsize); // TODO place in a queue that is triggered by other map events - prerender_icon(name.c_str(), mappedSize, psize); + IconImpl::prerenderIcon(name.c_str(), mappedSize, psize); } } @@ -1185,7 +1189,7 @@ static std::string getDestDir( unsigned psize ) } // returns true if icon needed preloading, false if nothing was done -bool prerender_icon(gchar const *name, GtkIconSize lsize, unsigned psize) +bool IconImpl::prerenderIcon(gchar const *name, GtkIconSize lsize, unsigned psize) { bool loadNeeded = false; static bool dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpGtk"); @@ -1196,7 +1200,7 @@ bool prerender_icon(gchar const *name, GtkIconSize lsize, unsigned psize) if ((internalNames.find(name) != internalNames.end()) || (!gtk_icon_theme_has_icon(gtk_icon_theme_get_default(), name))) { if (dump) { - g_message("prerender_icon [%s] %d:%d", name, lsize, psize); + g_message("prerenderIcon [%s] %d:%d", name, lsize, psize); } std::string potentialFile; @@ -1278,13 +1282,13 @@ bool prerender_icon(gchar const *name, GtkIconSize lsize, unsigned psize) } } else if (dump) { - g_message("prerender_icon [%s] %d NOT!!!!!!", name, psize); + g_message("prerenderIcon [%s] %d NOT!!!!!!", name, psize); } } return loadNeeded; } -static GdkPixbuf *sp_icon_image_load_svg(std::list const &names, GtkIconSize lsize, unsigned psize) +GdkPixbuf *IconImpl::loadSvg(std::list const &names, GtkIconSize lsize, unsigned psize) { Glib::ustring key = icon_cache_key(*names.begin(), psize); @@ -1308,7 +1312,7 @@ static GdkPixbuf *sp_icon_image_load_svg(std::list const &names, return pb; } -void sp_icon_overlay_pixels(guchar *px, int width, int height, int stride, +void IconImpl::overlayPixels(guchar *px, int width, int height, int stride, unsigned r, unsigned g, unsigned b) { int bytesPerPixel = 4; @@ -1380,18 +1384,18 @@ public: static std::vector pendingRenders; static bool callbackHooked = false; -static void addPreRender( GtkIconSize lsize, gchar const *name ) +void IconImpl::addPreRender( GtkIconSize lsize, gchar const *name ) { if ( !callbackHooked ) { callbackHooked = true; - g_idle_add_full( G_PRIORITY_LOW, &icon_prerender_task, NULL, NULL ); + g_idle_add_full( G_PRIORITY_LOW, &prerenderTask, NULL, NULL ); } pendingRenders.push_back(preRenderItem(lsize, name)); } -gboolean icon_prerender_task(gpointer /*data*/) { +gboolean IconImpl::prerenderTask(gpointer /*data*/) { if ( inkscapeIsCrashing() ) { // stop } else if (!pendingRenders.empty()) { @@ -1399,8 +1403,8 @@ gboolean icon_prerender_task(gpointer /*data*/) { do { preRenderItem single = pendingRenders.front(); pendingRenders.erase(pendingRenders.begin()); - int psize = sp_icon_get_phys_size(single._lsize); - workDone = prerender_icon(single._name.c_str(), single._lsize, psize); + int psize = getPhysSize(single._lsize); + workDone = prerenderIcon(single._name.c_str(), single._lsize, psize); } while (!pendingRenders.empty() && !workDone); } @@ -1413,22 +1417,23 @@ gboolean icon_prerender_task(gpointer /*data*/) { } -void imageMapCB(GtkWidget* widget, gpointer user_data) { +void IconImpl::imageMapCB(GtkWidget* widget, gpointer user_data) +{ gchar* id = 0; GtkIconSize size = GTK_ICON_SIZE_INVALID; gtk_image_get_stock(GTK_IMAGE(widget), &id, &size); GtkIconSize lsize = static_cast(GPOINTER_TO_INT(user_data)); if ( id ) { - int psize = sp_icon_get_phys_size(lsize); + int psize = getPhysSize(lsize); g_message("imageMapCB(%p) for [%s]:%d:%d", widget, id, lsize, psize); for ( std::vector::iterator it = pendingRenders.begin(); it != pendingRenders.end(); ++it ) { if ( (it->_name == id) && (it->_lsize == lsize) ) { - prerender_icon(id, lsize, psize); + prerenderIcon(id, lsize, psize); pendingRenders.erase(it); g_message(" prerender for %s:%d:%d", id, lsize, psize); if (lsize != size) { - int psize = sp_icon_get_phys_size(size); - prerender_icon(id, size, psize); + int psize = getPhysSize(size); + prerenderIcon(id, size, psize); } break; } @@ -1438,7 +1443,8 @@ void imageMapCB(GtkWidget* widget, gpointer user_data) { g_signal_handlers_disconnect_by_func(widget, (gpointer)imageMapCB, user_data); } -static void imageMapNamedCB(GtkWidget* widget, gpointer user_data) { +void IconImpl::imageMapNamedCB(GtkWidget* widget, gpointer user_data) +{ GtkImage* img = GTK_IMAGE(widget); gchar const* iconName = 0; GtkIconSize size = GTK_ICON_SIZE_INVALID; @@ -1458,8 +1464,8 @@ static void imageMapNamedCB(GtkWidget* widget, gpointer user_data) { for ( std::vector::iterator it = pendingRenders.begin(); it != pendingRenders.end(); ++it ) { if ( (it->_name == iconName) && (it->_lsize == size) ) { - int psize = sp_icon_get_phys_size(size); - prerender_icon(iconName, size, psize); + int psize = getPhysSize(size); + prerenderIcon(iconName, size, psize); pendingRenders.erase(it); break; } diff --git a/src/widgets/icon.h b/src/widgets/icon.h index f70423702..a20fad73a 100644 --- a/src/widgets/icon.h +++ b/src/widgets/icon.h @@ -6,8 +6,10 @@ * * Author: * Lauris Kaplinski + * Jon A. Cruz * * Copyright (C) 2002 Lauris Kaplinski + * Copyright (C) 2010 Authors * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -16,12 +18,16 @@ #include "icon-size.h" -#define SP_TYPE_ICON (sp_icon_get_type ()) +#define SP_TYPE_ICON SPIcon::getType() #define SP_ICON(o) (GTK_CHECK_CAST ((o), SP_TYPE_ICON, SPIcon)) #define SP_IS_ICON(o) (GTK_CHECK_TYPE ((o), SP_TYPE_ICON)) #include +struct SPIconClass { + GtkWidgetClass parent_class; +}; + struct SPIcon { GtkWidget widget; @@ -30,13 +36,12 @@ struct SPIcon { gchar *name; GdkPixbuf *pb; -}; -struct SPIconClass { - GtkWidgetClass parent_class; + static GType getType(void); + + friend class SPIconImpl; }; -GType sp_icon_get_type (void); GtkWidget *sp_icon_new( Inkscape::IconSize size, const gchar *name ); @@ -54,3 +59,14 @@ namespace Inkscape { } #endif // SEEN_SP_ICON_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 : -- cgit v1.2.3 From c65cc56178d18a3d3c58d708ef1d94bbc658f183 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Tue, 21 Dec 2010 00:10:34 -0800 Subject: Restore name that was broken for testing. (bzr r9955.1.11) --- src/verbs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/verbs.cpp b/src/verbs.cpp index 00a82624b..4cdad7d36 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -2314,7 +2314,7 @@ Verb *Verb::_base_verbs[] = { new EditVerb(SP_VERB_EDIT_CLEAR_ALL, "EditClearAll", N_("Clea_r All"), N_("Delete all objects from document"), NULL), new EditVerb(SP_VERB_EDIT_SELECT_ALL, "EditSelectAll", N_("Select Al_l"), - N_("Select all objects or all nodes"), "fooble"),//GTK_STOCK_SELECT_ALL), + N_("Select all objects or all nodes"), GTK_STOCK_SELECT_ALL), new EditVerb(SP_VERB_EDIT_SELECT_ALL_IN_ALL_LAYERS, "EditSelectAllInAllLayers", N_("Select All in All La_yers"), N_("Select all objects in all visible and unlocked layers"), INKSCAPE_ICON_EDIT_SELECT_ALL_LAYERS), new EditVerb(SP_VERB_EDIT_INVERT, "EditInvert", N_("In_vert Selection"), -- cgit v1.2.3 From e076366297f9aeccb9944b06e3ce5985546d1964 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Tue, 21 Dec 2010 00:13:59 -0800 Subject: Clear cached items when state is invalid. (bzr r9955.1.12) --- src/widgets/icon.cpp | 148 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 145 insertions(+), 3 deletions(-) (limited to 'src') diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index 3b9b47425..3e0746edf 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -22,6 +22,7 @@ #include #include #include +#include #include "path-prefix.h" #include "preferences.h" @@ -76,13 +77,23 @@ struct IconImpl { static void imageMapNamedCB(GtkWidget* widget, gpointer user_data); static bool prerenderIcon(gchar const *name, GtkIconSize lsize, unsigned psize); + + static std::list &icons_svg_paths(); + static guchar *load_svg_pixels(std::list const &names, + unsigned lsize, unsigned psize); + + static std::string fileEscape( std::string const & str ); + + static void validateCache(); static void setupLegacyNaming(); private: + static const std::string magicNumber; static GtkWidgetClass *parent_class; static std::map legacyNames; }; +const std::string IconImpl::magicNumber = "1.0"; GtkWidgetClass *IconImpl::parent_class = 0; std::map IconImpl::legacyNames; @@ -303,6 +314,132 @@ void IconImpl::themeChanged( SPIcon *icon ) gtk_widget_queue_draw( GTK_WIDGET(icon) ); } +std::string IconImpl::fileEscape( std::string const & str ) +{ + std::string result; + result.reserve(str.size()); + for ( size_t i = 0; i < str.size(); ++i ) { + char ch = str[i]; + if ( (0x20 <= ch) && !(0x80 & ch) ) { + result += ch; + } else { + result += "\\x"; + gchar *tmp = g_strdup_printf("%02X", (0x0ff & ch)); + result += tmp; + g_free(tmp); + } + } + return result; +} + +static bool isSizedSubdir( std::string const &name ) +{ + bool isSized = false; + if ( (name.size() > 2) && (name.size() & 1) ) { // needs to be an odd length 3 or more + size_t mid = (name.size() - 1) / 2; + if ( (name[mid] == 'x') && (name.substr(0, mid) == name.substr(mid + 1)) ) { + isSized = true; + for ( size_t i = 0; (i < mid) && isSized; ++i ) { + isSized &= g_ascii_isdigit(name[i]); + } + } + } + return isSized; +} + +void IconImpl::validateCache() +{ + std::list &sources = icons_svg_paths(); + std::string iconCacheDir = Glib::build_filename(Glib::build_filename(Glib::get_user_cache_dir(), "inkscape"), "icons"); + std::string iconCacheFile = Glib::build_filename( iconCacheDir, "cache.info" ); + + std::vector filesFound; + + for (std::list::iterator i = sources.begin(); i != sources.end(); ++i) { + gchar const* potentialFile = *i; + if ( Glib::file_test(potentialFile, Glib::FILE_TEST_EXISTS) && Glib::file_test(potentialFile, Glib::FILE_TEST_IS_REGULAR) ) { + filesFound.push_back(*i); + } + } + + unsigned long lastSeen = 0; + std::ostringstream out; + out << "Inkscape cache v" << std::hex << magicNumber << std::dec << std::endl; + out << "Sourcefiles: " << filesFound.size() << std::endl; + for ( std::vector::iterator it = filesFound.begin(); it != filesFound.end(); ++it ) { + GStatBuf st; + memset(&st, 0, sizeof(st)); + if ( !g_stat(it->c_str(), &st) ) { + unsigned long when = st.st_mtime; + lastSeen = std::max(lastSeen, when); + out << std::hex << when << std::dec << " " << fileEscape(*it) << std::endl; + } else { + out << "0 " << fileEscape(*it) << std::endl; + } + } + std::string wanted = out.str(); + + std::string present; + { + gchar *contents = 0; + if ( g_file_get_contents(iconCacheFile.c_str(), &contents, 0, 0) ) { + if ( contents ) { + present = contents; + } + g_free(contents); + contents = 0; + } + } + bool cacheValid = (present == wanted); + + if ( cacheValid ) { + // Check if any cached rasters are out of date + Glib::Dir dir(iconCacheDir); + for ( Glib::DirIterator it = dir.begin(); cacheValid && (it != dir.end()); ++it ) { + if ( isSizedSubdir(*it) ) { + std::string subdirName = Glib::build_filename( iconCacheDir, *it ); + Glib::Dir subdir(subdirName); + for ( Glib::DirIterator subit = subdir.begin(); cacheValid && (subit != subdir.end()); ++subit ) { + std::string fullpath = Glib::build_filename( subdirName, *subit ); + if ( Glib::file_test(fullpath, Glib::FILE_TEST_EXISTS) && !Glib::file_test(fullpath, Glib::FILE_TEST_IS_DIR) ) { + GStatBuf st; + memset(&st, 0, sizeof(st)); + if ( !g_stat(fullpath.c_str(), &st) ) { + unsigned long when = st.st_mtime; + if ( when < lastSeen ) { + cacheValid = false; + } + } + } + } + } + } + } + + if ( !cacheValid ) { + // Purge existing icons, but not possible future sub-directories. + Glib::Dir dir(iconCacheDir); + for ( Glib::DirIterator it = dir.begin(); it != dir.end(); ++it ) { + if ( isSizedSubdir(*it) ) { + std::string subdirName = Glib::build_filename( iconCacheDir, *it ); + Glib::Dir subdir(subdirName); + for ( Glib::DirIterator subit = subdir.begin(); subit != subdir.end(); ++subit ) { + std::string fullpath = Glib::build_filename( subdirName, *subit ); + if ( Glib::file_test(fullpath, Glib::FILE_TEST_EXISTS) && !Glib::file_test(fullpath, Glib::FILE_TEST_IS_DIR) ) { + g_remove(fullpath.c_str()); + } + } + g_rmdir( subdirName.c_str() ); + } + } + + if ( g_file_set_contents(iconCacheFile.c_str(), wanted.c_str(), wanted.size(), 0) ) { + // Caching may proceed + } else { + g_warning("Unable to write cache info file."); + } + } +} static Glib::ustring icon_cache_key(Glib::ustring const &name, unsigned psize); static GdkPixbuf *get_cached_pixbuf(Glib::ustring const &key); @@ -1073,7 +1210,7 @@ GdkPixbuf *get_cached_pixbuf(Glib::ustring const &key) { return pb; } -static std::list &icons_svg_paths() +std::list &IconImpl::icons_svg_paths() { static std::list sources; static bool initialized = false; @@ -1089,8 +1226,8 @@ static std::list &icons_svg_paths() } // this function renders icons from icons.svg and returns the pixels. -static guchar *load_svg_pixels(std::list const &names, - unsigned /*lsize*/, unsigned psize) +guchar *IconImpl::load_svg_pixels(std::list const &names, + unsigned /*lsize*/, unsigned psize) { bool const dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpSvg"); std::list &sources = icons_svg_paths(); @@ -1194,6 +1331,11 @@ bool IconImpl::prerenderIcon(gchar const *name, GtkIconSize lsize, unsigned psiz bool loadNeeded = false; static bool dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpGtk"); static bool useCache = Inkscape::Preferences::get()->getBool("/debug/icons/useCache"); + static bool cacheValidated = false; + if (!cacheValidated) { + cacheValidated = true; + validateCache(); + } Glib::ustring key = icon_cache_key(name, psize); if ( !get_cached_pixbuf(key) ) { -- cgit v1.2.3 From 20e4fc4bff32e775567487e16bb19e559475b628 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Tue, 21 Dec 2010 00:33:29 -0800 Subject: Enable icon disk cache by default. (bzr r9970) --- src/widgets/icon.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index 3e0746edf..bfdf2d3b9 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -1330,7 +1330,7 @@ bool IconImpl::prerenderIcon(gchar const *name, GtkIconSize lsize, unsigned psiz { bool loadNeeded = false; static bool dump = Inkscape::Preferences::get()->getBool("/debug/icons/dumpGtk"); - static bool useCache = Inkscape::Preferences::get()->getBool("/debug/icons/useCache"); + static bool useCache = Inkscape::Preferences::get()->getBool("/debug/icons/useCache", true); static bool cacheValidated = false; if (!cacheValidated) { cacheValidated = true; -- cgit v1.2.3 From 2ced3393f87dd11df4eb6327fa000ae8cda47ed0 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Tue, 21 Dec 2010 19:43:32 +0100 Subject: Indent support for XSLT extensions output. (bzr r9971) --- src/extension/implementation/xslt.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/implementation/xslt.cpp b/src/extension/implementation/xslt.cpp index c929ba19a..762051339 100644 --- a/src/extension/implementation/xslt.cpp +++ b/src/extension/implementation/xslt.cpp @@ -29,6 +29,7 @@ #include #include +#include Inkscape::XML::Document * sp_repr_do_read (xmlDocPtr doc, const gchar * default_ns); @@ -217,11 +218,16 @@ XSLT::save(Inkscape::Extension::Output */*module*/, SPDocument *doc, gchar const params[0] = NULL; xmlDocPtr newdoc = xsltApplyStylesheet(_stylesheet, svgdoc, params); - xmlSaveFile(filename, newdoc); + //xmlSaveFile(filename, newdoc); + xsltSaveResultToFilename(filename, newdoc, _stylesheet, 0); + xmlFreeDoc(newdoc); xmlFreeDoc(svgdoc); + xsltCleanupGlobals(); + xmlCleanupParser(); + return; } -- cgit v1.2.3 From ed0d3e31f2e6860a20661853c320c2eb8941e41a Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Tue, 21 Dec 2010 11:26:53 -0800 Subject: Unify stat type for older glib. (bzr r9972) --- src/widgets/icon.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'src') diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index bfdf2d3b9..526309727 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -35,6 +35,14 @@ #include "icon.h" +// Bring in work-around for Glib versions missing GStatBuf +#if !GLIB_CHECK_VERSION(2,25,0) +#if defined (_MSC_VER) && !defined(_WIN64) +typedef struct _stat32 GStatBuf; +#else //defined (_MSC_VER) && !defined(_WIN64) +typedef struct stat GStatBuf; +#endif //defined (_MSC_VER) && !defined(_WIN64) +#endif //!GLIB_CHECK_VERSION(2,25,0) struct IconImpl { static void classInit(SPIconClass *klass); -- cgit v1.2.3 From a7ee5b9cbdb640f1bcefb9a5b500d0705a47808f Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Tue, 21 Dec 2010 12:43:41 -0800 Subject: Handle missing, inaccessible and misnamed cache directories. (bzr r9974) --- src/widgets/icon.cpp | 64 +++++++++++++++++++++++++++++++--------------------- 1 file changed, 38 insertions(+), 26 deletions(-) (limited to 'src') diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index 526309727..e7207d944 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -406,16 +406,18 @@ void IconImpl::validateCache() for ( Glib::DirIterator it = dir.begin(); cacheValid && (it != dir.end()); ++it ) { if ( isSizedSubdir(*it) ) { std::string subdirName = Glib::build_filename( iconCacheDir, *it ); - Glib::Dir subdir(subdirName); - for ( Glib::DirIterator subit = subdir.begin(); cacheValid && (subit != subdir.end()); ++subit ) { - std::string fullpath = Glib::build_filename( subdirName, *subit ); - if ( Glib::file_test(fullpath, Glib::FILE_TEST_EXISTS) && !Glib::file_test(fullpath, Glib::FILE_TEST_IS_DIR) ) { - GStatBuf st; - memset(&st, 0, sizeof(st)); - if ( !g_stat(fullpath.c_str(), &st) ) { - unsigned long when = st.st_mtime; - if ( when < lastSeen ) { - cacheValid = false; + if ( Glib::file_test(subdirName, Glib::FILE_TEST_IS_DIR) ) { + Glib::Dir subdir(subdirName); + for ( Glib::DirIterator subit = subdir.begin(); cacheValid && (subit != subdir.end()); ++subit ) { + std::string fullpath = Glib::build_filename( subdirName, *subit ); + if ( Glib::file_test(fullpath, Glib::FILE_TEST_EXISTS) && !Glib::file_test(fullpath, Glib::FILE_TEST_IS_DIR) ) { + GStatBuf st; + memset(&st, 0, sizeof(st)); + if ( !g_stat(fullpath.c_str(), &st) ) { + unsigned long when = st.st_mtime; + if ( when < lastSeen ) { + cacheValid = false; + } } } } @@ -425,20 +427,28 @@ void IconImpl::validateCache() } if ( !cacheValid ) { - // Purge existing icons, but not possible future sub-directories. - Glib::Dir dir(iconCacheDir); - for ( Glib::DirIterator it = dir.begin(); it != dir.end(); ++it ) { - if ( isSizedSubdir(*it) ) { - std::string subdirName = Glib::build_filename( iconCacheDir, *it ); - Glib::Dir subdir(subdirName); - for ( Glib::DirIterator subit = subdir.begin(); subit != subdir.end(); ++subit ) { - std::string fullpath = Glib::build_filename( subdirName, *subit ); - if ( Glib::file_test(fullpath, Glib::FILE_TEST_EXISTS) && !Glib::file_test(fullpath, Glib::FILE_TEST_IS_DIR) ) { - g_remove(fullpath.c_str()); + if ( Glib::file_test(iconCacheDir, Glib::FILE_TEST_EXISTS) ) { + // Purge existing icons, but not possible future sub-directories. + if ( Glib::file_test(iconCacheDir, Glib::FILE_TEST_IS_DIR) ) { + Glib::Dir dir(iconCacheDir); + for ( Glib::DirIterator it = dir.begin(); it != dir.end(); ++it ) { + if ( isSizedSubdir(*it) ) { + std::string subdirName = Glib::build_filename( iconCacheDir, *it ); + if ( Glib::file_test(subdirName, Glib::FILE_TEST_IS_DIR) ) { + Glib::Dir subdir(subdirName); + for ( Glib::DirIterator subit = subdir.begin(); subit != subdir.end(); ++subit ) { + std::string fullpath = Glib::build_filename( subdirName, *subit ); + if ( Glib::file_test(fullpath, Glib::FILE_TEST_EXISTS) && !Glib::file_test(fullpath, Glib::FILE_TEST_IS_DIR) ) { + g_remove(fullpath.c_str()); + } + } + g_rmdir( subdirName.c_str() ); + } } } - g_rmdir( subdirName.c_str() ); } + } else { + g_mkdir_with_parents( iconCacheDir.c_str(), 0x1ED ); } if ( g_file_set_contents(iconCacheFile.c_str(), wanted.c_str(), wanted.size(), 0) ) { @@ -1342,7 +1352,9 @@ bool IconImpl::prerenderIcon(gchar const *name, GtkIconSize lsize, unsigned psiz static bool cacheValidated = false; if (!cacheValidated) { cacheValidated = true; - validateCache(); + if ( useCache ) { + validateCache(); + } } Glib::ustring key = icon_cache_key(name, psize); @@ -1382,10 +1394,10 @@ bool IconImpl::prerenderIcon(gchar const *name, GtkIconSize lsize, unsigned psiz } } } catch ( Glib::FileError &ex ) { - g_warning("FileError [%s]", ex.what().c_str()); + //g_warning("FileError [%s]", ex.what().c_str()); badFile = true; } catch ( Gdk::PixbufError &ex ) { - g_warning("PixbufError [%s]", ex.what().c_str()); + //g_warning("PixbufError [%s]", ex.what().c_str()); // Invalid contents. Remove cached item badFile = true; } @@ -1421,9 +1433,9 @@ bool IconImpl::prerenderIcon(gchar const *name, GtkIconSize lsize, unsigned psiz try { ppp->save( potentialFile, "png" ); } catch ( Glib::FileError &ex ) { - g_warning("FileError [%s]", ex.what().c_str()); + //g_warning("FileError [%s]", ex.what().c_str()); } catch ( Gdk::PixbufError &ex ) { - g_warning("PixbufError [%s]", ex.what().c_str()); + //g_warning("PixbufError [%s]", ex.what().c_str()); } } } else if (dump) { -- cgit v1.2.3 From 9c8be3fa45c9821676ff7180e4f9deb12be140ae Mon Sep 17 00:00:00 2001 From: Maximilian Albert Date: Wed, 22 Dec 2010 17:12:06 +0100 Subject: Enable item-selection by cycling through them (using Alt+mouse wheel scroll). (bzr r9976) --- src/select-context.cpp | 117 ++++++++++++++++++++++++++++++++++++++++++++++++- src/select-context.h | 6 +++ 2 files changed, 121 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/select-context.cpp b/src/select-context.cpp index febcc282d..96758a9f1 100644 --- a/src/select-context.cpp +++ b/src/select-context.cpp @@ -40,6 +40,7 @@ #include "selection-describer.h" #include "seltrans.h" #include "box3d.h" +#include "display/nr-arena-item.h" using Inkscape::DocumentUndo; @@ -109,6 +110,10 @@ sp_select_context_init(SPSelectContext *sc) sc->button_press_shift = false; sc->button_press_ctrl = false; sc->button_press_alt = false; + sc->is_cycling = false; + sc->cycling_items = NULL; + sc->cycling_items_selected_before = NULL; + sc->cycling_cur_item = NULL; sc->_seltrans = NULL; sc->_describer = NULL; @@ -176,7 +181,7 @@ sp_select_context_setup(SPEventContext *ec) desktop->selection, desktop->messageStack(), _("Click selection to toggle scale/rotation handles"), - _("No objects selected. Click, Shift+click, or drag around objects to select.") + _("No objects selected. Click, Shift+click, Alt+scroll mouse on top of objects, or drag around objects to select.") ); select_context->_seltrans = new Inkscape::SelTrans(desktop); @@ -401,6 +406,43 @@ sp_select_context_item_handler(SPEventContext *event_context, SPItem *item, GdkE return ret; } +static void +sp_select_context_cycle_through_items(SPSelectContext *sc, Inkscape::Selection *selection, GdkEventScroll *scroll_event, bool shift_pressed) { + if (!sc->cycling_cur_item) + return; + + NRArenaItem *arenaitem; + SPDesktop *desktop = SP_EVENT_CONTEXT(sc)->desktop; + SPItem *item = SP_ITEM(sc->cycling_cur_item->data); + + // Deactivate current item + if (!g_list_find(sc->cycling_items_selected_before, item) && selection->includes(item)) + selection->remove(item); + arenaitem = item->get_arenaitem(desktop->dkey); + nr_arena_item_set_opacity (arenaitem, 0.3); + + // Find next item and activate it + GList *next; + if (scroll_event->direction == GDK_SCROLL_UP) { + next = sc->cycling_cur_item->next; + if (next == NULL) + next = sc->cycling_items; + } else { + next = sc->cycling_cur_item->prev; + if (next == NULL) + next = g_list_last(sc->cycling_items); + } + sc->cycling_cur_item = next; + item = SP_ITEM(sc->cycling_cur_item->data); + arenaitem = item->get_arenaitem(desktop->dkey); + nr_arena_item_set_opacity (arenaitem, 1.0); + + if (shift_pressed) + selection->add(item); + else + selection->set(item); +} + static gint sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) { @@ -481,6 +523,22 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) break; case GDK_MOTION_NOTIFY: + { + SPSelectContext *sc = SP_SELECT_CONTEXT(event_context); + if (sc->is_cycling) { + // Abort cycle-select + NRArenaItem *arenaitem; + for (GList *l = sc->cycling_items; l != NULL; l = g_list_next(l)) { + arenaitem = item->get_arenaitem(desktop->dkey); + nr_arena_item_set_opacity (arenaitem, 1.0); + } + g_list_free(sc->cycling_items); + g_list_free(sc->cycling_items_selected_before); + sc->cycling_items = NULL; + sc->cycling_cur_item = NULL; + sc->is_cycling = false; + } + tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); if (event->motion.state & GDK_BUTTON1_MASK && !event_context->space_panning) { Geom::Point const motion_pt(event->motion.x, event->motion.y); @@ -567,6 +625,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) } } break; + } case GDK_BUTTON_RELEASE: xp = yp = 0; if ((event->button.button == 1) && (sc->grabbed) && !event_context->space_panning) { @@ -699,6 +758,42 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) sc->button_press_alt = false; break; + case GDK_SCROLL: + { + SPSelectContext *sc = SP_SELECT_CONTEXT(event_context); + GdkEventScroll *scroll_event = (GdkEventScroll*) event; + + if (scroll_event->state & GDK_MOD1_MASK) { // alt modified pressed + bool shift_pressed = scroll_event->state & GDK_SHIFT_MASK; + + if(sc->is_cycling == false) { + // Build a list of items underneath the mouse pointer (for cycle-selection) and reduce their opacity + Geom::Point p = desktop->d2w(desktop->point()); + SPItem *item = desktop->getItemAtPoint(p, true, NULL); + while(item != NULL) { + sc->cycling_items = g_list_append(sc->cycling_items, item); + if (selection->includes(item)) { + // already selected items are stored separately, too + sc->cycling_items_selected_before = g_list_append(sc->cycling_items_selected_before, item); + } + NRArenaItem *arenaitem = item->get_arenaitem(desktop->dkey); + nr_arena_item_set_opacity (arenaitem, 0.3); + + item = desktop->getItemAtPoint(p, true, item); + } + // Here we set the current item to the bottommost one so that the cycling step below re-starts at the top + sc->cycling_cur_item = g_list_last(sc->cycling_items); + sc->is_cycling = true; + } + + // Cycle through the items underneath the mouse pointer, one-by-one + sp_select_context_cycle_through_items(sc, selection, scroll_event, shift_pressed); + + ret = TRUE; + } + break; + } + case GDK_KEY_PRESS: // keybindings for select context { @@ -727,7 +822,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) sp_event_show_modifier_tip (event_context->defaultMessageContext(), event, _("Ctrl: click to select in groups; drag to move hor/vert"), _("Shift: click to toggle select; drag for rubberband selection"), - _("Alt: click to select under; drag to move selected or select by touch")); + _("Alt: click to select under; scroll mouse-wheel to cycle-select; drag to move selected or select by touch")); // if Alt and nonempty selection, show moving cursor ("move selected"): if (alt && !selection->isEmpty() && !desktop->isWaitingCursor()) { gdk_window_set_cursor(GTK_WIDGET(sp_desktop_canvas(desktop))->window, CursorSelectDragging); @@ -815,6 +910,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) selection->clear(); ret = TRUE; break; + case GDK_a: case GDK_A: if (MOD__CTRL_ONLY) { @@ -950,7 +1046,24 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) if (alt) { Inkscape::Rubberband::get(desktop)->setMode(RUBBERBAND_MODE_RECT); } + } else { + if (alt && sc->is_cycling) { + // quit cycle-selection and reset opacities + SPSelectContext *sc = SP_SELECT_CONTEXT(event_context); + NRArenaItem *arenaitem; + for (GList *l = sc->cycling_items; l != NULL; l = g_list_next(l)) { + arenaitem = SP_ITEM(l->data)->get_arenaitem(desktop->dkey); + nr_arena_item_set_opacity (arenaitem, 1.0); + } + g_list_free(sc->cycling_items); + g_list_free(sc->cycling_items_selected_before); + sc->cycling_items = NULL; + sc->cycling_items_selected_before = NULL; + sc->cycling_cur_item = NULL; + sc->is_cycling = false; + } } + } // set cursor to default. if (!desktop->isWaitingCursor()) { diff --git a/src/select-context.h b/src/select-context.h index 3f3f8bfb6..4c58fc858 100644 --- a/src/select-context.h +++ b/src/select-context.h @@ -37,6 +37,12 @@ struct SPSelectContext : public SPEventContext { bool button_press_shift; bool button_press_ctrl; bool button_press_alt; + + bool is_cycling; + GList *cycling_items; + GList *cycling_items_selected_before; + GList *cycling_cur_item; + SPItem *item; SPCanvasItem *grabbed; Inkscape::SelTrans *_seltrans; -- cgit v1.2.3 From 3cc158ecff4f2420590ab102d7f3a84d7ca2a711 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Thu, 23 Dec 2010 00:10:28 -0800 Subject: Split SPCanvasItem and SPCanvasGroup to individual .h files. Removed forward header. (bzr r9978.1.1) --- src/common-context.h | 1 - src/connector-context.cpp | 5 +- src/connector-context.h | 3 +- src/desktop-handles.cpp | 3 +- src/desktop-handles.h | 5 +- src/desktop.cpp | 1 + src/display/Makefile_insert | 3 +- src/display/canvas-arena.cpp | 3 - src/display/canvas-arena.h | 2 +- src/display/canvas-axonomgrid.cpp | 3 - src/display/canvas-bpath.cpp | 22 ++----- src/display/canvas-bpath.h | 9 ++- src/display/canvas-grid.cpp | 4 +- src/display/canvas-grid.h | 3 +- src/display/canvas-temporary-item-list.h | 3 +- src/display/canvas-temporary-item.h | 4 +- src/display/canvas-text.cpp | 1 - src/display/canvas-text.h | 13 ++-- src/display/display-forward.h | 52 --------------- src/display/gnome-canvas-acetate.cpp | 1 - src/display/gnome-canvas-acetate.h | 19 ++++-- src/display/guideline.cpp | 3 - src/display/guideline.h | 8 +-- src/display/nr-arena-glyphs.h | 27 +++++--- src/display/nr-arena-shape.cpp | 34 +++++----- src/display/nr-arena-shape.h | 1 - src/display/snap-indicator.h | 3 +- src/display/sodipodi-ctrl.cpp | 1 - src/display/sodipodi-ctrl.h | 5 +- src/display/sodipodi-ctrlrect.cpp | 1 - src/display/sodipodi-ctrlrect.h | 11 ++-- src/display/sp-canvas-group.h | 45 +++++++++++++ src/display/sp-canvas-item.h | 110 +++++++++++++++++++++++++++++++ src/display/sp-canvas-util.cpp | 3 +- src/display/sp-canvas.cpp | 8 +-- src/display/sp-canvas.h | 60 +++-------------- src/display/sp-ctrlline.cpp | 1 - src/display/sp-ctrlline.h | 8 +-- src/display/sp-ctrlpoint.cpp | 1 - src/display/sp-ctrlpoint.h | 10 +-- src/display/sp-ctrlquadr.cpp | 9 +-- src/draw-context.h | 1 - src/dropper-context.h | 1 - src/dyna-draw-context.cpp | 1 + src/eraser-context.cpp | 1 + src/gradient-drag.cpp | 1 + src/inkview.cpp | 3 +- src/interface.cpp | 25 ++++--- src/knot.h | 2 +- src/live_effects/effect.h | 2 +- src/pen-context.cpp | 1 + src/pencil-context.cpp | 1 + src/rubberband.cpp | 4 +- src/rubberband.h | 6 +- src/select-context.cpp | 3 + src/seltrans-handles.cpp | 2 - src/seltrans-handles.h | 20 +++++- src/sp-conn-end-pair.h | 2 + src/sp-guide.cpp | 1 + src/sp-guide.h | 4 +- src/sp-image.h | 1 - src/sp-lpe-item.h | 10 ++- src/sp-path.h | 7 +- src/sp-shape.h | 1 - src/spray-context.cpp | 2 +- src/spray-context.h | 1 - src/svg-view-widget.cpp | 26 ++++---- src/svg-view-widget.h | 41 +++++++----- src/svg-view.cpp | 1 - src/text-context.h | 1 - src/tweak-context.cpp | 2 +- src/tweak-context.h | 1 - src/ui/dialog/aboutbox.cpp | 2 +- src/ui/tool/control-point-selection.h | 2 +- src/ui/tool/control-point.cpp | 1 + src/ui/tool/control-point.h | 1 - src/ui/tool/multi-path-manipulator.h | 1 - src/ui/tool/node-tool.cpp | 1 + src/ui/tool/node-tool.h | 9 ++- src/ui/tool/path-manipulator.h | 2 +- src/ui/tool/selector.h | 1 - src/ui/tool/transform-handle-set.h | 3 +- src/ui/widget/ruler.cpp | 1 + src/ui/widget/svg-canvas.cpp | 2 +- src/widgets/desktop-widget.cpp | 1 + src/widgets/desktop-widget.h | 2 +- src/zoom-context.cpp | 3 +- 87 files changed, 405 insertions(+), 311 deletions(-) delete mode 100644 src/display/display-forward.h create mode 100644 src/display/sp-canvas-group.h create mode 100644 src/display/sp-canvas-item.h (limited to 'src') diff --git a/src/common-context.h b/src/common-context.h index 416307d58..74b6bbaef 100644 --- a/src/common-context.h +++ b/src/common-context.h @@ -21,7 +21,6 @@ #include "event-context.h" #include "display/curve.h" -#include "display/display-forward.h" #include <2geom/point.h> #define SP_TYPE_COMMON_CONTEXT (sp_common_context_get_type()) diff --git a/src/connector-context.cpp b/src/connector-context.cpp index b1061c124..f4b202451 100644 --- a/src/connector-context.cpp +++ b/src/connector-context.cpp @@ -1,12 +1,14 @@ -/* +/** * Connector creation tool * * Authors: * Michael Wybrow * Abhishek Sharma + * Jon A. Cruz * * Copyright (C) 2005-2008 Michael Wybrow * Copyright (C) 2009 Monash University + * Copyright (C) 2010 authors * * Released under GNU GPL, read the file 'COPYING' for more information * @@ -172,6 +174,7 @@ #include "inkscape.h" #include "preferences.h" #include "sp-path.h" +#include "display/sp-canvas.h" #include "display/canvas-bpath.h" #include "display/sodipodi-ctrl.h" #include diff --git a/src/connector-context.h b/src/connector-context.h index 036981f6f..b03d0fcf0 100644 --- a/src/connector-context.h +++ b/src/connector-context.h @@ -16,7 +16,6 @@ #include #include "event-context.h" #include -#include #include <2geom/point.h> #include "libavoid/connector.h" #include "connection-points.h" @@ -29,6 +28,8 @@ #define SP_IS_CONNECTOR_CONTEXT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE((k), SP_TYPE_CONNECTOR_CONTEXT)) struct SPKnot; +struct SPCurve; + namespace Inkscape { class Selection; diff --git a/src/desktop-handles.cpp b/src/desktop-handles.cpp index 481bf35ea..d35df6454 100644 --- a/src/desktop-handles.cpp +++ b/src/desktop-handles.cpp @@ -1,5 +1,3 @@ -#define __SP_DESKTOP_HANDLES_C__ - /* * Frontends * @@ -13,6 +11,7 @@ */ #include "display/sp-canvas.h" +#include "display/sp-canvas-item.h" #include "desktop.h" SPEventContext * diff --git a/src/desktop-handles.h b/src/desktop-handles.h index 61ea43d1e..74001d890 100644 --- a/src/desktop-handles.h +++ b/src/desktop-handles.h @@ -13,9 +13,12 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "display/display-forward.h" #include "forward.h" +struct SPCanvas; +struct SPCanvasItem; +struct SPCanvasGroup; + namespace Inkscape { class MessageStack; class Selection; diff --git a/src/desktop.cpp b/src/desktop.cpp index 0b17fb385..bfde0ee92 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -80,6 +80,7 @@ #include "display/sp-canvas-util.h" #include "display/canvas-temporary-item-list.h" #include "display/snap-indicator.h" +#include "display/sp-canvas-group.h" #include "ui/dialog/dialog-manager.h" #include "xml/repr.h" #include "message-context.h" diff --git a/src/display/Makefile_insert b/src/display/Makefile_insert index 58e667402..b50a71033 100644 --- a/src/display/Makefile_insert +++ b/src/display/Makefile_insert @@ -35,7 +35,6 @@ ink_common_sources += \ display/canvas-text.cpp \ display/curve.cpp \ display/curve.h \ - display/display-forward.h \ display/gnome-canvas-acetate.cpp \ display/gnome-canvas-acetate.h \ display/guideline.cpp \ @@ -53,6 +52,8 @@ ink_common_sources += \ display/sodipodi-ctrl.h \ display/sodipodi-ctrlrect.cpp \ display/sodipodi-ctrlrect.h \ + display/sp-canvas-group.h \ + display/sp-canvas-item.h \ display/sp-canvas-util.cpp \ display/sp-canvas-util.h \ display/sp-canvas.cpp \ diff --git a/src/display/canvas-arena.cpp b/src/display/canvas-arena.cpp index af9a38281..fb7ca9d78 100644 --- a/src/display/canvas-arena.cpp +++ b/src/display/canvas-arena.cpp @@ -1,5 +1,3 @@ -#define __SP_CANVAS_ARENA_C__ - /* * RGBA display list system for inkscape * @@ -15,7 +13,6 @@ #include #include -#include #include #include "helper/sp-marshal.h" #include diff --git a/src/display/canvas-arena.h b/src/display/canvas-arena.h index 34bc19946..7267583f0 100644 --- a/src/display/canvas-arena.h +++ b/src/display/canvas-arena.h @@ -13,7 +13,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "../display/sp-canvas.h" +#include "sp-canvas-item.h" #include "nr-arena-item.h" G_BEGIN_DECLS diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index 9dfde969d..550fd3559 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -1,5 +1,3 @@ -#define CANVAS_AXONOMGRID_C - /* * Copyright (C) 2006-2008 Johan Engelen */ @@ -21,7 +19,6 @@ #include "canvas-axonomgrid.h" #include "util/mathfns.h" #include "2geom/line.h" -#include "display-forward.h" #include #include "canvas-grid.h" diff --git a/src/display/canvas-bpath.cpp b/src/display/canvas-bpath.cpp index 063bdab66..f8a8ef22c 100644 --- a/src/display/canvas-bpath.cpp +++ b/src/display/canvas-bpath.cpp @@ -1,5 +1,3 @@ -#define __SP_CANVAS_BPATH_C__ - /* * Simple bezier bpath CanvasItem for inkscape * @@ -15,28 +13,20 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif +#include +#include +#include + #include "color.h" #include "sp-canvas-util.h" #include "inkscape-cairo.h" #include "canvas-bpath.h" -#include "display/display-forward.h" +#include "display/sp-canvas-group.h" #include "display/curve.h" #include "display/inkscape-cairo.h" -#include +#include "libnr/nr-pixops.h" #include "helper/geom.h" -#include -#include -#include - -/** -#ifdef HAVE_CONFIG_H -# include "config.h" -#endif -#include - -#include -**/ void nr_pixblock_render_bpath_rgba (Shape* theS,uint32_t color,NRRectL &area,char* destBuf,int stride); diff --git a/src/display/canvas-bpath.h b/src/display/canvas-bpath.h index 65ad4aa00..0760baef6 100644 --- a/src/display/canvas-bpath.h +++ b/src/display/canvas-bpath.h @@ -1,13 +1,15 @@ -#ifndef __SP_CANVAS_BPATH_H__ -#define __SP_CANVAS_BPATH_H__ +#ifndef SEEN_SP_CANVAS_BPATH_H +#define SEEN_SP_CANVAS_BPATH_H /* * Simple bezier bpath CanvasItem for inkscape * * Authors: * Lauris Kaplinski + * Jon A. Cruz * * Copyright (C) 2001 Lauris Kaplinski and Ximian, Inc. + * Copyright (C) 2010 authors * * Released under GNU GPL * @@ -15,10 +17,11 @@ #include -#include +#include "sp-canvas-item.h" struct SPCanvasBPath; struct SPCanvasBPathClass; +struct SPCanvasGroup; struct SPCurve; #define SP_TYPE_CANVAS_BPATH (sp_canvas_bpath_get_type ()) diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index df73eb78e..5892e1dc7 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -12,10 +12,10 @@ * Don't be shy to correct things. */ +#include "sp-canvas-group.h" #include "sp-canvas-util.h" #include "util/mathfns.h" -#include "display-forward.h" -#include +#include "libnr/nr-pixops.h" #include "desktop-handles.h" #include "helper/units.h" #include "svg/svg-color.h" diff --git a/src/display/canvas-grid.h b/src/display/canvas-grid.h index a11d77d1d..b8f313948 100644 --- a/src/display/canvas-grid.h +++ b/src/display/canvas-grid.h @@ -14,7 +14,7 @@ #include #include -#include "display/sp-canvas.h" +#include "sp-canvas-item.h" #include "xml/repr.h" #include "ui/widget/color-picker.h" #include "ui/widget/scalar-unit.h" @@ -26,6 +26,7 @@ struct SPDesktop; struct SPNamedView; +struct SPCanvasBuf; class SPDocument; namespace Inkscape { diff --git a/src/display/canvas-temporary-item-list.h b/src/display/canvas-temporary-item-list.h index 4d712e216..47556b9f1 100644 --- a/src/display/canvas-temporary-item-list.h +++ b/src/display/canvas-temporary-item-list.h @@ -13,9 +13,10 @@ */ #include "forward.h" -#include "display/display-forward.h" #include +struct SPCanvasItem; + namespace Inkscape { namespace Display { diff --git a/src/display/canvas-temporary-item.h b/src/display/canvas-temporary-item.h index 5077fb55b..692f9d85b 100644 --- a/src/display/canvas-temporary-item.h +++ b/src/display/canvas-temporary-item.h @@ -12,9 +12,11 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "display/display-forward.h" #include +#include + +struct SPCanvasItem; namespace Inkscape { namespace Display { diff --git a/src/display/canvas-text.cpp b/src/display/canvas-text.cpp index 94312bacb..e2bc09679 100644 --- a/src/display/canvas-text.cpp +++ b/src/display/canvas-text.cpp @@ -13,7 +13,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "display-forward.h" #include "sp-canvas-util.h" #include "canvas-text.h" #include "display/inkscape-cairo.h" diff --git a/src/display/canvas-text.h b/src/display/canvas-text.h index e5d634985..cc194ccc4 100644 --- a/src/display/canvas-text.h +++ b/src/display/canvas-text.h @@ -1,5 +1,5 @@ -#ifndef __SP_CANVASTEXT_H__ -#define __SP_CANVASTEXT_H__ +#ifndef SEEN_SP_CANVASTEXT_H +#define SEEN_SP_CANVASTEXT_H /* * Canvas text. @@ -14,10 +14,7 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -/* - * FIXME: The following code should actually be in a separate file called display/canvas-text.h. It - * temporarily had to be moved here because of linker errors. - */ +#include "sp-canvas-item.h" struct SPItem; struct SPDesktop; @@ -26,7 +23,7 @@ struct SPDesktop; #define SP_CANVASTEXT(obj) (GTK_CHECK_CAST ((obj), SP_TYPE_CANVASTEXT, SPCanvasText)) #define SP_IS_CANVASTEXT(obj) (GTK_CHECK_TYPE ((obj), SP_TYPE_CANVASTEXT)) -struct SPCanvasText : public SPCanvasItem{ +struct SPCanvasText : public SPCanvasItem { SPItem *item; // the item to which this line belongs in some sense; may be NULL for some users guint32 rgba; guint32 rgba_stroke; @@ -53,7 +50,7 @@ void sp_canvastext_set_number_as_text (SPCanvasText *ct, int num); void sp_canvastext_set_fontsize (SPCanvasText *ct, double size); void sp_canvastext_set_anchor (SPCanvasText *ct, double anchor_x, double anchor_y); -#endif +#endif // SEEN_SP_CANVASTEXT_H /* diff --git a/src/display/display-forward.h b/src/display/display-forward.h deleted file mode 100644 index 25c4a6e3d..000000000 --- a/src/display/display-forward.h +++ /dev/null @@ -1,52 +0,0 @@ -#ifndef SEEN_DISPLAY_DISPLAY_FORWARD_H -#define SEEN_DISPLAY_DISPLAY_FORWARD_H - -#include - -struct SPCanvas; -struct SPCanvasClass; -struct SPCanvasItem; -typedef struct _SPCanvasItemClass SPCanvasItemClass; -struct SPCanvasGroup; -struct SPCanvasGroupClass; -class SPCurve; - -namespace Inkscape { -namespace Display { - class TemporaryItem; - class TemporaryItemList; -} -} - -#define SP_TYPE_CANVAS_ITEM (sp_canvas_item_get_type()) -#define SP_CANVAS_ITEM(obj) (GTK_CHECK_CAST((obj), SP_TYPE_CANVAS_ITEM, SPCanvasItem)) -#define SP_IS_CANVAS_ITEM(obj) (GTK_CHECK_TYPE((obj), SP_TYPE_CANVAS_ITEM)) -#define SP_CANVAS_ITEM_GET_CLASS(o) (GTK_CHECK_GET_CLASS((o), SP_TYPE_CANVAS_ITEM, SPCanvasItemClass)) - -GType sp_canvas_item_get_type(); - -#define SP_TYPE_CANVAS_GROUP (sp_canvas_group_get_type()) -#define SP_CANVAS_GROUP(obj) (GTK_CHECK_CAST((obj), SP_TYPE_CANVAS_GROUP, SPCanvasGroup)) -#define SP_IS_CANVAS_GROUP(obj) (GTK_CHECK_TYPE((obj), SP_TYPE_CANVAS_GROUP)) - -GType sp_canvas_group_get_type(); - -#define SP_TYPE_CANVAS (sp_canvas_get_type()) -#define SP_CANVAS(obj) (GTK_CHECK_CAST((obj), SP_TYPE_CANVAS, SPCanvas)) -#define SP_IS_CANVAS(obj) (GTK_CHECK_TYPE((obj), SP_TYPE_CANVAS)) - -GType sp_canvas_get_type(); - - -#endif /* !SEEN_DISPLAY_DISPLAY_FORWARD_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/display/gnome-canvas-acetate.cpp b/src/display/gnome-canvas-acetate.cpp index fdb137e27..c257f1f92 100644 --- a/src/display/gnome-canvas-acetate.cpp +++ b/src/display/gnome-canvas-acetate.cpp @@ -14,7 +14,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "display-forward.h" #include "gnome-canvas-acetate.h" static void sp_canvas_acetate_class_init (SPCanvasAcetateClass *klass); diff --git a/src/display/gnome-canvas-acetate.h b/src/display/gnome-canvas-acetate.h index 40574e1bf..8c284291c 100644 --- a/src/display/gnome-canvas-acetate.h +++ b/src/display/gnome-canvas-acetate.h @@ -1,5 +1,5 @@ -#ifndef __SP_CANVAS_ACETATE_H__ -#define __SP_CANVAS_ACETATE_H__ +#ifndef SEEN_SP_CANVAS_ACETATE_H +#define SEEN_SP_CANVAS_ACETATE_H /* * Infinite invisible canvas item @@ -16,7 +16,7 @@ */ #include -#include "display/sp-canvas.h" +#include "display/sp-canvas-item.h" #define GNOME_TYPE_CANVAS_ACETATE (sp_canvas_acetate_get_type ()) @@ -38,4 +38,15 @@ GtkType sp_canvas_acetate_get_type (void); -#endif +#endif // SEEN_SP_CANVAS_ACETATE_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/display/guideline.cpp b/src/display/guideline.cpp index 0141692f2..ce1289faf 100644 --- a/src/display/guideline.cpp +++ b/src/display/guideline.cpp @@ -1,5 +1,3 @@ -#define __SP_GUIDELINE_C__ - /* * Horizontal/vertical but can also be angled line * @@ -18,7 +16,6 @@ #include #include <2geom/transforms.h> -#include "display-forward.h" #include "sp-canvas-util.h" #include "sp-ctrlpoint.h" #include "guideline.h" diff --git a/src/display/guideline.h b/src/display/guideline.h index a6ce57113..9654d04a1 100644 --- a/src/display/guideline.h +++ b/src/display/guideline.h @@ -1,5 +1,5 @@ -#ifndef __SP_GUIDELINE_H__ -#define __SP_GUIDELINE_H__ +#ifndef SEEN_SP_GUIDELINE_H +#define SEEN_SP_GUIDELINE_H /* * The visual representation of SPGuide. @@ -14,8 +14,8 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "sp-canvas.h" #include <2geom/point.h> +#include "sp-canvas-item.h" #define SP_TYPE_GUIDELINE (sp_guideline_get_type()) #define SP_GUIDELINE(o) (GTK_CHECK_CAST((o), SP_TYPE_GUIDELINE, SPGuideLine)) @@ -53,7 +53,7 @@ void sp_guideline_set_color(SPGuideLine *gl, unsigned int rgba); void sp_guideline_set_sensitive(SPGuideLine *gl, int sensitive); void sp_guideline_delete(SPGuideLine *gl); -#endif +#endif // SEEN_SP_GUIDELINE_H /* Local Variables: diff --git a/src/display/nr-arena-glyphs.h b/src/display/nr-arena-glyphs.h index 5bf94f3fc..1d15fef81 100644 --- a/src/display/nr-arena-glyphs.h +++ b/src/display/nr-arena-glyphs.h @@ -1,5 +1,5 @@ -#ifndef __NR_ARENA_GLYPHS_H__ -#define __NR_ARENA_GLYPHS_H__ +#ifndef SEEN_NR_ARENA_GLYPHS_H +#define SEEN_NR_ARENA_GLYPHS_H /* * RGBA display list system for inkscape @@ -17,15 +17,15 @@ #define NR_ARENA_GLYPHS(obj) (NR_CHECK_INSTANCE_CAST ((obj), NR_TYPE_ARENA_GLYPHS, NRArenaGlyphs)) #define NR_IS_ARENA_GLYPHS(obj) (NR_CHECK_INSTANCE_TYPE ((obj), NR_TYPE_ARENA_GLYPHS)) -#include +#include "libnrtype/nrtype-forward.h" -#include -#include -#include -#include +#include "forward.h" +#include "sp-paint-server.h" +#include "display/nr-arena-item.h" #define test_glyph_liv +struct SPCurve; class Shape; NRType nr_arena_glyphs_get_type (void); @@ -106,4 +106,15 @@ void nr_arena_glyphs_group_set_style (NRArenaGlyphsGroup *group, SPStyle *style) void nr_arena_glyphs_group_set_paintbox (NRArenaGlyphsGroup *group, const NRRect *pbox); -#endif +#endif // SEEN_NR_ARENA_GLYPHS_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/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp index 6aaf395b3..6f38fd97d 100644 --- a/src/display/nr-arena-shape.cpp +++ b/src/display/nr-arena-shape.cpp @@ -1,5 +1,3 @@ -#define __NR_ARENA_SHAPE_C__ - /* * RGBA display list system for inkscape * @@ -12,34 +10,36 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include +#include +#include +#include + #include <2geom/svg-path.h> #include <2geom/svg-path-parser.h> -#include -#include -#include -#include "display/curve.h" -#include -#include -#include #include <2geom/pathvector.h> #include <2geom/curves.h> -#include -#include -#include -#include +#include "display/sp-canvas.h" +#include "display/canvas-arena.h" +#include "display/nr-arena.h" +#include "display/nr-arena-shape.h" +#include "display/curve.h" +#include "libnr/nr-pixops.h" +#include "libnr/nr-blit.h" +#include "libnr/nr-convert2geom.h" +#include "livarot/Path.h" +#include "livarot/float-line.h" +#include "livarot/int-line.h" +#include "style.h" #include "inkscape-cairo.h" #include "helper/geom.h" #include "helper/geom-curves.h" #include "sp-filter.h" #include "sp-filter-reference.h" #include "display/nr-filter.h" -#include -#include #include "preferences.h" -#include #include "svg/svg.h" -#include //int showRuns=0; void nr_pixblock_render_shape_mask_or(NRPixBlock &m,Shape* theS); diff --git a/src/display/nr-arena-shape.h b/src/display/nr-arena-shape.h index 03505cfc2..d484615a9 100644 --- a/src/display/nr-arena-shape.h +++ b/src/display/nr-arena-shape.h @@ -17,7 +17,6 @@ #define NR_ARENA_SHAPE(obj) (NR_CHECK_INSTANCE_CAST ((obj), NR_TYPE_ARENA_SHAPE, NRArenaShape)) #define NR_IS_ARENA_SHAPE(obj) (NR_CHECK_INSTANCE_TYPE ((obj), NR_TYPE_ARENA_SHAPE)) -#include "display/display-forward.h" #include "display/canvas-bpath.h" #include "forward.h" #include "sp-paint-server.h" diff --git a/src/display/snap-indicator.h b/src/display/snap-indicator.h index 5475f9f60..d60ff1481 100644 --- a/src/display/snap-indicator.h +++ b/src/display/snap-indicator.h @@ -15,12 +15,13 @@ */ #include "forward.h" -#include "display/display-forward.h" #include "snapped-point.h" namespace Inkscape { namespace Display { +class TemporaryItem; + class SnapIndicator { public: SnapIndicator(SPDesktop *desktop); diff --git a/src/display/sodipodi-ctrl.cpp b/src/display/sodipodi-ctrl.cpp index 6084ff898..a63f570cf 100644 --- a/src/display/sodipodi-ctrl.cpp +++ b/src/display/sodipodi-ctrl.cpp @@ -10,7 +10,6 @@ #include <2geom/transforms.h> #include "sp-canvas-util.h" -#include "display-forward.h" #include "sodipodi-ctrl.h" #include "libnr/nr-pixops.h" diff --git a/src/display/sodipodi-ctrl.h b/src/display/sodipodi-ctrl.h index 945d94807..a708ad41b 100644 --- a/src/display/sodipodi-ctrl.h +++ b/src/display/sodipodi-ctrl.h @@ -8,10 +8,9 @@ */ #include -#include "sp-canvas.h" #include #include - +#include "sp-canvas-item.h" #define SP_TYPE_CTRL (sp_ctrl_get_type ()) @@ -35,7 +34,7 @@ typedef enum { SP_CTRL_MODE_XOR } SPCtrlModeType; -struct SPCtrl : public SPCanvasItem{ +struct SPCtrl : public SPCanvasItem { SPCtrlShapeType shape; SPCtrlModeType mode; GtkAnchorType anchor; diff --git a/src/display/sodipodi-ctrlrect.cpp b/src/display/sodipodi-ctrlrect.cpp index 46d83c208..6d9c40858 100644 --- a/src/display/sodipodi-ctrlrect.cpp +++ b/src/display/sodipodi-ctrlrect.cpp @@ -15,7 +15,6 @@ * */ -#include "display-forward.h" #include "sp-canvas-util.h" #include "sodipodi-ctrlrect.h" #include "libnr/nr-pixops.h" diff --git a/src/display/sodipodi-ctrlrect.h b/src/display/sodipodi-ctrlrect.h index 70dcf1f30..9ecba47c8 100644 --- a/src/display/sodipodi-ctrlrect.h +++ b/src/display/sodipodi-ctrlrect.h @@ -1,5 +1,5 @@ -#ifndef __INKSCAPE_CTRLRECT_H__ -#define __INKSCAPE_CTRLRECT_H__ +#ifndef SEEN_INKSCAPE_CTRLRECT_H +#define SEEN_INKSCAPE_CTRLRECT_H /** * \file sodipodi-ctrlrect.h @@ -17,7 +17,10 @@ */ #include -#include "sp-canvas.h" +#include "sp-canvas-item.h" +#include "libnr/nr-rect-l.h" + +struct SPCanvasBuf; #define SP_TYPE_CTRLRECT (sp_ctrlrect_get_type ()) #define SP_CTRLRECT(obj) (GTK_CHECK_CAST((obj), SP_TYPE_CTRLRECT, CtrlRect)) @@ -56,7 +59,7 @@ struct SPCtrlRectClass : public SPCanvasItemClass {}; GtkType sp_ctrlrect_get_type(); -#endif +#endif // SEEN_RUBBERBAND_H /* Local Variables: diff --git a/src/display/sp-canvas-group.h b/src/display/sp-canvas-group.h new file mode 100644 index 000000000..10bf0fa6c --- /dev/null +++ b/src/display/sp-canvas-group.h @@ -0,0 +1,45 @@ +#ifndef SEEN_SP_CANVAS_GROUP_H +#define SEEN_SP_CANVAS_GROUP_H + +/** \file + * SPCanvasGroup + * + * Authors: + * Federico Mena + * Raph Levien + * Lauris Kaplinski + * Jon A. Cruz + * + * Copyright (C) 1998 The Free Software Foundation + * Copyright (C) 2002 Lauris Kaplinski + * Copyright (C) 2010 authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include + +#define SP_TYPE_CANVAS_GROUP (sp_canvas_group_get_type()) +#define SP_CANVAS_GROUP(obj) (GTK_CHECK_CAST((obj), SP_TYPE_CANVAS_GROUP, SPCanvasGroup)) +#define SP_IS_CANVAS_GROUP(obj) (GTK_CHECK_TYPE((obj), SP_TYPE_CANVAS_GROUP)) + +GType sp_canvas_group_get_type(); + + + +#endif // SEEN_SP_CANVAS_GROUP_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/display/sp-canvas-item.h b/src/display/sp-canvas-item.h new file mode 100644 index 000000000..1ae2ff2d1 --- /dev/null +++ b/src/display/sp-canvas-item.h @@ -0,0 +1,110 @@ +#ifndef SEEN_SP_CANVAS_ITEM_H +#define SEEN_SP_CANVAS_ITEM_H + +/** \file + * SPCanvasItem. + * + * Authors: + * Federico Mena + * Raph Levien + * Lauris Kaplinski + * Jon A. Cruz + * + * Copyright (C) 1998 The Free Software Foundation + * Copyright (C) 2002 Lauris Kaplinski + * Copyright (C) 2010 authors + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include +#include +#include + +#include "2geom/rect.h" + +G_BEGIN_DECLS + +struct SPCanvas; +struct SPCanvasBuf; +struct SPCanvasGroup; + +typedef struct _SPCanvasItemClass SPCanvasItemClass; + +#define SP_TYPE_CANVAS_ITEM (sp_canvas_item_get_type()) +#define SP_CANVAS_ITEM(obj) (GTK_CHECK_CAST((obj), SP_TYPE_CANVAS_ITEM, SPCanvasItem)) +#define SP_IS_CANVAS_ITEM(obj) (GTK_CHECK_TYPE((obj), SP_TYPE_CANVAS_ITEM)) +#define SP_CANVAS_ITEM_GET_CLASS(o) (GTK_CHECK_GET_CLASS((o), SP_TYPE_CANVAS_ITEM, SPCanvasItemClass)) + +GType sp_canvas_item_get_type(); + +/** + * An SPCanvasItem refers to a SPCanvas and to its parent item; it has + * four coordinates, a bounding rectangle, and a transformation matrix. + */ +struct SPCanvasItem : public GtkObject { + SPCanvas *canvas; + SPCanvasItem *parent; + + double x1, y1, x2, y2; + Geom::Rect bounds; + Geom::Matrix xform; +}; + +/** + * The vtable of an SPCanvasItem. + */ +struct _SPCanvasItemClass : public GtkObjectClass { + void (* update) (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); + + void (* render) (SPCanvasItem *item, SPCanvasBuf *buf); + double (* point) (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item); + + int (* event) (SPCanvasItem *item, GdkEvent *event); +}; + +SPCanvasItem *sp_canvas_item_new(SPCanvasGroup *parent, GtkType type, const gchar *first_arg_name, ...); + +G_END_DECLS + + +#define sp_canvas_item_set gtk_object_set + +void sp_canvas_item_affine_absolute(SPCanvasItem *item, Geom::Matrix const &aff); + +void sp_canvas_item_raise(SPCanvasItem *item, int positions); +void sp_canvas_item_lower(SPCanvasItem *item, int positions); +bool sp_canvas_item_is_visible(SPCanvasItem *item); +void sp_canvas_item_show(SPCanvasItem *item); +void sp_canvas_item_hide(SPCanvasItem *item); +int sp_canvas_item_grab(SPCanvasItem *item, unsigned int event_mask, GdkCursor *cursor, guint32 etime); +void sp_canvas_item_ungrab(SPCanvasItem *item, guint32 etime); + +Geom::Matrix sp_canvas_item_i2w_affine(SPCanvasItem const *item); + +void sp_canvas_item_grab_focus(SPCanvasItem *item); + +void sp_canvas_item_request_update(SPCanvasItem *item); + +/* get item z-order in parent group */ + +gint sp_canvas_item_order(SPCanvasItem * item); + + + +#endif // SEEN_SP_CANVAS_ITEM_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/display/sp-canvas-util.cpp b/src/display/sp-canvas-util.cpp index a06d93074..af80eed44 100644 --- a/src/display/sp-canvas-util.cpp +++ b/src/display/sp-canvas-util.cpp @@ -13,10 +13,11 @@ */ +#include // for memset #include <2geom/matrix.h> #include "libnr/nr-pixops.h" +#include "sp-canvas-item.h" #include "sp-canvas-util.h" -#include /* for memset */ void diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index 2319f82f6..fc68bcfc0 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -1,5 +1,3 @@ -#define __SP_CANVAS_C__ - /** \file * Port of GnomeCanvas for Inkscape needs * @@ -30,10 +28,10 @@ #include "helper/sp-marshal.h" #include -#include -#include "display-forward.h" +#include "display/sp-canvas.h" +#include "display/sp-canvas-group.h" #include <2geom/matrix.h> -#include +#include "libnr/nr-convex-hull.h" #include "preferences.h" #include "inkscape.h" #include "sodipodi-ctrlrect.h" diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index 5cd201618..9c8b19982 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -2,7 +2,7 @@ #define SEEN_SP_CANVAS_H /** \file - * SPCanvas, SPCanvasBuf, and SPCanvasItem. + * SPCanvas, SPCanvasBuf. * * Authors: * Federico Mena @@ -42,9 +42,15 @@ G_BEGIN_DECLS +#define SP_TYPE_CANVAS sp_canvas_get_type() +#define SP_CANVAS(obj) (GTK_CHECK_CAST((obj), SP_TYPE_CANVAS, SPCanvas)) +#define SP_IS_CANVAS(obj) (GTK_CHECK_TYPE((obj), SP_TYPE_CANVAS)) + +GType sp_canvas_get_type(); + struct SPCanvas; +struct SPCanvasItem; struct SPCanvasGroup; -typedef struct _SPCanvasItemClass SPCanvasItemClass; enum { SP_CANVAS_UPDATE_REQUESTED = 1 << 0, @@ -66,58 +72,8 @@ struct SPCanvasBuf{ cairo_t *ct; }; -/** - * An SPCanvasItem refers to a SPCanvas and to its parent item; it has - * four coordinates, a bounding rectangle, and a transformation matrix. - */ -struct SPCanvasItem : public GtkObject { - SPCanvas *canvas; - SPCanvasItem *parent; - - double x1, y1, x2, y2; - Geom::Rect bounds; - Geom::Matrix xform; -}; - -/** - * The vtable of an SPCanvasItem. - */ -struct _SPCanvasItemClass : public GtkObjectClass { - void (* update) (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); - - void (* render) (SPCanvasItem *item, SPCanvasBuf *buf); - double (* point) (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item); - - int (* event) (SPCanvasItem *item, GdkEvent *event); -}; - -SPCanvasItem *sp_canvas_item_new(SPCanvasGroup *parent, GtkType type, const gchar *first_arg_name, ...); - G_END_DECLS -#define sp_canvas_item_set gtk_object_set - -void sp_canvas_item_affine_absolute(SPCanvasItem *item, Geom::Matrix const &aff); - -void sp_canvas_item_raise(SPCanvasItem *item, int positions); -void sp_canvas_item_lower(SPCanvasItem *item, int positions); -bool sp_canvas_item_is_visible(SPCanvasItem *item); -void sp_canvas_item_show(SPCanvasItem *item); -void sp_canvas_item_hide(SPCanvasItem *item); -int sp_canvas_item_grab(SPCanvasItem *item, unsigned int event_mask, GdkCursor *cursor, guint32 etime); -void sp_canvas_item_ungrab(SPCanvasItem *item, guint32 etime); - -Geom::Matrix sp_canvas_item_i2w_affine(SPCanvasItem const *item); - -void sp_canvas_item_grab_focus(SPCanvasItem *item); - -void sp_canvas_item_request_update(SPCanvasItem *item); - -/* get item z-order in parent group */ - -gint sp_canvas_item_order(SPCanvasItem * item); - - // SPCanvas ------------------------------------------------- /** * Port of GnomeCanvas for inkscape needs. diff --git a/src/display/sp-ctrlline.cpp b/src/display/sp-ctrlline.cpp index d8a622d90..0ef23812e 100644 --- a/src/display/sp-ctrlline.cpp +++ b/src/display/sp-ctrlline.cpp @@ -19,7 +19,6 @@ * */ -#include "display-forward.h" #include "sp-canvas-util.h" #include "sp-ctrlline.h" diff --git a/src/display/sp-ctrlline.h b/src/display/sp-ctrlline.h index 64497c464..a13907a70 100644 --- a/src/display/sp-ctrlline.h +++ b/src/display/sp-ctrlline.h @@ -1,5 +1,5 @@ -#ifndef __INKSCAPE_CTRLLINE_H__ -#define __INKSCAPE_CTRLLINE_H__ +#ifndef SEEN_INKSCAPE_CTRLLINE_H +#define SEEN_INKSCAPE_CTRLLINE_H /* * Simple straight line @@ -14,7 +14,7 @@ * Released under GNU GPL */ -#include "sp-canvas.h" +#include "sp-canvas-item.h" struct SPItem; @@ -38,7 +38,7 @@ void sp_ctrlline_set_coords (SPCtrlLine *cl, const Geom::Point start, const Geom -#endif +#endif // SEEN_INKSCAPE_CTRLLINE_H /* Local Variables: diff --git a/src/display/sp-ctrlpoint.cpp b/src/display/sp-ctrlpoint.cpp index 1f8c145a8..ba40192a9 100644 --- a/src/display/sp-ctrlpoint.cpp +++ b/src/display/sp-ctrlpoint.cpp @@ -11,7 +11,6 @@ * Released under GNU GPL */ -#include "display-forward.h" #include "sp-canvas-util.h" #include "sp-ctrlpoint.h" diff --git a/src/display/sp-ctrlpoint.h b/src/display/sp-ctrlpoint.h index d0e72f518..1b7b7ba1e 100644 --- a/src/display/sp-ctrlpoint.h +++ b/src/display/sp-ctrlpoint.h @@ -1,5 +1,5 @@ -#ifndef __INKSCAPE_CTRLPOINT_H__ -#define __INKSCAPE_CTRLPOINT_H__ +#ifndef SEEN_INKSCAPE_CTRLPOINT_H +#define SEEN_INKSCAPE_CTRLPOINT_H /* * A simple point @@ -12,7 +12,7 @@ * Released under GNU GPL */ -#include "sp-canvas.h" +#include "sp-canvas-item.h" struct SPItem; @@ -20,7 +20,7 @@ struct SPItem; #define SP_CTRLPOINT(obj) (GTK_CHECK_CAST ((obj), SP_TYPE_CTRLPOINT, SPCtrlPoint)) #define SP_IS_CTRLPOINT(obj) (GTK_CHECK_TYPE ((obj), SP_TYPE_CTRLPOINT)) -struct SPCtrlPoint : public SPCanvasItem{ +struct SPCtrlPoint : public SPCanvasItem { SPItem *item; // the item to which this line belongs in some sense; may be NULL for some users guint32 rgba; Geom::Point pt; @@ -38,7 +38,7 @@ void sp_ctrlpoint_set_radius (SPCtrlPoint *cp, const double r); -#endif +#endif // SEEN_INKSCAPE_CTRLPOINT_H /* Local Variables: diff --git a/src/display/sp-ctrlquadr.cpp b/src/display/sp-ctrlquadr.cpp index 54b9bc3e1..c29aecb96 100644 --- a/src/display/sp-ctrlquadr.cpp +++ b/src/display/sp-ctrlquadr.cpp @@ -1,5 +1,3 @@ -#define __INKSCAPE_CTRLQUADR_C__ - /* * Quadrilateral * @@ -11,13 +9,12 @@ * Released under GNU GPL */ -#include "display-forward.h" -#include "sp-canvas-util.h" -#include "sp-ctrlquadr.h" - #ifdef HAVE_CONFIG_H # include "config.h" #endif +#include "sp-canvas-util.h" +#include "sp-canvas-item.h" +#include "sp-ctrlquadr.h" #include "display/inkscape-cairo.h" #include "color.h" diff --git a/src/draw-context.h b/src/draw-context.h index 1364b5dad..2827714cb 100644 --- a/src/draw-context.h +++ b/src/draw-context.h @@ -17,7 +17,6 @@ #include #include "event-context.h" #include -#include #include #include "live_effects/effect.h" diff --git a/src/dropper-context.h b/src/dropper-context.h index 6f8b60b34..f2d18a507 100644 --- a/src/dropper-context.h +++ b/src/dropper-context.h @@ -12,7 +12,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "display/display-forward.h" #include "event-context.h" #define SP_TYPE_DROPPER_CONTEXT (sp_dropper_context_get_type ()) diff --git a/src/dyna-draw-context.cpp b/src/dyna-draw-context.cpp index 93d4262cd..7d0c7ee91 100644 --- a/src/dyna-draw-context.cpp +++ b/src/dyna-draw-context.cpp @@ -58,6 +58,7 @@ #include "sp-shape.h" #include "sp-path.h" #include "sp-text.h" +#include "display/sp-canvas.h" #include "display/canvas-bpath.h" #include "display/canvas-arena.h" #include "livarot/Shape.h" diff --git a/src/eraser-context.cpp b/src/eraser-context.cpp index 68c0989bc..8ac765b9e 100644 --- a/src/eraser-context.cpp +++ b/src/eraser-context.cpp @@ -34,6 +34,7 @@ #include #include "svg/svg.h" +#include "display/sp-canvas.h" #include "display/canvas-bpath.h" #include <2geom/bezier-utils.h> diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index 2e9a21acf..fe8297286 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -25,6 +25,7 @@ #include "selection.h" #include "desktop.h" #include "desktop-style.h" +#include "desktop-handles.h" #include "document.h" #include "display/sp-ctrlline.h" #include "display/sp-canvas-util.h" diff --git a/src/inkview.cpp b/src/inkview.cpp index 09adb8c2d..448aa77f1 100644 --- a/src/inkview.cpp +++ b/src/inkview.cpp @@ -325,8 +325,7 @@ main (int argc, const char **argv) (ss.doc)->ensureUpToDate(); ss.view = sp_svg_view_widget_new (ss.doc); (ss.doc)->doUnref (); - sp_svg_view_widget_set_resize (SP_SVG_VIEW_WIDGET (ss.view), FALSE, - (ss.doc)->getWidth (), (ss.doc)->getHeight ()); + SP_SVG_VIEW_WIDGET(ss.view)->setResize( false, ss.doc->getWidth(), ss.doc->getHeight() ); gtk_widget_show (ss.view); gtk_container_add (GTK_CONTAINER (w), ss.view); diff --git a/src/interface.cpp b/src/interface.cpp index 0fd2b65ea..551e2bf91 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -8,6 +8,7 @@ * Jon A. Cruz * Abhishek Sharma * + * Copyright (C) 2010 authors * Copyright (C) 1999-2005 authors * Copyright (C) 2001-2002 Ximian, Inc. * Copyright (C) 2004 David Turner @@ -272,7 +273,9 @@ sp_create_window(SPViewWidget *vw, gboolean editable) win->show(); // needed because the first ACTIVATE_DESKTOP was sent when there was no window yet - inkscape_reactivate_desktop(SP_DESKTOP_WIDGET(vw)->desktop); + if ( SP_IS_DESKTOP_WIDGET(vw) ) { + inkscape_reactivate_desktop(SP_DESKTOP_WIDGET(vw)->desktop); + } } void @@ -294,20 +297,16 @@ sp_ui_new_view() /* TODO: not yet working */ /* To be re-enabled (by adding to menu) once it works. */ -void -sp_ui_new_view_preview() +void sp_ui_new_view_preview() { - SPDocument *document; - SPViewWidget *dtw; - - document = SP_ACTIVE_DOCUMENT; - if (!document) return; + SPDocument *document = SP_ACTIVE_DOCUMENT; + if ( document ) { + SPViewWidget *dtw = reinterpret_cast(sp_svg_view_widget_new(document)); + g_return_if_fail(dtw != NULL); + SP_SVG_VIEW_WIDGET(dtw)->setResize(true, 400.0, 400.0); - dtw = (SPViewWidget *) sp_svg_view_widget_new(document); - g_return_if_fail(dtw != NULL); - sp_svg_view_widget_set_resize(SP_SVG_VIEW_WIDGET(dtw), TRUE, 400.0, 400.0); - - sp_create_window(dtw, FALSE); + sp_create_window(dtw, FALSE); + } } /** diff --git a/src/knot.h b/src/knot.h index 32035d603..24a86282e 100644 --- a/src/knot.h +++ b/src/knot.h @@ -16,7 +16,6 @@ #include #include -#include "display/display-forward.h" #include "forward.h" #include <2geom/point.h> #include "knot-enums.h" @@ -24,6 +23,7 @@ class SPKnot; class SPKnotClass; +struct SPCanvasItem; #define SP_TYPE_KNOT (sp_knot_get_type()) #define SP_KNOT(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_KNOT, SPKnot)) diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h index 681bae387..6acba000c 100644 --- a/src/live_effects/effect.h +++ b/src/live_effects/effect.h @@ -10,7 +10,6 @@ */ -#include "display/display-forward.h" #include #include #include <2geom/forward.h> @@ -29,6 +28,7 @@ class SPLPEItem; class KnotHolder; class KnotHolderEntity; class SPPath; +struct SPCurve; namespace Gtk { class Widget; diff --git a/src/pen-context.cpp b/src/pen-context.cpp index 6778d4bcc..607bdaedc 100644 --- a/src/pen-context.cpp +++ b/src/pen-context.cpp @@ -31,6 +31,7 @@ #include "message-context.h" #include "preferences.h" #include "sp-path.h" +#include "display/sp-canvas.h" #include "display/curve.h" #include "pixmaps/cursor-pen.xpm" #include "display/canvas-bpath.h" diff --git a/src/pencil-context.cpp b/src/pencil-context.cpp index 0717724de..a873eb6fc 100644 --- a/src/pencil-context.cpp +++ b/src/pencil-context.cpp @@ -41,6 +41,7 @@ #include "document.h" #include "desktop-style.h" #include "macros.h" +#include "display/sp-canvas.h" #include "display/curve.h" #include "livarot/Path.h" diff --git a/src/rubberband.cpp b/src/rubberband.cpp index 17e7102f8..398f01d3e 100644 --- a/src/rubberband.cpp +++ b/src/rubberband.cpp @@ -1,5 +1,3 @@ -#define __RUBBERBAND_C__ - /** * \file src/rubberband.cpp * \brief Rubberbanding selector @@ -16,6 +14,8 @@ #include "desktop.h" #include "desktop-handles.h" #include "rubberband.h" +#include "display/sp-canvas.h" +#include "display/sp-canvas-item.h" #include "display/canvas-bpath.h" #include "display/curve.h" diff --git a/src/rubberband.h b/src/rubberband.h index 57e4ea2a3..6c857fb63 100644 --- a/src/rubberband.h +++ b/src/rubberband.h @@ -1,5 +1,5 @@ -#ifndef __RUBBERBAND_H__ -#define __RUBBERBAND_H__ +#ifndef SEEN_RUBBERBAND_H +#define SEEN_RUBBERBAND_H /** * \file src/rubberband.h @@ -74,7 +74,7 @@ private: } -#endif +#endif // SEEN_RUBBERBAND_H /* Local Variables: diff --git a/src/select-context.cpp b/src/select-context.cpp index 96758a9f1..4a8b38c37 100644 --- a/src/select-context.cpp +++ b/src/select-context.cpp @@ -5,7 +5,9 @@ * Lauris Kaplinski * bulia byak * Abhishek Sharma + * Jon A. Cruz * + * Copyright (C) 2010 authors * Copyright (C) 2006 Johan Engelen * Copyright (C) 1999-2005 Authors * @@ -40,6 +42,7 @@ #include "selection-describer.h" #include "seltrans.h" #include "box3d.h" +#include "display/sp-canvas.h" #include "display/nr-arena-item.h" using Inkscape::DocumentUndo; diff --git a/src/seltrans-handles.cpp b/src/seltrans-handles.cpp index d3197a062..10b87aaff 100644 --- a/src/seltrans-handles.cpp +++ b/src/seltrans-handles.cpp @@ -1,5 +1,3 @@ -#define SP_SELTRANS_HANDLES_C - #include "seltrans-handles.h" diff --git a/src/seltrans-handles.h b/src/seltrans-handles.h index 4a0dd0bf7..f796a1007 100644 --- a/src/seltrans-handles.h +++ b/src/seltrans-handles.h @@ -1,5 +1,5 @@ -#ifndef __SP_SELTRANS_HANDLES_H__ -#define __SP_SELTRANS_HANDLES_H__ +#ifndef SEEN_SP_SELTRANS_HANDLES_H +#define SEEN_SP_SELTRANS_HANDLES_H /* * Seltrans knots @@ -14,6 +14,7 @@ #include "display/sodipodi-ctrl.h" #include <2geom/forward.h> +#include namespace Inkscape { @@ -50,9 +51,22 @@ struct SPSelTransHandle { gdouble x, y; }; +// TODO these must be purged: extern SPSelTransHandle const handles_scale[8]; extern SPSelTransHandle const handles_rotate[8]; extern SPSelTransHandle const handle_center; -#endif +#endif // SEEN_SP_SELTRANS_HANDLES_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/sp-conn-end-pair.h b/src/sp-conn-end-pair.h index 3b011ed17..fa585d618 100644 --- a/src/sp-conn-end-pair.h +++ b/src/sp-conn-end-pair.h @@ -22,6 +22,8 @@ class SPConnEnd; +struct SPCurve; + namespace Inkscape { namespace XML { class Node; diff --git a/src/sp-guide.cpp b/src/sp-guide.cpp index f92d79116..a0186a37d 100644 --- a/src/sp-guide.cpp +++ b/src/sp-guide.cpp @@ -23,6 +23,7 @@ #include #include #include "desktop-handles.h" +#include "display/sp-canvas.h" #include "display/guideline.h" #include "svg/svg.h" #include "svg/stringstream.h" diff --git a/src/sp-guide.h b/src/sp-guide.h index 4fc4032db..f9f67f301 100644 --- a/src/sp-guide.h +++ b/src/sp-guide.h @@ -15,11 +15,13 @@ #include -#include "display/display-forward.h" #include <2geom/point.h> #include "sp-object.h" #include "sp-guide-attachment.h" +struct SPCanvas; +struct SPCanvasGroup; + #define SP_TYPE_GUIDE (sp_guide_get_type()) #define SP_GUIDE(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), SP_TYPE_GUIDE, SPGuide)) #define SP_GUIDE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), SP_TYPE_GUIDE, SPGuideClass)) diff --git a/src/sp-image.h b/src/sp-image.h index 172cd7118..9618c9873 100644 --- a/src/sp-image.h +++ b/src/sp-image.h @@ -29,7 +29,6 @@ class SPImageClass; #include #include "svg/svg-length.h" #include "sp-item.h" -#include "display/display-forward.h" #define SP_IMAGE_HREF_MODIFIED_FLAG SP_OBJECT_USER_MODIFIED_FLAG_A diff --git a/src/sp-lpe-item.h b/src/sp-lpe-item.h index 1af7f2797..d1baa4309 100644 --- a/src/sp-lpe-item.h +++ b/src/sp-lpe-item.h @@ -15,7 +15,6 @@ */ #include "sp-item.h" -#include "display/display-forward.h" #include @@ -26,12 +25,17 @@ #define SP_IS_LPE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), SP_TYPE_LPE_ITEM)) struct LivePathEffectObject; +struct SPCurve; + namespace Inkscape{ +namespace Display { + class TemporaryItem; +} namespace LivePathEffect{ class LPEObjectReference; class Effect; -}; -}; +} +} typedef std::list PathEffectList; diff --git a/src/sp-path.h b/src/sp-path.h index bf294c37c..5cfa34913 100644 --- a/src/sp-path.h +++ b/src/sp-path.h @@ -1,5 +1,5 @@ -#ifndef __SP_PATH_H__ -#define __SP_PATH_H__ +#ifndef SEEN_SP_PATH_H +#define SEEN_SP_PATH_H /* * SVG implementation @@ -16,6 +16,7 @@ #include "sp-shape.h" #include "sp-conn-end-pair.h" +struct SPCurve; #define SP_TYPE_PATH (sp_path_get_type ()) #define SP_PATH(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), SP_TYPE_PATH, SPPath)) @@ -39,7 +40,7 @@ SPCurve* sp_path_get_original_curve (SPPath *path); SPCurve* sp_path_get_curve_for_edit (SPPath *path); const SPCurve* sp_path_get_curve_reference (SPPath *path); -#endif +#endif // SEEN_SP_PATH_H /* Local Variables: diff --git a/src/sp-shape.h b/src/sp-shape.h index 78855c1c7..493268711 100644 --- a/src/sp-shape.h +++ b/src/sp-shape.h @@ -16,7 +16,6 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "display/display-forward.h" #include "sp-lpe-item.h" #include "sp-marker-loc.h" #include <2geom/forward.h> diff --git a/src/spray-context.cpp b/src/spray-context.cpp index 0cf74f59b..6d19cbce4 100644 --- a/src/spray-context.cpp +++ b/src/spray-context.cpp @@ -27,7 +27,6 @@ #include #include "svg/svg.h" -#include "display/canvas-bpath.h" #include #include "macros.h" @@ -62,6 +61,7 @@ #include "gradient-chemistry.h" #include "sp-text.h" #include "sp-flowtext.h" +#include "display/sp-canvas.h" #include "display/canvas-bpath.h" #include "display/canvas-arena.h" #include "display/curve.h" diff --git a/src/spray-context.h b/src/spray-context.h index b559fa593..edb872117 100644 --- a/src/spray-context.h +++ b/src/spray-context.h @@ -19,7 +19,6 @@ */ #include "event-context.h" -#include #include //#include "ui/widget/spray-option.h" #include "ui/dialog/dialog.h" diff --git a/src/svg-view-widget.cpp b/src/svg-view-widget.cpp index d2a31966a..777c1b496 100644 --- a/src/svg-view-widget.cpp +++ b/src/svg-view-widget.cpp @@ -5,7 +5,9 @@ * Lauris Kaplinski * Ralf Stephan * Abhishek Sharma + * Jon A. Cruz * + * Copyright (C) 2010 authors * Copyright (C) 2001-2002 Lauris Kaplinski * Copyright (C) 2001 Ximian, Inc. * @@ -13,6 +15,8 @@ */ #include +#include "display/sp-canvas.h" +#include "display/sp-canvas-group.h" #include "display/canvas-arena.h" #include "document.h" #include "svg-view.h" @@ -220,22 +224,18 @@ sp_svg_view_widget_new (SPDocument *doc) /** * Flags the SPSVGSPViewWidget to have its size renegotiated with Gtk. */ -void -sp_svg_view_widget_set_resize (SPSVGSPViewWidget *vw, bool resize, gdouble width, gdouble height) +void SPSVGSPViewWidget::setResize(bool resize, gdouble width, gdouble height) { - g_return_if_fail (vw != NULL); + g_return_if_fail( !resize || (width > 0.0) ); + g_return_if_fail( !resize || (height > 0.0) ); - g_return_if_fail (SP_IS_SVG_VIEW_WIDGET (vw)); - g_return_if_fail (!resize || (width > 0.0)); - g_return_if_fail (!resize || (height > 0.0)); + this->resize = resize; + this->maxwidth = width; + this->maxheight = height; - vw->resize = resize; - vw->maxwidth = width; - vw->maxheight = height; - - if (resize) { - gtk_widget_queue_resize (GTK_WIDGET (vw)); - } + if ( resize ) { + gtk_widget_queue_resize( GTK_WIDGET(this) ); + } } diff --git a/src/svg-view-widget.h b/src/svg-view-widget.h index cd609b07a..e732841c7 100644 --- a/src/svg-view-widget.h +++ b/src/svg-view-widget.h @@ -1,19 +1,20 @@ -#ifndef __SP_SVG_VIEW_WIDGET_H__ -#define __SP_SVG_VIEW_WIDGET_H__ +#ifndef SEEN_SP_SVG_VIEW_WIDGET_H +#define SEEN_SP_SVG_VIEW_WIDGET_H /** \file * SPSVGView, SPSVGSPViewWidget: Generic SVG view and widget * * Authors: * Lauris Kaplinski + * Jon A. Cruz * + * Copyright (C) 2010 Authors * Copyright (C) 2001-2002 Lauris Kaplinski * Copyright (C) 2001 Ximian, Inc. * * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "display/display-forward.h" #include "ui/view/view-widget.h" class SPDocument; @@ -30,33 +31,39 @@ GtkType sp_svg_view_widget_get_type (void); GtkWidget *sp_svg_view_widget_new (SPDocument *doc); -void sp_svg_view_widget_set_resize (SPSVGSPViewWidget *vw, bool resize, gdouble width, gdouble height); - /** * An SPSVGSPViewWidget is an SVG view together with a canvas. */ struct SPSVGSPViewWidget { - public: - SPViewWidget widget; +public: + SPViewWidget widget; - GtkWidget *sw; - GtkWidget *canvas; + GtkWidget *sw; + GtkWidget *canvas; - /// Whether to resize automatically - bool resize; - gdouble maxwidth, maxheight; + /// Whether to resize automatically + bool resize; + gdouble maxwidth, maxheight; // C++ Wrappers /// Flags the SPSVGSPViewWidget to have its size changed with Gtk. - void setResize(bool resize, gdouble width, gdouble height) { - sp_svg_view_widget_set_resize(this, resize, width, height); - } + void setResize(bool resize, gdouble width, gdouble height); }; /// The SPSVGSPViewWidget vtable. struct SPSVGSPViewWidgetClass { - SPViewWidgetClass parent_class; + SPViewWidgetClass parent_class; }; -#endif +#endif // SEEN_SP_SVG_VIEW_WIDGET_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/svg-view.cpp b/src/svg-view.cpp index ef87b38ef..b35375736 100644 --- a/src/svg-view.cpp +++ b/src/svg-view.cpp @@ -14,7 +14,6 @@ */ #include "display/canvas-arena.h" -#include "display/display-forward.h" #include "document.h" #include "sp-item.h" #include "svg-view.h" diff --git a/src/text-context.h b/src/text-context.h index a6e2e8db7..2cceaebb2 100644 --- a/src/text-context.h +++ b/src/text-context.h @@ -19,7 +19,6 @@ #include #include "event-context.h" -#include #include <2geom/point.h> #include "libnrtype/Layout-TNG.h" diff --git a/src/tweak-context.cpp b/src/tweak-context.cpp index 1d0c004a4..3b93c659b 100644 --- a/src/tweak-context.cpp +++ b/src/tweak-context.cpp @@ -20,7 +20,6 @@ #include #include "svg/svg.h" -#include "display/canvas-bpath.h" #include #include "macros.h" @@ -61,6 +60,7 @@ #include "gradient-chemistry.h" #include "sp-text.h" #include "sp-flowtext.h" +#include "display/sp-canvas.h" #include "display/canvas-bpath.h" #include "display/canvas-arena.h" #include "display/curve.h" diff --git a/src/tweak-context.h b/src/tweak-context.h index ad688b025..542254b91 100644 --- a/src/tweak-context.h +++ b/src/tweak-context.h @@ -13,7 +13,6 @@ */ #include "event-context.h" -#include #include #define SP_TYPE_TWEAK_CONTEXT (sp_tweak_context_get_type()) diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp index 8db5e7c0b..61851c56c 100644 --- a/src/ui/dialog/aboutbox.cpp +++ b/src/ui/dialog/aboutbox.cpp @@ -165,7 +165,7 @@ Gtk::Widget *build_splash_widget() { doc->doUnref(); - sp_svg_view_widget_set_resize(SP_SVG_VIEW_WIDGET(v), FALSE, (int)width, (int)height); + SP_SVG_VIEW_WIDGET(v)->setResize(false, static_cast(width), static_cast(height)); Gtk::AspectFrame *frame=new Gtk::AspectFrame(); frame->unset_label(); diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h index 3aed6ae93..6a5b05e85 100644 --- a/src/ui/tool/control-point-selection.h +++ b/src/ui/tool/control-point-selection.h @@ -18,13 +18,13 @@ #include <2geom/forward.h> #include <2geom/point.h> #include <2geom/rect.h> -#include "display/display-forward.h" #include "util/accumulators.h" #include "util/unordered-containers.h" #include "ui/tool/commit-events.h" #include "ui/tool/manipulator.h" class SPDesktop; +struct SPCanvasGroup; namespace Inkscape { namespace UI { diff --git a/src/ui/tool/control-point.cpp b/src/ui/tool/control-point.cpp index d5e5b7dfe..38b421553 100644 --- a/src/ui/tool/control-point.cpp +++ b/src/ui/tool/control-point.cpp @@ -14,6 +14,7 @@ #include <2geom/point.h> #include "desktop.h" #include "desktop-handles.h" +#include "display/sp-canvas.h" #include "display/snap-indicator.h" #include "event-context.h" #include "message-context.h" diff --git a/src/ui/tool/control-point.h b/src/ui/tool/control-point.h index 4de5e5847..3f5fe668d 100644 --- a/src/ui/tool/control-point.h +++ b/src/ui/tool/control-point.h @@ -17,7 +17,6 @@ #include #include <2geom/point.h> -#include "display/display-forward.h" #include "forward.h" #include "util/accumulators.h" #include "display/sodipodi-ctrl.h" diff --git a/src/ui/tool/multi-path-manipulator.h b/src/ui/tool/multi-path-manipulator.h index ddb74c1bc..aef9c1ac9 100644 --- a/src/ui/tool/multi-path-manipulator.h +++ b/src/ui/tool/multi-path-manipulator.h @@ -12,7 +12,6 @@ #define SEEN_UI_TOOL_MULTI_PATH_MANIPULATOR_H #include -#include "display/display-forward.h" #include "forward.h" #include "ui/tool/commit-events.h" #include "ui/tool/manipulator.h" diff --git a/src/ui/tool/node-tool.cpp b/src/ui/tool/node-tool.cpp index 8661e7946..e75f31370 100644 --- a/src/ui/tool/node-tool.cpp +++ b/src/ui/tool/node-tool.cpp @@ -13,6 +13,7 @@ #include #include "desktop.h" #include "desktop-handles.h" +#include "display/sp-canvas-group.h" #include "display/canvas-bpath.h" #include "display/curve.h" #include "display/sp-canvas.h" diff --git a/src/ui/tool/node-tool.h b/src/ui/tool/node-tool.h index 4d38e69e2..bcf6a8d5e 100644 --- a/src/ui/tool/node-tool.h +++ b/src/ui/tool/node-tool.h @@ -17,7 +17,6 @@ #include #include "event-context.h" #include "forward.h" -#include "display/display-forward.h" #include "ui/tool/node-types.h" #define INK_TYPE_NODE_TOOL (ink_node_tool_get_type ()) @@ -30,13 +29,17 @@ class InkNodeTool; class InkNodeToolClass; namespace Inkscape { + +namespace Display { +class TemporaryItem; +} // namespace Display namespace UI { class MultiPathManipulator; class ControlPointSelection; class Selector; struct PathSharedData; -} -} +} // namespace UI +} // namespace Inkscape typedef std::auto_ptr MultiPathPtr; typedef std::auto_ptr CSelPtr; diff --git a/src/ui/tool/path-manipulator.h b/src/ui/tool/path-manipulator.h index 8a0167e59..58907ea96 100644 --- a/src/ui/tool/path-manipulator.h +++ b/src/ui/tool/path-manipulator.h @@ -17,12 +17,12 @@ #include <2geom/matrix.h> #include #include -#include "display/display-forward.h" #include "forward.h" #include "ui/tool/node.h" #include "ui/tool/manipulator.h" struct SPCanvasItem; +struct SPCurve; namespace Inkscape { namespace XML { class Node; } diff --git a/src/ui/tool/selector.h b/src/ui/tool/selector.h index e61668d9e..05d72c208 100644 --- a/src/ui/tool/selector.h +++ b/src/ui/tool/selector.h @@ -14,7 +14,6 @@ #include #include #include <2geom/rect.h> -#include "display/display-forward.h" #include "ui/tool/manipulator.h" class SPDesktop; diff --git a/src/ui/tool/transform-handle-set.h b/src/ui/tool/transform-handle-set.h index 2a4df8751..b18c598ee 100644 --- a/src/ui/tool/transform-handle-set.h +++ b/src/ui/tool/transform-handle-set.h @@ -14,12 +14,11 @@ #include #include #include <2geom/forward.h> -#include "display/display-forward.h" #include "ui/tool/commit-events.h" #include "ui/tool/manipulator.h" class SPDesktop; -class CtrlRect; // this is not present in display-forward.h! +class CtrlRect; namespace Inkscape { namespace UI { diff --git a/src/ui/widget/ruler.cpp b/src/ui/widget/ruler.cpp index 107f4e8c6..1a6455ca0 100644 --- a/src/ui/widget/ruler.cpp +++ b/src/ui/widget/ruler.cpp @@ -26,6 +26,7 @@ #include "ui/widget/ruler.h" #include "xml/repr.h" +#include "display/sp-canvas.h" #include "display/guideline.h" #include "desktop.h" #include "desktop-handles.h" diff --git a/src/ui/widget/svg-canvas.cpp b/src/ui/widget/svg-canvas.cpp index 64657296d..7d37ec355 100644 --- a/src/ui/widget/svg-canvas.cpp +++ b/src/ui/widget/svg-canvas.cpp @@ -12,8 +12,8 @@ #include #include "desktop.h" #include "desktop-events.h" +#include "display/sp-canvas.h" #include "display/canvas-arena.h" -#include "display/display-forward.h" #include "ui/widget/svg-canvas.h" namespace Inkscape { diff --git a/src/widgets/desktop-widget.cpp b/src/widgets/desktop-widget.cpp index 3509a1040..be2caa5ee 100644 --- a/src/widgets/desktop-widget.cpp +++ b/src/widgets/desktop-widget.cpp @@ -33,6 +33,7 @@ #include "desktop-events.h" #include "desktop-handles.h" #include "desktop-widget.h" +#include "display/sp-canvas.h" #include "display/canvas-arena.h" #include "display/nr-arena.h" #include "document.h" diff --git a/src/widgets/desktop-widget.h b/src/widgets/desktop-widget.h index 4edd434af..1bb10fc51 100644 --- a/src/widgets/desktop-widget.h +++ b/src/widgets/desktop-widget.h @@ -15,7 +15,6 @@ #include #include -#include "display/display-forward.h" #include "libnr/nr-point.h" #include "forward.h" #include "sp-object.h" @@ -27,6 +26,7 @@ // forward declaration typedef struct _EgeColorProfTracker EgeColorProfTracker; +struct SPCanvas; #define SP_TYPE_DESKTOP_WIDGET SPDesktopWidget::getType() diff --git a/src/zoom-context.cpp b/src/zoom-context.cpp index f8212069e..45de37652 100644 --- a/src/zoom-context.cpp +++ b/src/zoom-context.cpp @@ -1,5 +1,3 @@ -#define __SP_ZOOM_CONTEXT_C__ - /* * Handy zooming tool * @@ -18,6 +16,7 @@ #include "macros.h" #include "rubberband.h" +#include "display/sp-canvas-item.h" #include "display/sp-canvas-util.h" #include "desktop.h" #include "pixmaps/cursor-zoom.xpm" -- cgit v1.2.3 From ca41dd0b6f68683f8586f78e7a8171551c6ad57a Mon Sep 17 00:00:00 2001 From: Maximilian Albert Date: Thu, 23 Dec 2010 16:51:07 +0100 Subject: Fix crash in cycle-selection (and restructure internals). (bzr r9980) --- src/select-context.cpp | 92 ++++++++++++++++++++++++++++++++++---------------- src/select-context.h | 2 +- 2 files changed, 63 insertions(+), 31 deletions(-) (limited to 'src') diff --git a/src/select-context.cpp b/src/select-context.cpp index 4a8b38c37..d6355ba74 100644 --- a/src/select-context.cpp +++ b/src/select-context.cpp @@ -113,7 +113,6 @@ sp_select_context_init(SPSelectContext *sc) sc->button_press_shift = false; sc->button_press_ctrl = false; sc->button_press_alt = false; - sc->is_cycling = false; sc->cycling_items = NULL; sc->cycling_items_selected_before = NULL; sc->cycling_cur_item = NULL; @@ -527,21 +526,6 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) case GDK_MOTION_NOTIFY: { - SPSelectContext *sc = SP_SELECT_CONTEXT(event_context); - if (sc->is_cycling) { - // Abort cycle-select - NRArenaItem *arenaitem; - for (GList *l = sc->cycling_items; l != NULL; l = g_list_next(l)) { - arenaitem = item->get_arenaitem(desktop->dkey); - nr_arena_item_set_opacity (arenaitem, 1.0); - } - g_list_free(sc->cycling_items); - g_list_free(sc->cycling_items_selected_before); - sc->cycling_items = NULL; - sc->cycling_cur_item = NULL; - sc->is_cycling = false; - } - tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); if (event->motion.state & GDK_BUTTON1_MASK && !event_context->space_panning) { Geom::Point const motion_pt(event->motion.x, event->motion.y); @@ -769,24 +753,71 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) if (scroll_event->state & GDK_MOD1_MASK) { // alt modified pressed bool shift_pressed = scroll_event->state & GDK_SHIFT_MASK; - if(sc->is_cycling == false) { - // Build a list of items underneath the mouse pointer (for cycle-selection) and reduce their opacity - Geom::Point p = desktop->d2w(desktop->point()); - SPItem *item = desktop->getItemAtPoint(p, true, NULL); - while(item != NULL) { - sc->cycling_items = g_list_append(sc->cycling_items, item); + /* Rebuild list of items underneath the mouse pointer */ + Geom::Point p = desktop->d2w(desktop->point()); + SPItem *item = desktop->getItemAtPoint(p, true, NULL); + + // Save pointer to current cycle-item so that we can find it again later, in the freshly built list + SPItem *tmp_cur_item = sc->cycling_cur_item ? SP_ITEM(sc->cycling_cur_item->data) : NULL; + g_list_free(sc->cycling_items); + sc->cycling_items = NULL; + sc->cycling_cur_item = NULL; + + while(item != NULL) { + sc->cycling_items = g_list_append(sc->cycling_items, item); + item = desktop->getItemAtPoint(p, true, item); + } + + /* Compare current item list with item list during previous scroll ... */ + GList *l1, *l2; + bool item_lists_differ = false; + // Note that we can do an 'or' comparison in the loop because it is safe to call g_list_next with a NULL pointer. + for (l1 = sc->cycling_items, l2 = sc->cycling_items_cmp; l1 != NULL || l2 != NULL; l1 = g_list_next(l1), l2 = g_list_next(l2)) { + if ((l1 !=NULL && l2 == NULL) || (l1 == NULL && l2 != NULL) || (l1->data != l2->data)) { + item_lists_differ = true; + break; + } + } + + /* If list of items under mouse pointer hasn't changed ... */ + if (!item_lists_differ) { + // ... find current item in the freshly built list and continue cycling ... + // TODO: This wouldn't be necessary if cycling_cur_item pointed to an element of cycling_items_cmp instead + sc->cycling_cur_item = g_list_find(sc->cycling_items, tmp_cur_item); + g_assert(sc->cycling_cur_item != NULL || sc->cycling_items == NULL); + } else { + // ... otherwise reset opacities for outdated items ... + NRArenaItem *arenaitem; + for(GList *l = sc->cycling_items_cmp; l != NULL; l = l->next) { + arenaitem = SP_ITEM(l->data)->get_arenaitem(desktop->dkey); + nr_arena_item_set_opacity (arenaitem, 1.0); + //if (!shift_pressed && !g_list_find(sc->cycling_items_selected_before, SP_ITEM(l->data)) && selection->includes(SP_ITEM(l->data))) + if (!g_list_find(sc->cycling_items_selected_before, SP_ITEM(l->data)) && selection->includes(SP_ITEM(l->data))) + selection->remove(SP_ITEM(l->data)); + } + + // ... clear the lists ... + g_list_free(sc->cycling_items_cmp); + g_list_free(sc->cycling_items_selected_before); + sc->cycling_items_cmp = NULL; + sc->cycling_items_selected_before = NULL; + sc->cycling_cur_item = NULL; + + // ... and rebuild them with the new items. + sc->cycling_items_cmp = g_list_copy(sc->cycling_items); + SPItem *item; + for(GList *l = sc->cycling_items; l != NULL; l = l->next) { + item = SP_ITEM(l->data); + arenaitem = item->get_arenaitem(desktop->dkey); + nr_arena_item_set_opacity (arenaitem, 0.3); if (selection->includes(item)) { // already selected items are stored separately, too sc->cycling_items_selected_before = g_list_append(sc->cycling_items_selected_before, item); } - NRArenaItem *arenaitem = item->get_arenaitem(desktop->dkey); - nr_arena_item_set_opacity (arenaitem, 0.3); - - item = desktop->getItemAtPoint(p, true, item); } - // Here we set the current item to the bottommost one so that the cycling step below re-starts at the top + + // set the current item to the bottommost one so that the cycling step below re-starts at the top sc->cycling_cur_item = g_list_last(sc->cycling_items); - sc->is_cycling = true; } // Cycle through the items underneath the mouse pointer, one-by-one @@ -1050,7 +1081,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) Inkscape::Rubberband::get(desktop)->setMode(RUBBERBAND_MODE_RECT); } } else { - if (alt && sc->is_cycling) { + if (alt) { // TODO: Should we have a variable like is_cycling or is it harmless to run this piece of code each time? // quit cycle-selection and reset opacities SPSelectContext *sc = SP_SELECT_CONTEXT(event_context); NRArenaItem *arenaitem; @@ -1060,10 +1091,11 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) } g_list_free(sc->cycling_items); g_list_free(sc->cycling_items_selected_before); + g_list_free(sc->cycling_items_cmp); sc->cycling_items = NULL; sc->cycling_items_selected_before = NULL; sc->cycling_cur_item = NULL; - sc->is_cycling = false; + sc->cycling_items_cmp = NULL; } } diff --git a/src/select-context.h b/src/select-context.h index 4c58fc858..377e07275 100644 --- a/src/select-context.h +++ b/src/select-context.h @@ -38,8 +38,8 @@ struct SPSelectContext : public SPEventContext { bool button_press_ctrl; bool button_press_alt; - bool is_cycling; GList *cycling_items; + GList *cycling_items_cmp; GList *cycling_items_selected_before; GList *cycling_cur_item; -- cgit v1.2.3 From 94e5fe845bd66b66069df22c241867af20c6bcaf Mon Sep 17 00:00:00 2001 From: Kris De Gussem Date: Thu, 23 Dec 2010 18:52:29 +0100 Subject: Mnemonics in "Fill and stroke", "Align and distribute", and "Transform" dialogs (Bug 170765) (bzr r9981) --- src/ui/dialog/align-and-distribute.cpp | 9 ++++++--- src/ui/dialog/transformation.cpp | 2 +- src/widgets/spw-utilities.cpp | 14 +++++++++++--- src/widgets/spw-utilities.h | 3 ++- src/widgets/stroke-style.cpp | 28 +++++++++++++++++++--------- 5 files changed, 39 insertions(+), 17 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/align-and-distribute.cpp b/src/ui/dialog/align-and-distribute.cpp index 48f0fbf22..f974ec6ce 100644 --- a/src/ui/dialog/align-and-distribute.cpp +++ b/src/ui/dialog/align-and-distribute.cpp @@ -467,7 +467,8 @@ public: dialog.tooltips().set_tip(removeOverlapXGap, _("Minimum horizontal gap (in px units) between bounding boxes")); //TRANSLATORS: "H:" stands for horizontal gap - removeOverlapXGapLabel.set_label(C_("Gap", "H:")); + removeOverlapXGapLabel.set_text_with_mnemonic(C_("Gap", "_H:")); + removeOverlapXGapLabel.set_mnemonic_widget(removeOverlapXGap); removeOverlapYGap.set_digits(1); removeOverlapYGap.set_size_request(60, -1); @@ -477,7 +478,8 @@ public: dialog.tooltips().set_tip(removeOverlapYGap, _("Minimum vertical gap (in px units) between bounding boxes")); /* TRANSLATORS: Vertical gap */ - removeOverlapYGapLabel.set_label(C_("Gap", "V:")); + removeOverlapYGapLabel.set_text_with_mnemonic(C_("Gap", "_V:")); + removeOverlapYGapLabel.set_mnemonic_widget(removeOverlapYGap); dialog.removeOverlap_table().attach(removeOverlapXGapLabel, column, column+1, row, row+1, Gtk::FILL, Gtk::FILL); dialog.removeOverlap_table().attach(removeOverlapXGap, column+1, column+2, row, row+1, Gtk::FILL, Gtk::FILL); @@ -896,7 +898,7 @@ AlignAndDistribute::AlignAndDistribute() _removeOverlapTable(1, 5, false), _nodesTable(1, 4, true), _anchorLabel(_("Relative to: ")), - _selgrpLabel(_("Treat selection as group: ")) + _selgrpLabel(_("_Treat selection as group: "), 1) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -1038,6 +1040,7 @@ AlignAndDistribute::AlignAndDistribute() _anchorBox.pack_start(_anchorLabel); _anchorBox.pack_start(_combo); + _selgrpLabel.set_mnemonic_widget(_selgrp); _selgrpBox.pack_start(_selgrpLabel); _selgrpBox.pack_start(_selgrp); _selgrp.set_active(prefs->getBool("/dialogs/align/sel-as-groups")); diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp index c895f0be9..8da9914bc 100644 --- a/src/ui/dialog/transformation.cpp +++ b/src/ui/dialog/transformation.cpp @@ -104,7 +104,7 @@ Transformation::Transformation() _scalar_transform_f ("_F:", _("Transformation matrix element F")), _check_move_relative (_("Rela_tive move"), _("Add the specified relative displacement to the current position; otherwise, edit the current absolute position directly")), - _check_scale_proportional (_("Scale proportionally"), _("Preserve the width/height ratio of the scaled objects")), + _check_scale_proportional (_("_Scale proportionally"), _("Preserve the width/height ratio of the scaled objects")), _check_apply_separately (_("Apply to each _object separately"), _("Apply the scale/rotate/skew to each selected object separately; otherwise, transform the selection as a whole")), _check_replace_matrix (_("Edit c_urrent matrix"), _("Edit the current transform= matrix; otherwise, post-multiply transform= by this matrix")) diff --git a/src/widgets/spw-utilities.cpp b/src/widgets/spw-utilities.cpp index 7c2956c65..49e3a7495 100644 --- a/src/widgets/spw-utilities.cpp +++ b/src/widgets/spw-utilities.cpp @@ -34,11 +34,19 @@ * position in the table. */ Gtk::Label * -spw_label(Gtk::Table *table, const gchar *label_text, int col, int row) +spw_label(Gtk::Table *table, const gchar *label_text, int col, int row, Gtk::Widget* target) { - Gtk::Label *label_widget = new Gtk::Label(label_text); + Gtk::Label *label_widget = new Gtk::Label(); g_assert(label_widget != NULL); - + if (target != NULL) + { + label_widget->set_text_with_mnemonic(label_text); + label_widget->set_mnemonic_widget(*target); + } + else + { + label_widget->set_text(label_text); + } label_widget->set_alignment(1.0, 0.5); label_widget->show(); table->attach(*label_widget, col, col+1, row, row+1, (Gtk::EXPAND | Gtk::FILL), static_cast(0), 4, 0); diff --git a/src/widgets/spw-utilities.h b/src/widgets/spw-utilities.h index d17762811..9a387454f 100644 --- a/src/widgets/spw-utilities.h +++ b/src/widgets/spw-utilities.h @@ -20,6 +20,7 @@ #include #include /* GtkWidget */ +#include namespace Gtk { class Label; @@ -28,7 +29,7 @@ namespace Gtk { } Gtk::Label * -spw_label(Gtk::Table *table, gchar const *label_text, int col, int row); +spw_label(Gtk::Table *table, gchar const *label_text, int col, int row, Gtk::Widget *target); GtkWidget * spw_label_old(GtkWidget *table, gchar const *label_text, int col, int row); diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp index ffcbe48f8..885a58536 100644 --- a/src/widgets/stroke-style.cpp +++ b/src/widgets/stroke-style.cpp @@ -673,7 +673,7 @@ sp_stroke_style_line_widget_new(void) gint i = 0; - spw_label(t, C_("Stroke width", "Width:"), 0, i); + //spw_label(t, C_("Stroke width", "_Width:"), 0, i); hb = spw_hbox(t, 3, 1, i); @@ -689,7 +689,8 @@ sp_stroke_style_line_widget_new(void) sb = new Gtk::SpinButton(*a, 0.1, 3); tt->set_tip(*sb, _("Stroke width")); sb->show(); - + spw_label(t, C_("Stroke width", "_Width:"), 0, i, sb); + sp_dialog_defocus_on_enter_cpp(sb); hb->pack_start(*sb, false, false, 0); @@ -711,7 +712,7 @@ sp_stroke_style_line_widget_new(void) /* Join type */ // TRANSLATORS: The line join style specifies the shape to be used at the // corners of paths. It can be "miter", "round" or "bevel". - spw_label(t, _("Join:"), 0, i); + spw_label(t, _("Join:"), 0, i, NULL); hb = spw_hbox(t, 3, 1, i); @@ -755,7 +756,7 @@ sp_stroke_style_line_widget_new(void) // spike that extends well beyond the connection point. The purpose of the // miter limit is to cut off such spikes (i.e. convert them into bevels) // when they become too long. - spw_label(t, _("Miter limit:"), 0, i); + //spw_label(t, _("Miter _limit:"), 0, i); hb = spw_hbox(t, 3, 1, i); @@ -765,6 +766,7 @@ sp_stroke_style_line_widget_new(void) sb = new Gtk::SpinButton(*a, 0.1, 2); tt->set_tip(*sb, _("Maximum length of the miter (in units of stroke width)")); sb->show(); + spw_label(t, _("Miter _limit:"), 0, i, sb); spw->set_data("miterlimit_sb", sb); sp_dialog_defocus_on_enter_cpp(sb); @@ -775,7 +777,8 @@ sp_stroke_style_line_widget_new(void) /* Cap type */ // TRANSLATORS: cap type specifies the shape for the ends of lines - spw_label(t, _("Cap:"), 0, i); + //spw_label(t, _("_Cap:"), 0, i); + spw_label(t, _("Cap:"), 0, i, NULL); hb = spw_hbox(t, 3, 1, i); @@ -809,7 +812,11 @@ sp_stroke_style_line_widget_new(void) /* Dash */ - spw_label(t, _("Dashes:"), 0, i); + spw_label(t, _("Dashes:"), 0, i, NULL); //no mnemonic for now + //decide what to do: + // implement a set_mnemonic_source function in the + // SPDashSelector class, so that we do not have to + // expose any of the underlying widgets? ds = manage(new SPDashSelector); ds->show(); @@ -826,8 +833,9 @@ sp_stroke_style_line_widget_new(void) // TRANSLATORS: Path markers are an SVG feature that allows you to attach arbitrary shapes // (arrowheads, bullets, faces, whatever) to the start, end, or middle nodes of a path. - spw_label(t, _("Start Markers:"), 0, i); + //spw_label(t, _("_Start Markers:"), 0, i); marker_start_menu = ink_marker_menu(spw ,"marker-start", sandbox); + spw_label(t, _("_Start Markers:"), 0, i, marker_start_menu); tt->set_tip(*marker_start_menu, _("Start Markers are drawn on the first node of a path or shape")); marker_start_menu_connection = marker_start_menu->signal_changed().connect( sigc::bind( @@ -837,8 +845,9 @@ sp_stroke_style_line_widget_new(void) spw->set_data("start_mark_menu", marker_start_menu); i++; - spw_label(t, _("Mid Markers:"), 0, i); + //spw_label(t, _("_Mid Markers:"), 0, i); marker_mid_menu = ink_marker_menu(spw ,"marker-mid", sandbox); + spw_label(t, _("_Mid Markers:"), 0, i, marker_mid_menu); tt->set_tip(*marker_mid_menu, _("Mid Markers are drawn on every node of a path or shape except the first and last nodes")); marker_mid_menu_connection = marker_mid_menu->signal_changed().connect( sigc::bind( @@ -848,8 +857,9 @@ sp_stroke_style_line_widget_new(void) spw->set_data("mid_mark_menu", marker_mid_menu); i++; - spw_label(t, _("End Markers:"), 0, i); + //spw_label(t, _("_End Markers:"), 0, i); marker_end_menu = ink_marker_menu(spw ,"marker-end", sandbox); + spw_label(t, _("_End Markers:"), 0, i, marker_end_menu); tt->set_tip(*marker_end_menu, _("End Markers are drawn on the last node of a path or shape")); marker_end_menu_connection = marker_end_menu->signal_changed().connect( sigc::bind( -- cgit v1.2.3 From c210fd393e9423898f9c745fe081da3d90e9b605 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Mon, 27 Dec 2010 22:18:34 +0100 Subject: Node tool: snap while scaling a selection of nodes. Consider this as experimental; needs cleanup! (bzr r9985) --- src/seltrans.cpp | 28 ++------------ src/seltrans.h | 1 - src/snap.cpp | 56 ++++++++++++++++++++++++---- src/snap.h | 17 +++++---- src/ui/tool/control-point-selection.cpp | 18 +++++++++ src/ui/tool/control-point-selection.h | 5 +++ src/ui/tool/transform-handle-set.cpp | 66 ++++++++++++++++++++++++++++++++- 7 files changed, 148 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/seltrans.cpp b/src/seltrans.cpp index b0e19e60c..b1d184986 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -299,7 +299,7 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s An average user would rarely ever try to snap such a large number of nodes anyway, because (s)he could hardly discern which node would be snapping */ if (prefs->getBool("/options/snapclosestonly/value", false)) { - _keepClosestPointOnly(_snap_points, p); + m.keepClosestPointOnly(_snap_points, p); } else { _snap_points = snap_points_hull; } @@ -360,14 +360,14 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s if (prefs->getBool("/options/snapclosestonly/value", false)) { if (m.snapprefs.getSnapModeNode()) { - _keepClosestPointOnly(_snap_points, p); + m.keepClosestPointOnly(_snap_points, p); } else { _snap_points.clear(); // don't keep any point } if (m.snapprefs.getSnapModeBBox()) { - _keepClosestPointOnly(_bbox_points, p); - _keepClosestPointOnly(_bbox_points_for_translating, p); + m.keepClosestPointOnly(_bbox_points, p); + m.keepClosestPointOnly(_bbox_points_for_translating, p); } else { _bbox_points.clear(); // don't keep any point _bbox_points_for_translating.clear(); @@ -1632,26 +1632,6 @@ Geom::Point Inkscape::SelTrans::_calcAbsAffineGeom(Geom::Scale const geom_scale) return _calcAbsAffineDefault(geom_scale); // this is bogus, but we must return _something_ } -void Inkscape::SelTrans::_keepClosestPointOnly(std::vector &points, const Geom::Point &reference) -{ - if (points.size() < 2) return; - - Inkscape::SnapCandidatePoint closest_point = Inkscape::SnapCandidatePoint(Geom::Point(NR_HUGE, NR_HUGE), SNAPSOURCE_UNDEFINED, SNAPTARGET_UNDEFINED); - Geom::Coord closest_dist = NR_HUGE; - - for(std::vector::const_iterator i = points.begin(); i != points.end(); i++) { - Geom::Coord dist = Geom::L2((*i).getPoint() - reference); - if (i == points.begin() || dist < closest_dist) { - closest_point = *i; - closest_dist = dist; - } - } - - closest_point.setSourceNum(-1); - points.clear(); - points.push_back(closest_point); -} - /* Local Variables: mode:c++ diff --git a/src/seltrans.h b/src/seltrans.h index 0183683ff..bb26aa2cb 100644 --- a/src/seltrans.h +++ b/src/seltrans.h @@ -103,7 +103,6 @@ private: Geom::Point _getGeomHandlePos(Geom::Point const &visual_handle_pos); Geom::Point _calcAbsAffineDefault(Geom::Scale const default_scale); Geom::Point _calcAbsAffineGeom(Geom::Scale const geom_scale); - void _keepClosestPointOnly(std::vector &points, const Geom::Point &reference); void _display_snapsource(); enum State { diff --git a/src/snap.cpp b/src/snap.cpp index 79f398cc5..85d2fd5af 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -22,6 +22,7 @@ #include "sp-namedview.h" #include "snap.h" +#include "snap-enums.h" #include "snapped-line.h" #include "snapped-curve.h" @@ -682,7 +683,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( Geom::Point const &transformation, Geom::Point const &origin, Geom::Dim2 dim, - bool uniform) const + bool uniform) { /* We have a list of points, which we are proposing to transform in some way. We need to see ** if any of these points, when transformed, snap to anything. If they do, we return the @@ -734,6 +735,12 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( g_warning("Unconstrained rotation is not supported!"); } + // We will try to snap a set of points, but we don't want to have a snap indicator displayed + // for each of them. That's why it's temporarily disabled here, and re-enabled again after we + // have finished calling the freeSnap() and constrainedSnap() methods + bool _orig_snapindicator_status = _snapindicator; + _snapindicator = false; + std::vector::iterator j = transformed_points.begin(); // std::cout << std::endl; @@ -802,6 +809,9 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // std::cout << "dist = " << snapped_point.getSnapDistance() << std::endl; snapped_point.setPointerDistance(Geom::L2(pointer - (*i).getPoint())); + // Allow the snapindicator to be displayed again + _snapindicator = _orig_snapindicator_status; + Geom::Point result; /*Find the transformation that describes where the snapped point has @@ -891,6 +901,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( if (snapped_point.getSnapped()) { // We snapped; keep track of the best snap + // TODO: Compare the transformations instead of the snap points; we should be looking for the closest transformation if (best_snapped_point.isOtherSnapBetter(snapped_point, true)) { best_transformation = result; best_snapped_point = snapped_point; @@ -932,6 +943,15 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( // Using " < 1e6" instead of " < NR_HUGE" for catching some rounding errors // These rounding errors might be caused by NRRects, see bug #1584301 best_snapped_point.setSnapDistance(best_metric < 1e6 ? best_metric : NR_HUGE); + + if (_snapindicator) { + if (best_snapped_point.getSnapped()) { + _desktop->snapindicator->set_new_snaptarget(best_snapped_point); + } else { + _desktop->snapindicator->remove_snaptarget(); + } + } + return best_snapped_point; } @@ -947,7 +967,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( Inkscape::SnappedPoint SnapManager::freeSnapTranslate(std::vector const &p, Geom::Point const &pointer, - Geom::Point const &tr) const + Geom::Point const &tr) { Inkscape::SnappedPoint result = _snapTransformed(p, pointer, false, Geom::Point(0,0), TRANSLATE, tr, Geom::Point(0,0), Geom::X, false); @@ -971,7 +991,7 @@ Inkscape::SnappedPoint SnapManager::freeSnapTranslate(std::vector const &p, Geom::Point const &pointer, Inkscape::Snapper::SnapConstraint const &constraint, - Geom::Point const &tr) const + Geom::Point const &tr) { Inkscape::SnappedPoint result = _snapTransformed(p, pointer, true, constraint, TRANSLATE, tr, Geom::Point(0,0), Geom::X, false); @@ -996,7 +1016,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapTranslate(std::vector const &p, Geom::Point const &pointer, Geom::Scale const &s, - Geom::Point const &o) const + Geom::Point const &o) { Inkscape::SnappedPoint result = _snapTransformed(p, pointer, false, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, false); @@ -1021,7 +1041,7 @@ Inkscape::SnappedPoint SnapManager::freeSnapScale(std::vector const &p, Geom::Point const &pointer, Geom::Scale const &s, - Geom::Point const &o) const + Geom::Point const &o) { // When constrained scaling, only uniform scaling is supported. Inkscape::SnappedPoint result = _snapTransformed(p, pointer, true, Geom::Point(0,0), SCALE, Geom::Point(s[Geom::X], s[Geom::Y]), o, Geom::X, true); @@ -1050,7 +1070,7 @@ Inkscape::SnappedPoint SnapManager::constrainedSnapStretch(std::vector const &p, Geom::Point const &pointer, Geom::Coord const &angle, - Geom::Point const &o) const + Geom::Point const &o) { // Snapping the nodes of the bounding box of a selection that is being transformed, will only work if // the transformation of the bounding box is equal to the transformation of the individual nodes. This is @@ -1429,6 +1449,26 @@ void SnapManager::_displaySnapsource(Inkscape::SnapCandidatePoint const &p) cons } } +void SnapManager::keepClosestPointOnly(std::vector &points, const Geom::Point &reference) const +{ + if (points.size() < 2) return; + + Inkscape::SnapCandidatePoint closest_point = Inkscape::SnapCandidatePoint(Geom::Point(NR_HUGE, NR_HUGE), Inkscape::SNAPSOURCE_UNDEFINED, Inkscape::SNAPTARGET_UNDEFINED); + Geom::Coord closest_dist = NR_HUGE; + + for(std::vector::const_iterator i = points.begin(); i != points.end(); i++) { + Geom::Coord dist = Geom::L2((*i).getPoint() - reference); + if (i == points.begin() || dist < closest_dist) { + closest_point = *i; + closest_dist = dist; + } + } + + closest_point.setSourceNum(-1); + points.clear(); + points.push_back(closest_point); +} + /* Local Variables: mode:c++ diff --git a/src/snap.h b/src/snap.h index c79bd308a..8f8416ee5 100644 --- a/src/snap.h +++ b/src/snap.h @@ -149,41 +149,41 @@ public: Inkscape::SnappedPoint freeSnapTranslate(std::vector const &p, Geom::Point const &pointer, - Geom::Point const &tr) const; + Geom::Point const &tr); Inkscape::SnappedPoint constrainedSnapTranslate(std::vector const &p, Geom::Point const &pointer, Inkscape::Snapper::SnapConstraint const &constraint, - Geom::Point const &tr) const; + Geom::Point const &tr); Inkscape::SnappedPoint freeSnapScale(std::vector const &p, Geom::Point const &pointer, Geom::Scale const &s, - Geom::Point const &o) const; + Geom::Point const &o); Inkscape::SnappedPoint constrainedSnapScale(std::vector const &p, Geom::Point const &pointer, Geom::Scale const &s, - Geom::Point const &o) const; + Geom::Point const &o); Inkscape::SnappedPoint constrainedSnapStretch(std::vector const &p, Geom::Point const &pointer, Geom::Coord const &s, Geom::Point const &o, Geom::Dim2 d, - bool uniform) const; + bool uniform); Inkscape::SnappedPoint constrainedSnapSkew(std::vector const &p, Geom::Point const &pointer, Inkscape::Snapper::SnapConstraint const &constraint, Geom::Point const &s, // s[0] = skew factor, s[1] = scale factor Geom::Point const &o, - Geom::Dim2 d) const; + Geom::Dim2 d); Inkscape::SnappedPoint constrainedSnapRotate(std::vector const &p, Geom::Point const &pointer, Geom::Coord const &angle, - Geom::Point const &o) const; + Geom::Point const &o); Inkscape::GuideSnapper guide; ///< guide snapper Inkscape::ObjectSnapper object; ///< snapper to other objects @@ -200,6 +200,7 @@ public: bool getSnapIndicator() const {return _snapindicator;} Inkscape::SnappedPoint findBestSnap(Inkscape::SnapCandidatePoint const &p, SnappedConstraints const &sc, bool constrained, bool noCurves = false, bool allowOffScreen = false) const; + void keepClosestPointOnly(std::vector &points, const Geom::Point &reference) const; protected: SPNamedView const *_named_view; @@ -220,7 +221,7 @@ private: Geom::Point const &transformation, Geom::Point const &origin, Geom::Dim2 dim, - bool uniform) const; + bool uniform); Geom::Point _transformPoint(Inkscape::SnapCandidatePoint const &p, Transformation const transformation_type, diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp index baa53f76e..517e90da2 100644 --- a/src/ui/tool/control-point-selection.cpp +++ b/src/ui/tool/control-point-selection.cpp @@ -642,6 +642,24 @@ bool ControlPointSelection::event(GdkEvent *event) return false; } +std::vector ControlPointSelection::getOriginalPoints() +{ + std::vector points; + for (iterator i = _points.begin(); i != _points.end(); ++i) { + points.push_back(Inkscape::SnapCandidatePoint(_original_positions[*i], SNAPSOURCE_NODE_HANDLE)); + } + return points; +} + +void ControlPointSelection::setOriginalPoints() +{ + _original_positions.clear(); + for (iterator i = _points.begin(); i != _points.end(); ++i) { + _original_positions.insert(std::make_pair(*i, (*i)->position())); + } +} + + } // namespace UI } // namespace Inkscape diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h index 6a5b05e85..0e5acf6c5 100644 --- a/src/ui/tool/control-point-selection.h +++ b/src/ui/tool/control-point-selection.h @@ -22,6 +22,7 @@ #include "util/unordered-containers.h" #include "ui/tool/commit-events.h" #include "ui/tool/manipulator.h" +#include "snap-candidate.h" class SPDesktop; struct SPCanvasGroup; @@ -108,6 +109,10 @@ public: sigc::signal signal_update; sigc::signal signal_point_changed; sigc::signal signal_commit; + + std::vector getOriginalPoints(); + void setOriginalPoints(); + private: // The functions below are invoked from SelectableControlPoint. // Previously they were connected to handlers when selecting, but this diff --git a/src/ui/tool/transform-handle-set.cpp b/src/ui/tool/transform-handle-set.cpp index cafd592a3..209b7fe98 100644 --- a/src/ui/tool/transform-handle-set.cpp +++ b/src/ui/tool/transform-handle-set.cpp @@ -19,11 +19,15 @@ #include "display/sodipodi-ctrlrect.h" #include "preferences.h" #include "snap.h" +#include "snap-candidate.h" #include "sp-namedview.h" #include "ui/tool/commit-events.h" #include "ui/tool/control-point.h" +#include "ui/tool/control-point-selection.h" +#include "ui/tool/selectable-control-point.h" #include "ui/tool/event-utils.h" #include "ui/tool/transform-handle-set.h" +#include "ui/tool/node-tool.h" // FIXME BRAIN DAMAGE WARNING: this is a global variable in select-context.cpp // It should be moved to a header @@ -96,6 +100,8 @@ protected: Geom::Matrix _last_transform; Geom::Point _origin; TransformHandleSet &_th; + std::vector _snap_points; + private: virtual bool grabbed(GdkEventMotion *) { _origin = position(); @@ -105,6 +111,20 @@ private: _th._setActiveHandle(this); _cset = &invisible_cset; _setState(_state); + + // Collect the snap-candidates, one for each selected node. These will be stored in the _snap_points vector. + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + SnapManager &m = desktop->namedview->snap_manager; + InkNodeTool *nt = INK_NODE_TOOL(_desktop->event_context); + ControlPointSelection *selection = nt->_selected_nodes.get(); + + _snap_points = selection->getOriginalPoints(); + + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if (prefs->getBool("/options/snapclosestonly/value", false)) { + m.keepClosestPointOnly(_snap_points, _origin); + } + return false; } virtual void dragged(Geom::Point &new_pos, GdkEventMotion *event) @@ -118,6 +138,7 @@ private: _last_transform = t; } virtual void ungrabbed(GdkEventButton *) { + _snap_points.clear(); _th._clearActiveHandle(); _cset = &thandle_cset; _setState(_state); @@ -177,23 +198,64 @@ protected: _sc_center = _th.rotationCenter(); _sc_opposite = _th.bounds().corner(_corner + 2); _last_scale_x = _last_scale_y = 1.0; + InkNodeTool *nt = INK_NODE_TOOL(_desktop->event_context); + ControlPointSelection *selection = nt->_selected_nodes.get(); + std::cout << "startTransform()" << std::endl; + selection->setOriginalPoints(); } virtual Geom::Matrix computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) { Geom::Point scc = held_shift(*event) ? _sc_center : _sc_opposite; Geom::Point vold = _origin - scc, vnew = new_pos - scc; + // avoid exploding the selection if (Geom::are_near(vold[Geom::X], 0) || Geom::are_near(vold[Geom::Y], 0)) return Geom::identity(); double scale[2] = { vnew[Geom::X] / vold[Geom::X], vnew[Geom::Y] / vold[Geom::Y] }; + if (held_alt(*event)) { for (unsigned i = 0; i < 2; ++i) { if (scale[i] >= 1.0) scale[i] = round(scale[i]); else scale[i] = 1.0 / round(1.0 / scale[i]); } - } else if (held_control(*event)) { - scale[0] = scale[1] = std::min(scale[0], scale[1]); + } else { + //SPDesktop *desktop = _th._desktop; // Won't work as _desktop is protected + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + SnapManager &m = desktop->namedview->snap_manager; + + // The lines below have been copied from Handle::dragged() in node.cpp, and need to be + // activated if we want to snap to unselected (i.e. stationary) nodes and stationary pieces of paths of the + // path that's currently being edited + /* + std::vector unselected; + typedef ControlPointSelection::Set Set; + Set &nodes = _parent->_selection.allPoints(); + for (Set::iterator i = nodes.begin(); i != nodes.end(); ++i) { + Node *n = static_cast(*i); + Inkscape::SnapCandidatePoint p(n->position(), n->_snapSourceType(), n->_snapTargetType()); + unselected.push_back(p); + } + m.setupIgnoreSelection(_desktop, true, &unselected); + */ + + m.setupIgnoreSelection(_desktop); + + Inkscape::SnappedPoint sp; + if (held_control(*event)) { + scale[0] = scale[1] = std::min(scale[0], scale[1]); + sp = m.constrainedSnapScale(_snap_points, _origin, Geom::Scale(scale[0], scale[1]), scc); + } else { + sp = m.freeSnapScale(_snap_points, _origin, Geom::Scale(scale[0], scale[1]), scc); + } + m.unSetup(); + + if (sp.getSnapped()) { + Geom::Point result = sp.getTransformation(); + scale[0] = result[0]; + scale[1] = result[1]; + } } + _last_scale_x = scale[0]; _last_scale_y = scale[1]; Geom::Matrix t = Geom::Translate(-scc) -- cgit v1.2.3 From e2fe5c8411dcbd514f1df51de0925c0719019dc9 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Mon, 27 Dec 2010 23:03:25 +0100 Subject: Snapping: improve calculation of metrics for scaling, modify some comments, and remove a line of obsolete debugging output (bzr r9986) --- src/snap.cpp | 17 ++++++++++------- src/ui/tool/transform-handle-set.cpp | 1 - 2 files changed, 10 insertions(+), 8 deletions(-) (limited to 'src') diff --git a/src/snap.cpp b/src/snap.cpp index 85d2fd5af..f13b02b46 100644 --- a/src/snap.cpp +++ b/src/snap.cpp @@ -826,11 +826,11 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( /* Consider the case in which a box is almost aligned with a grid in both * horizontal and vertical directions. The distance to the intersection of * the grid lines will always be larger then the distance to a single grid - * line. If we prefer snapping to an intersection instead of to a single + * line. If we prefer snapping to an intersection over to a single * grid line, then we cannot use "metric = Geom::L2(result)". Therefore the * snapped distance will be used as a metric. Please note that the snapped - * distance is defined as the distance to the nearest line of the intersection, - * and not to the intersection itself! + * distance to an intersection is defined as the distance to the nearest line + * of the intersection, and not to the intersection itself! */ // Only for translations, the relevant metric will be the real snapped distance, // so we don't have to do anything special here @@ -848,7 +848,7 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( if (fabs(fabs(a[index]/b[index]) - fabs(transformation[index])) > 1e-12) { // if SNAPPING DID occur in this direction result[index] = a[index] / b[index]; // then calculate it! } - // we might leave result[1-index] = NR_HUGE + // we might have left result[1-index] = NR_HUGE // if scaling didn't occur in the other direction } } @@ -861,8 +861,12 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( } // Compare the resulting scaling with the desired scaling Geom::Point scale_metric = Geom::abs(result - transformation); // One or both of its components might be NR_HUGE - snapped_point.setSnapDistance(std::min(scale_metric[0], scale_metric[1])); - snapped_point.setSecondSnapDistance(std::max(scale_metric[0], scale_metric[1])); + if (scale_metric[0] == NR_HUGE || scale_metric[1] == NR_HUGE) { + snapped_point.setSnapDistance(std::min(scale_metric[0], scale_metric[1])); + } else { + snapped_point.setSnapDistance(Geom::L2(scale_metric)); + } + snapped_point.setSecondSnapDistance(NR_HUGE); break; } case STRETCH: @@ -901,7 +905,6 @@ Inkscape::SnappedPoint SnapManager::_snapTransformed( if (snapped_point.getSnapped()) { // We snapped; keep track of the best snap - // TODO: Compare the transformations instead of the snap points; we should be looking for the closest transformation if (best_snapped_point.isOtherSnapBetter(snapped_point, true)) { best_transformation = result; best_snapped_point = snapped_point; diff --git a/src/ui/tool/transform-handle-set.cpp b/src/ui/tool/transform-handle-set.cpp index 209b7fe98..5c3b494ce 100644 --- a/src/ui/tool/transform-handle-set.cpp +++ b/src/ui/tool/transform-handle-set.cpp @@ -200,7 +200,6 @@ protected: _last_scale_x = _last_scale_y = 1.0; InkNodeTool *nt = INK_NODE_TOOL(_desktop->event_context); ControlPointSelection *selection = nt->_selected_nodes.get(); - std::cout << "startTransform()" << std::endl; selection->setOriginalPoints(); } virtual Geom::Matrix computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) { -- cgit v1.2.3 From 6bd7e1d7a54043645bc8c5a2994ec5f629521972 Mon Sep 17 00:00:00 2001 From: Maximilian Albert Date: Tue, 28 Dec 2010 20:01:41 +0100 Subject: Initialize pointer. (bzr r9987) --- src/select-context.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'src') diff --git a/src/select-context.cpp b/src/select-context.cpp index d6355ba74..4d1d06fe3 100644 --- a/src/select-context.cpp +++ b/src/select-context.cpp @@ -114,6 +114,7 @@ sp_select_context_init(SPSelectContext *sc) sc->button_press_ctrl = false; sc->button_press_alt = false; sc->cycling_items = NULL; + sc->cycling_items_cmp = NULL; sc->cycling_items_selected_before = NULL; sc->cycling_cur_item = NULL; sc->_seltrans = NULL; -- cgit v1.2.3 From b8e85b0807cad755cf69557b8d28c4f7c4bd47b8 Mon Sep 17 00:00:00 2001 From: "Arcadie M. Cracan" Date: Wed, 29 Dec 2010 17:05:55 +0200 Subject: Fix bug #552289 - Ungrouping objects changes position of arrow lines. This was due to incorrect initialization of unattached connector endpoints that was part of a group. Fixed bugs: - https://launchpad.net/bugs/552289 (bzr r9988) --- src/sp-conn-end-pair.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/sp-conn-end-pair.cpp b/src/sp-conn-end-pair.cpp index 0a5a6d7bd..5bce1a4f8 100644 --- a/src/sp-conn-end-pair.cpp +++ b/src/sp-conn-end-pair.cpp @@ -217,6 +217,7 @@ SPConnEndPair::getEndpoints(Geom::Point endPts[]) const { SPCurve *curve = _path->original_curve ? _path->original_curve : _path->curve; SPItem *h2attItem[2]; getAttachedItems(h2attItem); + Geom::Matrix i2d = SP_ITEM(_path)->i2doc_affine(); for (unsigned h = 0; h < 2; ++h) { if ( h2attItem[h] ) { @@ -226,10 +227,10 @@ SPConnEndPair::getEndpoints(Geom::Point endPts[]) const { else { if (h == 0) { - endPts[h] = *(curve->first_point()); + endPts[h] = *(curve->first_point())*i2d; } else { - endPts[h] = *(curve->last_point()); + endPts[h] = *(curve->last_point())*i2d; } } } -- cgit v1.2.3 From ad60eb09d30d964d1d250dd6553a10e2a8579282 Mon Sep 17 00:00:00 2001 From: Kris De Gussem Date: Wed, 29 Dec 2010 18:11:11 +0100 Subject: Mnemonics in "Export bitmap", and "Rows and Columns" dialogs (Bug 170765) (bzr r9989) --- src/dialogs/export.cpp | 6 +++--- src/ui/dialog/tile.cpp | 21 ++++++++++++++------- src/verbs.cpp | 2 +- 3 files changed, 18 insertions(+), 11 deletions(-) (limited to 'src') diff --git a/src/dialogs/export.cpp b/src/dialogs/export.cpp index 7e99c2496..b05f6589a 100644 --- a/src/dialogs/export.cpp +++ b/src/dialogs/export.cpp @@ -620,7 +620,7 @@ sp_export_dialog (void) { Gtk::HBox* batch_box = new Gtk::HBox(FALSE, 5); - GtkWidget *be = gtk_check_button_new_with_label(_("Batch export all selected objects")); + GtkWidget *be = gtk_check_button_new_with_mnemonic(_("B_atch export all selected objects")); gtk_widget_set_sensitive(GTK_WIDGET(be), TRUE); gtk_object_set_data(GTK_OBJECT(dlg), "batch_checkbox", be); batch_box->pack_start(*Glib::wrap(be), false, false); @@ -632,7 +632,7 @@ sp_export_dialog (void) { Gtk::HBox* hide_box = new Gtk::HBox(FALSE, 5); - GtkWidget *he = gtk_check_button_new_with_label(_("Hide all except selected")); + GtkWidget *he = gtk_check_button_new_with_mnemonic(_("Hide a_ll except selected")); gtk_widget_set_sensitive(GTK_WIDGET(he), TRUE); gtk_object_set_data(GTK_OBJECT(dlg), "hide_checkbox", he); hide_box->pack_start(*Glib::wrap(he), false, false); @@ -683,7 +683,7 @@ sp_export_update_checkbuttons (GtkObject *base) GtkWidget *he = (GtkWidget *)gtk_object_get_data(base, "hide_checkbox"); if (num >= 2) { gtk_widget_set_sensitive (be, true); - gtk_button_set_label (GTK_BUTTON(be), g_strdup_printf (ngettext("Batch export %d selected object","Batch export %d selected objects",num), num)); + gtk_button_set_label (GTK_BUTTON(be), g_strdup_printf (ngettext("B_atch export %d selected object","B_atch export %d selected objects",num), num)); } else { gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON(be), FALSE); gtk_widget_set_sensitive (be, FALSE); diff --git a/src/ui/dialog/tile.cpp b/src/ui/dialog/tile.cpp index fccf5c105..4b994335e 100644 --- a/src/ui/dialog/tile.cpp +++ b/src/ui/dialog/tile.cpp @@ -656,7 +656,8 @@ TileDialog::TileDialog() g_print("/n PerRox = %f PerCol = %f selcount = %d",PerRow,PerCol,selcount); #endif - NoOfRowsLabel.set_label(_("Rows:")); + NoOfRowsLabel.set_text_with_mnemonic(_("_Rows:")); + NoOfRowsLabel.set_mnemonic_widget(NoOfRowsSpinner); NoOfRowsBox.pack_start(NoOfRowsLabel, false, false, MARGIN); NoOfRowsSpinner.set_digits(0); @@ -668,7 +669,8 @@ TileDialog::TileDialog() NoOfRowsBox.pack_start(NoOfRowsSpinner, false, false, MARGIN); gtk_size_group_add_widget(_col1, (GtkWidget *) NoOfRowsBox.gobj()); - RowHeightButton.set_label(_("Equal height")); + RowHeightButton.set_label(_("Equal _height")); + RowHeightButton.set_use_underline(true); double AutoRow = prefs->getDouble("/dialogs/gridtiler/AutoRowSize", 15); if (AutoRow>0) AutoRowSize=true; @@ -726,7 +728,8 @@ TileDialog::TileDialog() /*#### Number of columns ####*/ - NoOfColsLabel.set_label(_("Columns:")); + NoOfColsLabel.set_text_with_mnemonic(_("_Columns:")); + NoOfColsLabel.set_mnemonic_widget(NoOfColsSpinner); NoOfColsBox.pack_start(NoOfColsLabel, false, false, MARGIN); NoOfColsSpinner.set_digits(0); @@ -738,7 +741,8 @@ TileDialog::TileDialog() NoOfColsBox.pack_start(NoOfColsSpinner, false, false, MARGIN); gtk_size_group_add_widget(_col3, (GtkWidget *) NoOfColsBox.gobj()); - ColumnWidthButton.set_label(_("Equal width")); + ColumnWidthButton.set_label(_("Equal _width")); + ColumnWidthButton.set_use_underline(true); double AutoCol = prefs->getDouble("/dialogs/gridtiler/AutoColSize", 15); if (AutoCol>0) AutoColSize=true; @@ -793,13 +797,15 @@ TileDialog::TileDialog() { /*#### Radio buttons to control spacing manually or to fit selection bbox ####*/ - SpaceByBBoxRadioButton.set_label(_("Fit into selection box")); + SpaceByBBoxRadioButton.set_label(_("_Fit into selection box")); + SpaceByBBoxRadioButton.set_use_underline (true); SpaceByBBoxRadioButton.signal_toggled().connect(sigc::mem_fun(*this, &TileDialog::Spacing_button_changed)); SpacingGroup = SpaceByBBoxRadioButton.get_group(); SpacingVBox.pack_start(SpaceByBBoxRadioButton, false, false, MARGIN); - SpaceManualRadioButton.set_label(_("Set spacing:")); + SpaceManualRadioButton.set_label(_("_Set spacing:")); + SpaceManualRadioButton.set_use_underline (true); SpaceManualRadioButton.set_group(SpacingGroup); SpaceManualRadioButton.signal_toggled().connect(sigc::mem_fun(*this, &TileDialog::Spacing_button_changed)); SpacingVBox.pack_start(SpaceManualRadioButton, false, false, MARGIN); @@ -867,7 +873,8 @@ TileDialog::TileDialog() SizesHBox.set_sensitive (ManualSpacing); //## The OK button - TileOkButton = addResponseButton(Q_("tileClonesDialog|Arrange"), GTK_RESPONSE_APPLY); + TileOkButton = addResponseButton(C_("Rows and columns dialog","_Arrange"), GTK_RESPONSE_APPLY); + TileOkButton->set_use_underline(true); tips.set_tip((*TileOkButton), _("Arrange selected objects")); show_all_children(); diff --git a/src/verbs.cpp b/src/verbs.cpp index 4cdad7d36..1695a427e 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -2414,7 +2414,7 @@ Verb *Verb::_base_verbs[] = { // Advanced tutorial for more info new SelectionVerb(SP_VERB_SELECTION_BREAK_APART, "SelectionBreakApart", N_("Break _Apart"), N_("Break selected paths into subpaths"), INKSCAPE_ICON_PATH_BREAK_APART), - new SelectionVerb(SP_VERB_SELECTION_GRIDTILE, "DialogGridArrange", N_("Rows and Columns..."), + new SelectionVerb(SP_VERB_SELECTION_GRIDTILE, "DialogGridArrange", N_("Ro_ws and Columns..."), N_("Arrange selected objects in a table"), INKSCAPE_ICON_DIALOG_ROWS_AND_COLUMNS), /* Layer */ new LayerVerb(SP_VERB_LAYER_NEW, "LayerNew", N_("_Add Layer..."), -- cgit v1.2.3 From fbbff2ae01dbd79690a885e148add1204fddb063 Mon Sep 17 00:00:00 2001 From: Kris De Gussem Date: Wed, 29 Dec 2010 21:05:10 +0100 Subject: Mnemonics in "Input devices", and LPE dialogs (Bug 170765) (bzr r9990) --- src/live_effects/lpe-bendpath.cpp | 6 +++--- src/live_effects/lpe-constructgrid.cpp | 4 ++-- src/live_effects/lpe-envelope.cpp | 4 ++-- src/live_effects/lpe-gears.cpp | 4 ++-- src/ui/dialog/input.cpp | 4 ++-- src/verbs.cpp | 2 +- 6 files changed, 12 insertions(+), 12 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-bendpath.cpp b/src/live_effects/lpe-bendpath.cpp index 254500908..2d6bbeb22 100644 --- a/src/live_effects/lpe-bendpath.cpp +++ b/src/live_effects/lpe-bendpath.cpp @@ -53,9 +53,9 @@ namespace LivePathEffect { LPEBendPath::LPEBendPath(LivePathEffectObject *lpeobject) : Effect(lpeobject), bend_path(_("Bend path:"), _("Path along which to bend the original path"), "bendpath", &wr, this, "M0,0 L1,0"), - prop_scale(_("Width:"), _("Width of the path"), "prop_scale", &wr, this, 1), - scale_y_rel(_("Width in units of length"), _("Scale the width of the path in units of its length"), "scale_y_rel", &wr, this, false), - vertical_pattern(_("Original path is vertical"), _("Rotates the original 90 degrees, before bending it along the bend path"), "vertical", &wr, this, false) + prop_scale(_("_Width:"), _("Width of the path"), "prop_scale", &wr, this, 1), + scale_y_rel(_("W_idth in units of length"), _("Scale the width of the path in units of its length"), "scale_y_rel", &wr, this, false), + vertical_pattern(_("_Original path is vertical"), _("Rotates the original 90 degrees, before bending it along the bend path"), "vertical", &wr, this, false) { registerParameter( dynamic_cast(&bend_path) ); registerParameter( dynamic_cast(&prop_scale) ); diff --git a/src/live_effects/lpe-constructgrid.cpp b/src/live_effects/lpe-constructgrid.cpp index aee4c127a..cb9c031aa 100644 --- a/src/live_effects/lpe-constructgrid.cpp +++ b/src/live_effects/lpe-constructgrid.cpp @@ -23,8 +23,8 @@ using namespace Geom; LPEConstructGrid::LPEConstructGrid(LivePathEffectObject *lpeobject) : Effect(lpeobject), - nr_x(_("Size X:"), _("The size of the grid in X direction."), "nr_x", &wr, this, 5), - nr_y(_("Size Y:"), _("The size of the grid in Y direction."), "nr_y", &wr, this, 5) + nr_x(_("Size _X:"), _("The size of the grid in X direction."), "nr_x", &wr, this, 5), + nr_y(_("Size _Y:"), _("The size of the grid in Y direction."), "nr_y", &wr, this, 5) { registerParameter( dynamic_cast(&nr_x) ); registerParameter( dynamic_cast(&nr_y) ); diff --git a/src/live_effects/lpe-envelope.cpp b/src/live_effects/lpe-envelope.cpp index bd1cc5861..49f294498 100644 --- a/src/live_effects/lpe-envelope.cpp +++ b/src/live_effects/lpe-envelope.cpp @@ -34,8 +34,8 @@ LPEEnvelope::LPEEnvelope(LivePathEffectObject *lpeobject) : bend_path2(_("Right bend path:"), _("Right path along which to bend the original path"), "bendpath2", &wr, this, "M0,0 L1,0"), bend_path3(_("Bottom bend path:"), _("Bottom path along which to bend the original path"), "bendpath3", &wr, this, "M0,0 L1,0"), bend_path4(_("Left bend path:"), _("Left path along which to bend the original path"), "bendpath4", &wr, this, "M0,0 L1,0"), - xx(_("Enable left & right paths"), _("Enable the left and right deformation paths"), "xx", &wr, this, true), - yy(_("Enable top & bottom paths"), _("Enable the top and bottom deformation paths"), "yy", &wr, this, true) + xx(_("E_nable left & right paths"), _("Enable the left and right deformation paths"), "xx", &wr, this, true), + yy(_("_Enable top & bottom paths"), _("Enable the top and bottom deformation paths"), "yy", &wr, this, true) { registerParameter( dynamic_cast(&yy) ); registerParameter( dynamic_cast(&xx) ); diff --git a/src/live_effects/lpe-gears.cpp b/src/live_effects/lpe-gears.cpp index c9bbde8f2..337beb516 100644 --- a/src/live_effects/lpe-gears.cpp +++ b/src/live_effects/lpe-gears.cpp @@ -209,8 +209,8 @@ namespace LivePathEffect { LPEGears::LPEGears(LivePathEffectObject *lpeobject) : Effect(lpeobject), - teeth(_("Teeth:"), _("The number of teeth"), "teeth", &wr, this, 10), - phi(_("Phi:"), _("Tooth pressure angle (typically 20-25 deg). The ratio of teeth not in contact."), "phi", &wr, this, 5) + teeth(_("_Teeth:"), _("The number of teeth"), "teeth", &wr, this, 10), + phi(_("_Phi:"), _("Tooth pressure angle (typically 20-25 deg). The ratio of teeth not in contact."), "phi", &wr, this, 5) { /* Tooth pressure angle: The angle between the tooth profile and a perpendicular to the pitch * circle, usually at the point where the pitch circle meets the tooth profile. Standard angles diff --git a/src/ui/dialog/input.cpp b/src/ui/dialog/input.cpp index 8f19c90c4..34d55a440 100644 --- a/src/ui/dialog/input.cpp +++ b/src/ui/dialog/input.cpp @@ -877,8 +877,8 @@ InputDialogImpl::ConfPanel::ConfPanel() : tree(store), treeScroller(), watcher(*this), - useExt(_("Use pressure-sensitive tablet (requires restart)")), - save(_("Save")) + useExt(_("_Use pressure-sensitive tablet (requires restart)"), true), + save(_("_Save"), true) { pack_start(treeScroller); diff --git a/src/verbs.cpp b/src/verbs.cpp index 1695a427e..33c52706b 100644 --- a/src/verbs.cpp +++ b/src/verbs.cpp @@ -2673,7 +2673,7 @@ Verb *Verb::_base_verbs[] = { N_("Query information about extensions"), NULL), new DialogVerb(SP_VERB_DIALOG_LAYERS, "DialogLayers", N_("Layer_s..."), N_("View Layers"), INKSCAPE_ICON_DIALOG_LAYERS), - new DialogVerb(SP_VERB_DIALOG_LIVE_PATH_EFFECT, "DialogLivePathEffect", N_("Path Effect Editor..."), + new DialogVerb(SP_VERB_DIALOG_LIVE_PATH_EFFECT, "DialogLivePathEffect", N_("Path E_ffect Editor..."), N_("Manage, edit, and apply path effects"), NULL), new DialogVerb(SP_VERB_DIALOG_FILTER_EFFECTS, "DialogFilterEffects", N_("Filter Editor..."), N_("Manage, edit, and apply SVG filters"), NULL), -- cgit v1.2.3 From 1cc8be7b772d1609b85e57c4dc378c0c00368823 Mon Sep 17 00:00:00 2001 From: Adib Taraben Date: Thu, 30 Dec 2010 04:01:03 +0100 Subject: check for element modification before filling undo stack Fixed bugs: - https://launchpad.net/bugs/510618 (bzr r9991) --- src/widgets/toolbox.cpp | 108 ++++++++++++++++++++++++++++++++---------------- 1 file changed, 72 insertions(+), 36 deletions(-) (limited to 'src') diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index 8a616d002..f72b0d907 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -6185,7 +6185,7 @@ static void sp_print_font( SPStyle *query ) { << (query->text->font_specification.value ? query->text->font_specification.value : "No value") << std::endl; } - + static void sp_print_fontweight( SPStyle *query ) { const gchar* names[] = {"100", "200", "300", "400", "500", "600", "700", "800", "900", "NORMAL", "BOLD", "LIGHTER", "BOLDER", "Out of range"}; @@ -6385,8 +6385,10 @@ static void sp_text_fontfamily_value_changed( Ink_ComboBoxEntry_Action *act, GOb g_free (family); // Save for undo - DocumentUndo::done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT, + if (result_fontspec != QUERY_STYLE_NOTHING) { + DocumentUndo::done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT, _("Text: Change font family")); + } sp_repr_css_attr_unref (css); // unfreeze @@ -6431,10 +6433,6 @@ static void sp_text_fontsize_value_changed( Ink_ComboBoxEntry_Action *act, GObje SPDesktop *desktop = SP_ACTIVE_DESKTOP; sp_desktop_set_style (desktop, css, true, true); - // Save for undo - DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:size", SP_VERB_NONE, - _("Text: Change font size")); - // If no selected objects, set default. SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); int result_numbers = @@ -6443,7 +6441,12 @@ static void sp_text_fontsize_value_changed( Ink_ComboBoxEntry_Action *act, GObje { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->mergeStyle("/tools/text/style", css); + } else { + // Save for undo + DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:size", SP_VERB_NONE, + _("Text: Change font size")); } + sp_style_unref(query); sp_repr_css_attr_unref (css); @@ -6578,8 +6581,10 @@ static void sp_text_style_changed( InkToggleAction* act, GObject *tbl ) // Do we need to update other CSS values? SPDesktop *desktop = SP_ACTIVE_DESKTOP; sp_desktop_set_style (desktop, css, true, true); - DocumentUndo::done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT, + if (result_fontspec != QUERY_STYLE_NOTHING) { + DocumentUndo::done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT, _("Text: Change font style")); + } sp_repr_css_attr_unref (css); g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); @@ -6655,9 +6660,10 @@ static void sp_text_script_changed( InkToggleAction* act, GObject *tbl ) sp_desktop_set_style (desktop, css, true, false); // Save for undo - DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:script", SP_VERB_NONE, + if(result_baseline != QUERY_STYLE_NOTHING) { + DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:script", SP_VERB_NONE, _("Text: Change superscript or subscript")); - + } g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } @@ -6799,8 +6805,11 @@ static void sp_text_align_mode_changed( EgeSelectOneAction *act, GObject *tbl ) sp_style_unref(query); sp_desktop_set_style (desktop, css, true, true); - DocumentUndo::done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT, + if (result_numbers != QUERY_STYLE_NOTHING) + { + DocumentUndo::done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT, _("Text: Change alignment")); + } sp_repr_css_attr_unref (css); gtk_widget_grab_focus (GTK_WIDGET(desktop->canvas)); @@ -6831,15 +6840,19 @@ static void sp_text_lineheight_value_changed( GtkAdjustment *adj, GObject *tbl ) // Until deprecated sodipodi:linespacing purged: Inkscape::Selection *selection = sp_desktop_selection(desktop); GSList const *items = selection->itemList(); + bool modmade = false; for (; items != NULL; items = items->next) { if (SP_IS_TEXT (items->data)) { SP_OBJECT_REPR(items->data)->setAttribute("sodipodi:linespacing", sp_repr_css_property (css, "line-height", NULL)); + modmade = true; } } // Save for undo - DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:line-height", SP_VERB_NONE, + if(modmade) { + DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:line-height", SP_VERB_NONE, _("Text: Change line-height")); + } // If no selected objects, set default. SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); @@ -6876,10 +6889,6 @@ static void sp_text_wordspacing_value_changed( GtkAdjustment *adj, GObject *tbl SPDesktop *desktop = SP_ACTIVE_DESKTOP; sp_desktop_set_style (desktop, css, true, false); - // Save for undo - DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:word-spacing", SP_VERB_NONE, - _("Text: Change word-spacing")); - // If no selected objects, set default. SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); int result_numbers = @@ -6888,6 +6897,10 @@ static void sp_text_wordspacing_value_changed( GtkAdjustment *adj, GObject *tbl { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->mergeStyle("/tools/text/style", css); + } else { + // Save for undo + DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:word-spacing", SP_VERB_NONE, + _("Text: Change word-spacing")); } sp_style_unref(query); @@ -6915,9 +6928,6 @@ static void sp_text_letterspacing_value_changed( GtkAdjustment *adj, GObject *tb SPDesktop *desktop = SP_ACTIVE_DESKTOP; sp_desktop_set_style (desktop, css, true, false); - // Save for undo - DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:letter-spacing", SP_VERB_NONE, - _("Text: Change letter-spacing")); // If no selected objects, set default. SPStyle *query = sp_style_new (SP_ACTIVE_DOCUMENT); @@ -6928,8 +6938,16 @@ static void sp_text_letterspacing_value_changed( GtkAdjustment *adj, GObject *tb Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->mergeStyle("/tools/text/style", css); } + else + { + // Save for undo + DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:letter-spacing", SP_VERB_NONE, + _("Text: Change letter-spacing")); + } + sp_style_unref(query); + sp_repr_css_attr_unref (css); g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); @@ -6945,6 +6963,7 @@ static void sp_text_dx_value_changed( GtkAdjustment *adj, GObject *tbl ) g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); gdouble new_dx = adj->value; + bool modmade = false; if( SP_IS_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context) ) { SPTextContext *const tc = SP_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context); @@ -6956,14 +6975,16 @@ static void sp_text_dx_value_changed( GtkAdjustment *adj, GObject *tbl ) double old_dx = attributes->getDx( char_index ); double delta_dx = new_dx - old_dx; sp_te_adjust_dx( tc->text, tc->text_sel_start, tc->text_sel_end, SP_ACTIVE_DESKTOP, delta_dx ); + modmade = true; } } } - // Save for undo - DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:dx", SP_VERB_NONE, + if(modmade) { + // Save for undo + DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:dx", SP_VERB_NONE, _("Text: Change dx (kern)")); - + } g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } @@ -6976,6 +6997,7 @@ static void sp_text_dy_value_changed( GtkAdjustment *adj, GObject *tbl ) g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE) ); gdouble new_dy = adj->value; + bool modmade = false; if( SP_IS_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context) ) { SPTextContext *const tc = SP_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context); @@ -6987,13 +7009,16 @@ static void sp_text_dy_value_changed( GtkAdjustment *adj, GObject *tbl ) double old_dy = attributes->getDy( char_index ); double delta_dy = new_dy - old_dy; sp_te_adjust_dy( tc->text, tc->text_sel_start, tc->text_sel_end, SP_ACTIVE_DESKTOP, delta_dy ); + modmade = true; } } } - // Save for undo - DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:dy", SP_VERB_NONE, + if(modmade) { + // Save for undo + DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:dy", SP_VERB_NONE, _("Text: Change dy")); + } g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } @@ -7008,6 +7033,7 @@ static void sp_text_rotation_value_changed( GtkAdjustment *adj, GObject *tbl ) gdouble new_degrees = adj->value; + bool modmade = false; if( SP_IS_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context) ) { SPTextContext *const tc = SP_TEXT_CONTEXT((SP_ACTIVE_DESKTOP)->event_context); if( tc ) { @@ -7018,13 +7044,16 @@ static void sp_text_rotation_value_changed( GtkAdjustment *adj, GObject *tbl ) double old_degrees = attributes->getRotate( char_index ); double delta_deg = new_degrees - old_degrees; sp_te_adjust_rotation( tc->text, tc->text_sel_start, tc->text_sel_end, SP_ACTIVE_DESKTOP, delta_deg ); - } + modmade = true; + } } } // Save for undo - DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:rotate", SP_VERB_NONE, + if(modmade) { + DocumentUndo::maybeDone(sp_desktop_document(SP_ACTIVE_DESKTOP), "ttb:rotate", SP_VERB_NONE, _("Text: Change rotate")); + } g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } @@ -7068,8 +7097,11 @@ static void sp_text_orientation_mode_changed( EgeSelectOneAction *act, GObject * } sp_desktop_set_style (SP_ACTIVE_DESKTOP, css, true, true); - DocumentUndo::done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT, + if(result_numbers != QUERY_STYLE_NOTHING) + { + DocumentUndo::done(sp_desktop_document(SP_ACTIVE_DESKTOP), SP_VERB_CONTEXT_TEXT, _("Text: Change orientation")); + } sp_repr_css_attr_unref (css); g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); @@ -7217,7 +7249,7 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ // Superscript gboolean superscriptSet = - ((result_baseline == QUERY_STYLE_SINGLE || result_baseline == QUERY_STYLE_MULTIPLE_SAME ) && + ((result_baseline == QUERY_STYLE_SINGLE || result_baseline == QUERY_STYLE_MULTIPLE_SAME ) && query->baseline_shift.set && query->baseline_shift.type == SP_BASELINE_SHIFT_LITERAL && query->baseline_shift.literal == SP_CSS_BASELINE_SHIFT_SUPER ); @@ -7228,7 +7260,7 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ // Subscript gboolean subscriptSet = - ((result_baseline == QUERY_STYLE_SINGLE || result_baseline == QUERY_STYLE_MULTIPLE_SAME ) && + ((result_baseline == QUERY_STYLE_SINGLE || result_baseline == QUERY_STYLE_MULTIPLE_SAME ) && query->baseline_shift.set && query->baseline_shift.type == SP_BASELINE_SHIFT_LITERAL && query->baseline_shift.literal == SP_CSS_BASELINE_SHIFT_SUB ); @@ -7302,7 +7334,7 @@ static void sp_text_toolbox_selection_changed(Inkscape::Selection */*selection*/ double letterSpacing; if (query->letter_spacing.normal) letterSpacing = 0.0; else letterSpacing = query->letter_spacing.computed; // Assume no units (change in desktop-style.cpp) - + GtkAction* letterSpacingAction = GTK_ACTION( g_object_get_data( tbl, "TextLetterSpacingAction" ) ); GtkAdjustment *letterSpacingAdjustment = ege_adjustment_action_get_adjustment(EGE_ADJUSTMENT_ACTION( letterSpacingAction )); @@ -7913,10 +7945,11 @@ static void sp_connector_orthogonal_toggled( GtkToggleAction* act, GObject *tbl if (!modmade) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setBool("/tools/connector/orthogonal", is_orthog); - } + } else { - DocumentUndo::done(doc, SP_VERB_CONTEXT_CONNECTOR, + DocumentUndo::done(doc, SP_VERB_CONTEXT_CONNECTOR, is_orthog ? _("Set connector type: orthogonal"): _("Set connector type: polyline")); + } g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } @@ -7962,9 +7995,10 @@ static void connector_curvature_changed(GtkAdjustment *adj, GObject* tbl) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->setDouble(Glib::ustring("/tools/connector/curvature"), newValue); } - - DocumentUndo::done(doc, SP_VERB_CONTEXT_CONNECTOR, + else { + DocumentUndo::done(doc, SP_VERB_CONTEXT_CONNECTOR, _("Change connector curvature")); + } g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } @@ -7999,21 +8033,23 @@ static void connector_spacing_changed(GtkAdjustment *adj, GObject* tbl) sp_repr_set_css_double(repr, "inkscape:connector-spacing", adj->value); SP_OBJECT(desktop->namedview)->updateRepr(); + bool modmade = false; GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop); for ( GSList const *iter = items ; iter != NULL ; iter = iter->next ) { SPItem *item = reinterpret_cast(iter->data); Geom::Matrix m = Geom::identity(); avoid_item_move(&m, item); + modmade = true; } if (items) { g_slist_free(items); } - - DocumentUndo::done(doc, SP_VERB_CONTEXT_CONNECTOR, + if(modmade) { + DocumentUndo::done(doc, SP_VERB_CONTEXT_CONNECTOR, _("Change connector spacing")); - + } g_object_set_data( tbl, "freeze", GINT_TO_POINTER(FALSE) ); } -- cgit v1.2.3 From 14e173d4dce197988118767de0de5c05601e1a1d Mon Sep 17 00:00:00 2001 From: Alvin Penner Date: Mon, 3 Jan 2011 19:36:56 -0500 Subject: disable Rectangle and Ellipse (Bug 407394) Fixed bugs: - https://launchpad.net/bugs/407394 (bzr r9995) --- src/extension/internal/emf-win32-print.cpp | 32 +++++++++++++++--------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'src') diff --git a/src/extension/internal/emf-win32-print.cpp b/src/extension/internal/emf-win32-print.cpp index 6be48e44c..c7f8e3d4c 100644 --- a/src/extension/internal/emf-win32-print.cpp +++ b/src/extension/internal/emf-win32-print.cpp @@ -681,24 +681,24 @@ PrintEmfWin32::print_simple_shape(Geom::PathVector const &pathv, const Geom::Mat if (moves == 1 && moves+lines == nodes && closed) { polygon = true; - if (nodes==5) { - if (lpPoints[0].x == lpPoints[3].x && lpPoints[1].x == lpPoints[2].x && - lpPoints[0].y == lpPoints[1].y && lpPoints[2].y == lpPoints[3].y) - { - rectangle = true; - } - } +// if (nodes==5) { // disable due to LP Bug 407394 +// if (lpPoints[0].x == lpPoints[3].x && lpPoints[1].x == lpPoints[2].x && +// lpPoints[0].y == lpPoints[1].y && lpPoints[2].y == lpPoints[3].y) +// { +// rectangle = true; +// } +// } } else if (moves == 1 && nodes == 5 && moves+curves == nodes && closed) { - if (lpPoints[0].x == lpPoints[1].x && lpPoints[1].x == lpPoints[11].x && - lpPoints[5].x == lpPoints[6].x && lpPoints[6].x == lpPoints[7].x && - lpPoints[2].x == lpPoints[10].x && lpPoints[3].x == lpPoints[9].x && lpPoints[4].x == lpPoints[8].x && - lpPoints[2].y == lpPoints[3].y && lpPoints[3].y == lpPoints[4].y && - lpPoints[8].y == lpPoints[9].y && lpPoints[9].y == lpPoints[10].y && - lpPoints[5].y == lpPoints[1].y && lpPoints[6].y == lpPoints[0].y && lpPoints[7].y == lpPoints[11].y) - { - ellipse = true; - } +// if (lpPoints[0].x == lpPoints[1].x && lpPoints[1].x == lpPoints[11].x && +// lpPoints[5].x == lpPoints[6].x && lpPoints[6].x == lpPoints[7].x && +// lpPoints[2].x == lpPoints[10].x && lpPoints[3].x == lpPoints[9].x && lpPoints[4].x == lpPoints[8].x && +// lpPoints[2].y == lpPoints[3].y && lpPoints[3].y == lpPoints[4].y && +// lpPoints[8].y == lpPoints[9].y && lpPoints[9].y == lpPoints[10].y && +// lpPoints[5].y == lpPoints[1].y && lpPoints[6].y == lpPoints[0].y && lpPoints[7].y == lpPoints[11].y) +// { // disable due to LP Bug 407394 +// ellipse = true; +// } } if (polygon || ellipse) { -- cgit v1.2.3 From 8dd5757453e95dab25c2e3bc5aafde76cfe571e7 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Wed, 5 Jan 2011 20:48:47 +0100 Subject: Filters. Custom predefined filters update and new ABC filters. (bzr r9996) --- src/extension/internal/filter/abc.h | 324 +++++++++++++++++++++++++++ src/extension/internal/filter/color.h | 20 +- src/extension/internal/filter/drop-shadow.h | 4 +- src/extension/internal/filter/experimental.h | 232 +++++++++++-------- src/extension/internal/filter/filter-all.cpp | 12 +- src/extension/internal/filter/morphology.h | 6 +- 6 files changed, 482 insertions(+), 116 deletions(-) create mode 100755 src/extension/internal/filter/abc.h mode change 100644 => 100755 src/extension/internal/filter/color.h mode change 100644 => 100755 src/extension/internal/filter/experimental.h mode change 100644 => 100755 src/extension/internal/filter/filter-all.cpp (limited to 'src') diff --git a/src/extension/internal/filter/abc.h b/src/extension/internal/filter/abc.h new file mode 100755 index 000000000..c93bbb7f7 --- /dev/null +++ b/src/extension/internal/filter/abc.h @@ -0,0 +1,324 @@ +#ifndef __INKSCAPE_EXTENSION_INTERNAL_FILTER_ABC_H__ +#define __INKSCAPE_EXTENSION_INTERNAL_FILTER_ABC_H__ +/* Change the 'ABC' above to be your file name */ + +/* + * Copyright (C) 2011 Authors: + * Ivan Louette (filters) + * Nicolas Dufour (UI) + * + * Basic filters + * Blur + * Diffuse light + * Roughen + * Specular light + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ +/* ^^^ Change the copyright to be you and your e-mail address ^^^ */ + +#include "filter.h" + +#include "extension/internal/clear-n_.h" +#include "extension/system.h" +#include "extension/extension.h" + +namespace Inkscape { +namespace Extension { +namespace Internal { +namespace Filter { + +/** + \brief Custom predefined Blur filter. + + Simple horizontal and vertical blur. + + Filter's parameters: + * Horizontal blur (0.01->100., default 2) -> blur (stdDeviation) + * Vertical blur (0.01->100., default 2) -> blur (stdDeviation) +*/ + +class Blur : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + Blur ( ) : Filter() { }; + virtual ~Blur ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Blur, custom (ABCs)") "\n" + "org.inkscape.effect.filter.blur\n" + "2\n" + "2\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Simple vertical and horizontal blur effect") "\n" + "\n" + "\n", new Blur()); + }; + +}; + +gchar const * +Blur::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream hblur; + std::ostringstream vblur; + + hblur << ext->get_param_float("hblur"); + vblur << ext->get_param_float("vblur"); + + _filter = g_strdup_printf( + "\n" + "\n" + "\n", hblur.str().c_str(), vblur.str().c_str()); + + return _filter; +}; /* Blur filter */ + +/** + \brief Custom predefined Diffuse light filter. + + Basic diffuse bevel to use for building textures + + Filter's parameters: + * Smoothness (0.->10., default 6.) -> blur (stdDeviation) + * Elevation (0->360, default 25) -> feDistantLight (elevation) + * Azimuth (0->360, default 235) -> feDistantLight (azimuth) + * Lightning color (guint, default -1 [white]) -> diffuse (lighting-color) + + TODO: use the alpha channel to calculate the lightning color +*/ + +class DiffuseLight : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + DiffuseLight ( ) : Filter() { }; + virtual ~DiffuseLight ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Diffuse light, custom (ABCs)") "\n" + "org.inkscape.effect.filter.diffuselight\n" + "6\n" + "25\n" + "235\n" + "-1\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Basic diffuse bevel to use for building textures") "\n" + "\n" + "\n", new DiffuseLight()); + }; + +}; + +gchar const * +DiffuseLight::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream smooth; + std::ostringstream elevation; + std::ostringstream azimuth; + std::ostringstream r; + std::ostringstream g; + std::ostringstream b; + std::ostringstream a; + + smooth << ext->get_param_float("smooth"); + elevation << ext->get_param_int("elevation"); + azimuth << ext->get_param_int("azimuth"); + guint32 color = ext->get_param_color("color"); + + r << ((color >> 24) & 0xff); + g << ((color >> 16) & 0xff); + b << ((color >> 8) & 0xff); + a << (color & 0xff) / 255.0F; + + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n", smooth.str().c_str(), r.str().c_str(), g.str().c_str(), b.str().c_str(), elevation.str().c_str(), azimuth.str().c_str(), a.str().c_str()); + + return _filter; +}; /* DiffuseLight filter */ + +/** + \brief Custom predefined Roughen filter. + + Small-scale roughening to edges and content + + Filter's parameters: + * Frequency (*100) (0.0->40., default 1.3) -> turbulence (baseFrequency) + * Intensity (0.0->50., default 6.6) -> displacement (scale) +*/ + +class Roughen : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + Roughen ( ) : Filter() { }; + virtual ~Roughen ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Roughen, custom (ABCs)") "\n" + "org.inkscape.effect.filter.roughen\n" + "1.3\n" + "1.3\n" + "6.6\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Small-scale roughening to edges and content") "\n" + "\n" + "\n", new Roughen()); + }; + +}; + +gchar const * +Roughen::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream hfreq; + std::ostringstream vfreq; + std::ostringstream intensity; + + hfreq << (ext->get_param_float("hfreq") / 100); + vfreq << (ext->get_param_float("vfreq") / 100); + intensity << ext->get_param_float("intensity"); + + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n", hfreq.str().c_str(), vfreq.str().c_str(), intensity.str().c_str()); + + return _filter; +}; /* Roughen filter */ + +/** + \brief Custom predefined Specular light filter. + + Basic specular bevel to use for building textures + + Filter's parameters: + * Smoothness (0.0->10., default 6.) -> blur (stdDeviation) + * Brightness (0.0->5., default 1.) -> specular (specularConstant) + * Elevation (0->360, default 25) -> feDistantLight (elevation) + * Azimuth (0->360, default 235) -> feDistantLight (azimuth) + * Lightning color (guint, default -1 [white]) -> specular (lighting-color) + + TODO: use the alpha channel to calculate the lightning color (but do we really need a lightning color here?) +*/ + +class SpecularLight : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + SpecularLight ( ) : Filter() { }; + virtual ~SpecularLight ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Specular light, custom (ABCs)") "\n" + "org.inkscape.effect.filter.specularlight\n" + "6\n" + "1\n" + "45\n" + "235\n" + "-1\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Basic specular bevel to use for building textures") "\n" + "\n" + "\n", new SpecularLight()); + }; + +}; + +gchar const * +SpecularLight::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream smooth; + std::ostringstream bright; + std::ostringstream elevation; + std::ostringstream azimuth; + std::ostringstream r; + std::ostringstream g; + std::ostringstream b; + std::ostringstream a; + + smooth << ext->get_param_float("smooth"); + bright << ext->get_param_float("bright"); + elevation << ext->get_param_int("elevation"); + azimuth << ext->get_param_int("azimuth"); + guint32 color = ext->get_param_color("color"); + + r << ((color >> 24) & 0xff); + g << ((color >> 16) & 0xff); + b << ((color >> 8) & 0xff); + a << (color & 0xff) / 255.0F; + + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n", smooth.str().c_str(), bright.str().c_str(), r.str().c_str(), g.str().c_str(), b.str().c_str(), elevation.str().c_str(), azimuth.str().c_str(), a.str().c_str()); + + return _filter; +}; /* SpecularLight filter */ + + +}; /* namespace Filter */ +}; /* namespace Internal */ +}; /* namespace Extension */ +}; /* namespace Inkscape */ + +/* Change the 'COLOR' below to be your file name */ +#endif /* __INKSCAPE_EXTENSION_INTERNAL_FILTER_ABC_H__ */ diff --git a/src/extension/internal/filter/color.h b/src/extension/internal/filter/color.h old mode 100644 new mode 100755 index 54312685c..05173b684 --- a/src/extension/internal/filter/color.h +++ b/src/extension/internal/filter/color.h @@ -54,7 +54,7 @@ public: static void init (void) { Inkscape::Extension::build_from_mem( "\n" - "" N_("Colorize, custom -EXP-") "\n" + "" N_("Colorize, custom (color)") "\n" "org.inkscape.effect.filter.Colorize\n" "0\n" "1\n" @@ -119,7 +119,7 @@ Colorize::get_filter_text (Inkscape::Extension::Extension * ext) duotone << "1"; _filter = g_strdup_printf( - "\n" + "\n" "\n" "\n" "\n" @@ -156,7 +156,7 @@ public: static void init (void) { Inkscape::Extension::build_from_mem( "\n" - "" N_("Duochrome, custom -EXP-") "\n" + "" N_("Duochrome, custom (color)") "\n" "org.inkscape.effect.filter.Duochrome\n" "\n" "\n" @@ -241,7 +241,7 @@ Duochrome::get_filter_text (Inkscape::Extension::Extension * ext) } _filter = g_strdup_printf( - "\n" + "\n" "\n" "\n" "\n" @@ -282,7 +282,7 @@ public: static void init (void) { Inkscape::Extension::build_from_mem( "\n" - "" N_("Quadritone fantasy, custom -EXP-") "\n" + "" N_("Quadritone fantasy, custom (color)") "\n" "org.inkscape.effect.filter.Quadritone\n" "280\n" "100\n" @@ -331,7 +331,7 @@ Quadritone::get_filter_text (Inkscape::Extension::Extension * ext) blend2 << ext->get_param_enum("blend2"); _filter = g_strdup_printf( - "\n" + "\n" "\n" "\n" "\n" @@ -369,7 +369,7 @@ public: static void init (void) { Inkscape::Extension::build_from_mem( "\n" - "" N_("Solarize, custom -EXP-") "\n" + "" N_("Solarize, custom (color)") "\n" "org.inkscape.effect.filter.Solarize\n" "0\n" "\n" @@ -412,7 +412,7 @@ Solarize::get_filter_text (Inkscape::Extension::Extension * ext) } _filter = g_strdup_printf( - "\n" + "\n" "\n" "\n" "\n" @@ -456,7 +456,7 @@ public: static void init (void) { Inkscape::Extension::build_from_mem( "\n" - "" N_("Tritone, custom -EXP-") "\n" + "" N_("Tritone, custom (color)") "\n" "org.inkscape.effect.filter.Tritone\n" "\n" "\n" @@ -565,7 +565,7 @@ Tritone::get_filter_text (Inkscape::Extension::Extension * ext) } _filter = g_strdup_printf( - "\n" + "\n" "\n" "\n" "\n" diff --git a/src/extension/internal/filter/drop-shadow.h b/src/extension/internal/filter/drop-shadow.h index 0cd2a8eeb..22890d39a 100644 --- a/src/extension/internal/filter/drop-shadow.h +++ b/src/extension/internal/filter/drop-shadow.h @@ -152,7 +152,7 @@ public: static void init (void) { Inkscape::Extension::build_from_mem( "\n" - "" N_("Drop shadow, color -EXP-") "\n" + "" N_("Drop shadow, color") "\n" "org.inkscape.effect.filter.colorizable-drop-shadow\n" "3.0\n" "6.0\n" @@ -196,7 +196,7 @@ ColorizableDropShadow::get_filter_text (Inkscape::Extension::Extension * ext) b << ((color >> 8) & 0xff); _filter = g_strdup_printf( - "\n" + "\n" "\n" "\n" "\n" diff --git a/src/extension/internal/filter/experimental.h b/src/extension/internal/filter/experimental.h old mode 100644 new mode 100755 index a8879720b..acd258805 --- a/src/extension/internal/filter/experimental.h +++ b/src/extension/internal/filter/experimental.h @@ -3,7 +3,7 @@ /* Change the 'EXPERIMENTAL' above to be your file name */ /* - * Copyright (C) 2010 Authors: + * Copyright (C) 2011 Authors: * Ivan Louette (filters) * Nicolas Dufour (UI) * @@ -11,7 +11,7 @@ * Chromolitho * Drawing * Posterize - * Test filter (should no be used...) + * Posterize basic * * Released under GNU GPL, read the file 'COPYING' for more information */ @@ -38,8 +38,7 @@ namespace Filter { * Transparent (boolean, default unchecked) -> Checked = colormatrix5 (in="colormatrix4"), Unchecked = colormatrix5 (in="component1") * Invert (boolean, default false) -> component1 (tableValues) [adds a trailing 0] * Dented (boolean, default false) -> component1 (tableValues) [adds intermediate 0s] - * Expand white (0->5, default 1) -> component1 (tableValues) [0="0 1", 5="0 1 1 1 1 1 1"] - * Lightness (0->10, default 0) -> composite1 (k1) + * Lightness (0.->10., default 0.) -> composite1 (k1) * Saturation (0.->1., default 1.) -> colormatrix3 (values) * Noise reduction (1->1000, default 20) -> convolve (kernelMatrix, central value -1001->-2000, default -1020) * Drawing blend (enum, default Normal) -> blend1 (mode) @@ -65,24 +64,24 @@ public: static void init (void) { Inkscape::Extension::build_from_mem( "\n" - "" N_("Chromolitho, custom -EXP-") "\n" + "" N_("Chromolitho, custom") "\n" "org.inkscape.effect.filter.Chromolitho\n" "\n" "\n" "true\n" "\n" + "<_item value=\"darken\">Darken\n" "<_item value=\"normal\">Normal\n" "<_item value=\"multiply\">Multiply\n" "<_item value=\"screen\">Screen\n" "<_item value=\"lighten\">Lighten\n" - "<_item value=\"darken\">Darken\n" "\n" "false\n" "false\n" "false\n" - "0\n" + "0\n" "1\n" - "20\n" + "10\n" "1\n" "\n" "\n" @@ -149,7 +148,7 @@ Chromolitho::get_filter_text (Inkscape::Extension::Extension * ext) col3in << "colormatrix4"; else col3in << "component1"; - light << ext->get_param_int("light"); + light << ext->get_param_float("light"); saturation << ext->get_param_float("saturation"); noise << (-1000 - ext->get_param_int("noise")); dblend << ext->get_param_enum("dblend"); @@ -180,8 +179,7 @@ Chromolitho::get_filter_text (Inkscape::Extension::Extension * ext) graincol << "0"; _filter = g_strdup_printf( - "\n" - + "\n" "\n" "\n" "\n" @@ -210,21 +208,24 @@ Chromolitho::get_filter_text (Inkscape::Extension::Extension * ext) Convert images to duochrome drawings. Filter's parameters: - * Simplification (0.01->10, default 0.7) -> blur1 (stdDeviation) - * Lightness (0->50, default 5) -> convolve (kernelMatrix, central value -1000->-1050, default -1005) - * Smoothness (0.01->10, default 0.7) -> blur2 (stdDeviation) - * Dilatation (3->100, default 6) -> colormatrix3 (n-1th value) - - * Blur (0.01->10., default 1.) -> blur3 (stdDeviation) - * Blur spread (3->20, default 6) -> colormatrix5 (n-1th value) - * Blur erosion (-2->0, default -2) -> colormatrix5 (nth value) - - * Stroke color (guint, default 205,0,0) -> flood2 (flood-opacity, flood-color) - * Image on stroke (boolean, default false) -> composite1 (in="flood2" true-> in="SourceGraphic") - * Image on stroke opacity (0.->1., default 1) -> composite3 (k3) - * Fill color (guint, default 255,203,0) -> flood3 (flood-opacity, flood-color) - * Image on fill (boolean, default false) -> composite2 (in="flood3" true-> in="SourceGraphic") - * Image on fill opacity (0.->1., default 1) -> composite3 (k2) + * Simplification (0.01->20, default 0.6) -> blur1 (stdDeviation) + * Lightness (1->500, default 10) -> convolve1 (kernelMatrix, central value -1001->-1500, default -1010) + * Fading (0.->6., default 0) -> composite1 (k4) + * Smoothness (0.01->20, default 0.6) -> blur2 (stdDeviation) + * Dilatation (1->50, default 6) -> color2 (n-1th value) + * Erosion (0->50, default 3) -> color2 (nth value 0->-50) + * Transluscent (boolean, default false) -> composite 8 (in, true->merge1, false->composite7) + * Offset (-100->100, default 0) -> offset (val) + + * Blur (0.01->20., default 1.) -> blur3 (stdDeviation) + * Blur spread (1->50, default 6) -> color4 (n-1th value) + * Blur erosion (0->50, default 3) -> color4 (nth value 0->-50) + + * Stroke color (guint, default 64,64,64,255) -> flood2 (flood-color), composite3 (k2) + * Image on stroke (boolean, default false) -> composite2 (in="flood2" true-> in="SourceGraphic") + * Fill color (guint, default 200,200,200,255) -> flood3 (flood-opacity), composite5 (k2) + * Image on fill (boolean, default false) -> composite4 (in="flood3" true-> in="SourceGraphic") + */ class Drawing : public Inkscape::Extension::Internal::Filter::Filter { @@ -238,28 +239,30 @@ public: static void init (void) { Inkscape::Extension::build_from_mem( "\n" - "" N_("Drawing, custom -EXP-") "\n" + "" N_("Drawing, custom") "\n" "org.inkscape.effect.filter.Drawing\n" "\n" "\n" - "0.7\n" - "5\n" - "0.7\n" - "6\n" + "0.6\n" + "10\n" + "0\n" + "0.6\n" + "6\n" + "3\n" + "false\n" "<_param name=\"blurheader\" type=\"groupheader\">Blur\n" - "1\n" - "6\n" - "-2\n" + "1\n" + "6\n" + "3\n" "\n" "\n" - "-3473153\n" + "-1515870721\n" "false\n" - "1\n" "\n" "\n" - "-855637761\n" + "589505535\n" "false\n" - "1\n" + "0\n" "\n" "\n" "\n" @@ -282,32 +285,41 @@ Drawing::get_filter_text (Inkscape::Extension::Extension * ext) std::ostringstream simply; std::ostringstream light; + std::ostringstream fade; std::ostringstream smooth; std::ostringstream dilat; - std::ostringstream blur; - std::ostringstream spread; std::ostringstream erosion; + std::ostringstream transluscent; + std::ostringstream offset; + std::ostringstream blur; + std::ostringstream bdilat; + std::ostringstream berosion; std::ostringstream strokea; std::ostringstream stroker; std::ostringstream strokeg; std::ostringstream strokeb; std::ostringstream ios; - std::ostringstream ioso; std::ostringstream filla; std::ostringstream fillr; std::ostringstream fillg; std::ostringstream fillb; std::ostringstream iof; - std::ostringstream iofo; simply << ext->get_param_float("simply"); light << (-1000 - ext->get_param_int("light")); + fade << (ext->get_param_float("fade") / 10); smooth << ext->get_param_float("smooth"); - dilat << ext->get_param_int("dilat"); - + dilat << ext->get_param_float("dilat"); + erosion << (- ext->get_param_float("erosion")); + if (ext->get_param_bool("transluscent")) + transluscent << "merge1"; + else + transluscent << "composite7"; + offset << ext->get_param_int("offset"); + blur << ext->get_param_float("blur"); - spread << ext->get_param_int("spread"); - erosion << ext->get_param_int("erosion"); + bdilat << ext->get_param_float("bdilat"); + berosion << (- ext->get_param_float("berosion")); guint32 fcolor = ext->get_param_color("fcolor"); fillr << ((fcolor >> 24) & 0xff); @@ -318,7 +330,6 @@ Drawing::get_filter_text (Inkscape::Extension::Extension * ext) iof << "SourceGraphic"; else iof << "flood3"; - iofo << ext->get_param_float("iofo"); guint32 scolor = ext->get_param_color("scolor"); stroker << ((scolor >> 24) & 0xff); @@ -329,34 +340,40 @@ Drawing::get_filter_text (Inkscape::Extension::Extension * ext) ios << "SourceGraphic"; else ios << "flood2"; - ioso << ext->get_param_float("ioso"); - + _filter = g_strdup_printf( - "\n" + "\n" "\n" - "\n" - "\n" - "\n" + "\n" + "\n" + "\n" "\n" - "\n" + "\n" "\n" - "\n" - "\n" - "\n" - "\n" - "\n" + "\n" + "\n" + "\n" + "\n" + "\n" "\n" "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n", simply.str().c_str(), light.str().c_str(), smooth.str().c_str(), dilat.str().c_str(), blur.str().c_str(), spread.str().c_str(), erosion.str().c_str(), strokea.str().c_str(), stroker.str().c_str(), strokeg.str().c_str(), strokeb.str().c_str(), ios.str().c_str(), filla.str().c_str(), fillr.str().c_str(), fillg.str().c_str(), fillb.str().c_str(), iof.str().c_str(), iofo.str().c_str(), ioso.str().c_str()); + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n", simply.str().c_str(), light.str().c_str(), fade.str().c_str(), smooth.str().c_str(), dilat.str().c_str(), erosion.str().c_str(), blur.str().c_str(), bdilat.str().c_str(), berosion.str().c_str(), stroker.str().c_str(), strokeg.str().c_str(), strokeb.str().c_str(), ios.str().c_str(), strokea.str().c_str(), offset.str().c_str(), offset.str().c_str(), fillr.str().c_str(), fillg.str().c_str(), fillb.str().c_str(), iof.str().c_str(), filla.str().c_str(), transluscent.str().c_str()); return _filter; }; /* Drawing filter */ @@ -384,7 +401,7 @@ public: static void init (void) { Inkscape::Extension::build_from_mem( "\n" - "" N_("Poster and painting, custom -EXP-") "\n" + "" N_("Poster and painting, custom") "\n" "org.inkscape.effect.filter.Posterize\n" "\n" "<_item value=\"normal\">Normal\n" @@ -400,8 +417,8 @@ public: "<_item value=\"normal\">Normal\n" "<_item value=\"darken\">Darken\n" "\n" - "4.0\n" - "0.5\n" + "4.0\n" + "0.5\n" "1.00\n" "1.00\n" "false\n" @@ -434,8 +451,8 @@ Posterize::get_filter_text (Inkscape::Extension::Extension * ext) table << ext->get_param_enum("table"); blendmode << ext->get_param_enum("blend"); - blur1 << ext->get_param_float("blur1") + 0.01; - blur2 << ext->get_param_float("blur2") + 0.01; + blur1 << ext->get_param_float("blur1"); + blur2 << ext->get_param_float("blur2"); presat << ext->get_param_float("presaturation"); postsat << ext->get_param_float("postsaturation"); @@ -459,7 +476,7 @@ Posterize::get_filter_text (Inkscape::Extension::Extension * ext) antialias << "0.01"; _filter = g_strdup_printf( - "\n" + "\n" "\n" "\n" "\n" @@ -478,21 +495,30 @@ Posterize::get_filter_text (Inkscape::Extension::Extension * ext) return _filter; }; /* Posterize filter */ +/** + \brief Custom predefined PosterizeBasic filter. + + Simple posterizing effect -class TestFilter : public Inkscape::Extension::Internal::Filter::Filter { + Filter's parameters: + * Levels (1->20, default 5) -> component1 (tableValues) + * Blur (0.01->20., default 4.) -> blur1 (stdDeviation) +*/ +class PosterizeBasic : public Inkscape::Extension::Internal::Filter::Filter { protected: virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - TestFilter ( ) : Filter() { }; - virtual ~TestFilter ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + PosterizeBasic ( ) : Filter() { }; + virtual ~PosterizeBasic ( ) { if (_filter != NULL) g_free((void *)_filter); return; } static void init (void) { Inkscape::Extension::build_from_mem( "\n" - "" N_("Test Filter -EXP-") "\n" - "org.inkscape.effect.filter.TestFilter\n" - "<_param name=\"header1\" type=\"groupheader\">Test filter\n" + "" N_("Posterize basic, custom") "\n" + "org.inkscape.effect.filter.PosterizeBasic\n" + "5\n" + "4.0\n" "\n" "all\n" "\n" @@ -500,36 +526,44 @@ public: "\n" "\n" "\n" - "" N_("Change colors to a two colors palette") "\n" + "" N_("Simple posterizing effect") "\n" "\n" - "\n", new TestFilter()); + "\n", new PosterizeBasic()); }; }; gchar const * -TestFilter::get_filter_text (Inkscape::Extension::Extension * ext) +PosterizeBasic::get_filter_text (Inkscape::Extension::Extension * ext) { if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream blur; + std::ostringstream transf; + blur << ext->get_param_float("blur"); + + transf << "0"; + int levels = ext->get_param_int("levels") + 1; + float val = 0.0; + for ( int step = 1 ; step <= levels ; step++ ) { + val = (float) step / levels; + transf << " " << val; + } + transf << " 1"; + _filter = g_strdup_printf( - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" "\n" - "\n" - "\n" - "\n" - "\n"); + "\n" + "\n", blur.str().c_str(), transf.str().c_str(), transf.str().c_str(), transf.str().c_str()); return _filter; -}; /* Test filter */ +}; /* PosterizeBasic filter */ }; /* namespace Filter */ }; /* namespace Internal */ diff --git a/src/extension/internal/filter/filter-all.cpp b/src/extension/internal/filter/filter-all.cpp old mode 100644 new mode 100755 index 06b942a1f..846725472 --- a/src/extension/internal/filter/filter-all.cpp +++ b/src/extension/internal/filter/filter-all.cpp @@ -8,6 +8,7 @@ #include "filter.h" /* Put your filter here */ +#include "abc.h" #include "color.h" #include "drop-shadow.h" #include "morphology.h" @@ -30,7 +31,13 @@ Filter::filters_all (void ) Snow::init(); /* Experimental custom predefined filters */ - + + // ABCs + Blur::init(); + DiffuseLight::init(); + Roughen::init(); + SpecularLight::init(); + // Color Colorize::init(); Duochrome::init(); @@ -40,7 +47,7 @@ Filter::filters_all (void ) // Morphology Crosssmooth::init(); - + // Shadows and glows ColorizableDropShadow::init(); @@ -48,6 +55,7 @@ Filter::filters_all (void ) Chromolitho::init(); Drawing::init(); Posterize::init(); + PosterizeBasic::init(); // Here come the rest of the filters that are read from SVG files in share/filters and // .config/Inkscape/filters diff --git a/src/extension/internal/filter/morphology.h b/src/extension/internal/filter/morphology.h index 93d44d6fa..8e00b47be 100644 --- a/src/extension/internal/filter/morphology.h +++ b/src/extension/internal/filter/morphology.h @@ -48,8 +48,8 @@ public: static void init (void) { Inkscape::Extension::build_from_mem( "\n" - "" N_("Cross-smooth, custom -EXP-") "\n" - "org.inkscape.effect.filter.Crosssmooth\n" + "" N_("Cross-smooth, custom (morphology)") "\n" + "org.inkscape.effect.filter.crosssmooth\n" "\n" "<_item value=\"edges\">Smooth edges\n" "<_item value=\"all\">Smooth all\n" @@ -87,7 +87,7 @@ Crosssmooth::get_filter_text (Inkscape::Extension::Extension * ext) } _filter = g_strdup_printf( - "\n" + "\n" "\n" "\n" "\n" -- cgit v1.2.3 From 126cd0331f9ca6d2dc141226033272822466a1aa Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Fri, 7 Jan 2011 18:23:36 +0100 Subject: Export. Fix PS/EPS export (Bug #698340, PS Level Restriction reversed. (bzr r10000) --- src/extension/internal/cairo-ps-out.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/extension/internal/cairo-ps-out.cpp b/src/extension/internal/cairo-ps-out.cpp index 07312aab1..a5b7b3237 100644 --- a/src/extension/internal/cairo-ps-out.cpp +++ b/src/extension/internal/cairo-ps-out.cpp @@ -142,7 +142,7 @@ CairoPsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar con int level = CAIRO_PS_LEVEL_2; try { new_level = mod->get_param_enum("PSlevel"); - if((new_level != NULL) && !(g_ascii_strcasecmp("PS3", new_level) == 0)) + if((new_level != NULL) && (g_ascii_strcasecmp("PS3", new_level) == 0)) level = CAIRO_PS_LEVEL_3; } catch(...) {} @@ -225,7 +225,7 @@ CairoEpsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar co int level = CAIRO_PS_LEVEL_2; try { new_level = mod->get_param_enum("PSlevel"); - if((new_level != NULL) && !(g_ascii_strcasecmp("PS3", new_level) == 0)) + if((new_level != NULL) && (g_ascii_strcasecmp("PS3", new_level) == 0)) level = CAIRO_PS_LEVEL_3; } catch(...) {} -- cgit v1.2.3 From dc22b6046af378167f9bfbb248a2e3e82444f8e7 Mon Sep 17 00:00:00 2001 From: Alvin Penner Date: Fri, 7 Jan 2011 18:44:43 -0500 Subject: Export. add emf text rotation (Bug 681262) Fixed bugs: - https://launchpad.net/bugs/681262 (bzr r10001) --- src/extension/internal/emf-win32-print.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/extension/internal/emf-win32-print.cpp b/src/extension/internal/emf-win32-print.cpp index c7f8e3d4c..e1ef77ae5 100644 --- a/src/extension/internal/emf-win32-print.cpp +++ b/src/extension/internal/emf-win32-print.cpp @@ -863,6 +863,8 @@ PrintEmfWin32::text(Inkscape::Extension::Print * /*mod*/, char const *text, Geom if (!hdc) return 0; HFONT hfont = NULL; + Geom::Matrix tf = m_tr_stack.top(); + double rot = 1800.0*std::atan2(tf[1], tf[0])/M_PI; // 0.1 degree rotation #ifdef USE_PANGO_WIN32 /* @@ -883,8 +885,8 @@ PrintEmfWin32::text(Inkscape::Extension::Print * /*mod*/, char const *text, Geom lf->lfHeight = style->font_size.computed * IN_PER_PX * dwDPI; lf->lfWidth = 0; - lf->lfEscapement = 0; - lf->lfOrientation = 0; + lf->lfEscapement = rot; + lf->lfOrientation = rot; lf->lfWeight = style->font_weight.computed == SP_CSS_FONT_WEIGHT_100 ? FW_THIN : style->font_weight.computed == SP_CSS_FONT_WEIGHT_200 ? FW_EXTRALIGHT : @@ -919,8 +921,8 @@ PrintEmfWin32::text(Inkscape::Extension::Print * /*mod*/, char const *text, Geom lf->lfHeight = style->font_size.computed * IN_PER_PX * dwDPI; lf->lfWidth = 0; - lf->lfEscapement = 0; - lf->lfOrientation = 0; + lf->lfEscapement = rot; + lf->lfOrientation = rot; lf->lfWeight = style->font_weight.computed == SP_CSS_FONT_WEIGHT_100 ? FW_THIN : style->font_weight.computed == SP_CSS_FONT_WEIGHT_200 ? FW_EXTRALIGHT : @@ -964,8 +966,6 @@ PrintEmfWin32::text(Inkscape::Extension::Print * /*mod*/, char const *text, Geom // Transparent text background SetBkMode(hdc, TRANSPARENT); - Geom::Matrix tf = m_tr_stack.top(); - p = p * tf; p[Geom::X] = (p[Geom::X] * IN_PER_PX * dwDPI); p[Geom::Y] = (p[Geom::Y] * IN_PER_PX * dwDPI); -- cgit v1.2.3 From b89268ca339aadcae30e45be58dac016fcd90c39 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Tue, 11 Jan 2011 14:47:53 +0100 Subject: Filters. New custom predefined filters (all ABCs, Neon draw, Color shilf, Silhouette and Cross engraving) and code clean-up. (bzr r10003) --- src/extension/internal/filter/abc.h | 824 ++++++++++++++++++++++----- src/extension/internal/filter/color.h | 595 +++++++++++-------- src/extension/internal/filter/drop-shadow.h | 65 --- src/extension/internal/filter/experimental.h | 671 ++++++++++++++-------- src/extension/internal/filter/filter-all.cpp | 11 + src/extension/internal/filter/morphology.h | 72 +-- src/extension/internal/filter/shadows.h | 111 ++++ 7 files changed, 1629 insertions(+), 720 deletions(-) create mode 100644 src/extension/internal/filter/shadows.h (limited to 'src') diff --git a/src/extension/internal/filter/abc.h b/src/extension/internal/filter/abc.h index c93bbb7f7..b96585113 100755 --- a/src/extension/internal/filter/abc.h +++ b/src/extension/internal/filter/abc.h @@ -9,8 +9,15 @@ * * Basic filters * Blur + * Clean edges + * Color shift * Diffuse light + * Feather + * Matte jelly + * Noise fill + * Outline * Roughen + * Silhouette * Specular light * * Released under GNU GPL, read the file 'COPYING' for more information @@ -31,7 +38,7 @@ namespace Filter { /** \brief Custom predefined Blur filter. - Simple horizontal and vertical blur. + Simple horizontal and vertical blur Filter's parameters: * Horizontal blur (0.01->100., default 2) -> blur (stdDeviation) @@ -40,37 +47,37 @@ namespace Filter { class Blur : public Inkscape::Extension::Internal::Filter::Filter { protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - Blur ( ) : Filter() { }; - virtual ~Blur ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Blur, custom (ABCs)") "\n" - "org.inkscape.effect.filter.blur\n" - "2\n" - "2\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Simple vertical and horizontal blur effect") "\n" - "\n" - "\n", new Blur()); - }; + Blur ( ) : Filter() { }; + virtual ~Blur ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Blur, custom (ABCs)") "\n" + "org.inkscape.effect.filter.Blur\n" + "2\n" + "2\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Simple vertical and horizontal blur effect") "\n" + "\n" + "\n", new Blur()); + }; }; gchar const * Blur::get_filter_text (Inkscape::Extension::Extension * ext) { - if (_filter != NULL) g_free((void *)_filter); + if (_filter != NULL) g_free((void *)_filter); std::ostringstream hblur; std::ostringstream vblur; @@ -78,14 +85,130 @@ Blur::get_filter_text (Inkscape::Extension::Extension * ext) hblur << ext->get_param_float("hblur"); vblur << ext->get_param_float("vblur"); - _filter = g_strdup_printf( - "\n" - "\n" + _filter = g_strdup_printf( + "\n" + "\n" "\n", hblur.str().c_str(), vblur.str().c_str()); - return _filter; + return _filter; }; /* Blur filter */ +/** + \brief Custom predefined Clean edges filter. + + Removes or decreases glows and jaggeries around objects edges after applying some filters + + Filter's parameters: + * Strength (0.01->100., default 0.4) -> blur (stdDeviation) +*/ + +class CleanEdges : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + CleanEdges ( ) : Filter() { }; + virtual ~CleanEdges ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Clean edges, custom (ABCs)") "\n" + "org.inkscape.effect.filter.CleanEdges\n" + "0.4\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Removes or decreases glows and jaggeries around objects edges after applying some filters") "\n" + "\n" + "\n", new CleanEdges()); + }; + +}; + +gchar const * +CleanEdges::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream blur; + + blur << ext->get_param_float("blur"); + + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n", blur.str().c_str()); + + return _filter; +}; /* CleanEdges filter */ + + +/** + \brief Custom predefined Color shift filter. + + Rotate and desaturate hue + + Filter's parameters: + * Shift (0->360, default 330) -> color1 (values) + * Saturation (0.->10., default 6) -> color2 (values [/10]) +*/ + +class ColorShift : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + ColorShift ( ) : Filter() { }; + virtual ~ColorShift ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Color shift, custom (ABCs)") "\n" + "org.inkscape.effect.filter.ColorShift\n" + "330\n" + "6\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Rotate and desaturate hue") "\n" + "\n" + "\n", new ColorShift()); + }; + +}; + +gchar const * +ColorShift::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream shift; + std::ostringstream sat; + + shift << ext->get_param_int("shift"); + sat << (ext->get_param_float("sat") / 10); + + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n", shift.str().c_str(), sat.str().c_str()); + + return _filter; +}; /* ColorShift filter */ + /** \brief Custom predefined Diffuse light filter. @@ -96,45 +219,43 @@ Blur::get_filter_text (Inkscape::Extension::Extension * ext) * Elevation (0->360, default 25) -> feDistantLight (elevation) * Azimuth (0->360, default 235) -> feDistantLight (azimuth) * Lightning color (guint, default -1 [white]) -> diffuse (lighting-color) - - TODO: use the alpha channel to calculate the lightning color */ class DiffuseLight : public Inkscape::Extension::Internal::Filter::Filter { protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - DiffuseLight ( ) : Filter() { }; - virtual ~DiffuseLight ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Diffuse light, custom (ABCs)") "\n" - "org.inkscape.effect.filter.diffuselight\n" - "6\n" - "25\n" - "235\n" - "-1\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Basic diffuse bevel to use for building textures") "\n" - "\n" - "\n", new DiffuseLight()); - }; + DiffuseLight ( ) : Filter() { }; + virtual ~DiffuseLight ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Diffuse light, custom (ABCs)") "\n" + "org.inkscape.effect.filter.DiffuseLight\n" + "6\n" + "25\n" + "235\n" + "-1\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Basic diffuse bevel to use for building textures") "\n" + "\n" + "\n", new DiffuseLight()); + }; }; gchar const * DiffuseLight::get_filter_text (Inkscape::Extension::Extension * ext) { - if (_filter != NULL) g_free((void *)_filter); + if (_filter != NULL) g_free((void *)_filter); std::ostringstream smooth; std::ostringstream elevation; @@ -154,81 +275,516 @@ DiffuseLight::get_filter_text (Inkscape::Extension::Extension * ext) b << ((color >> 8) & 0xff); a << (color & 0xff) / 255.0F; - _filter = g_strdup_printf( - "\n" - "\n" - "\n" + _filter = g_strdup_printf( + "\n" + "\n" + "\n" "\n" - "\n" - "\n" - "\n" + "\n" + "\n" + "\n" "\n", smooth.str().c_str(), r.str().c_str(), g.str().c_str(), b.str().c_str(), elevation.str().c_str(), azimuth.str().c_str(), a.str().c_str()); - return _filter; + return _filter; }; /* DiffuseLight filter */ +/** + \brief Custom predefined Feather filter. + + Blurred mask on the edge without altering the contents + + Filter's parameters: + * Strength (0.01->100., default 5) -> blur (stdDeviation) +*/ + +class Feather : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + Feather ( ) : Filter() { }; + virtual ~Feather ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Feather, custom (ABCs)") "\n" + "org.inkscape.effect.filter.Feather\n" + "5\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Blurred mask on the edge without altering the contents") "\n" + "\n" + "\n", new Feather()); + }; + +}; + +gchar const * +Feather::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream blur; + + blur << ext->get_param_float("blur"); + + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n", blur.str().c_str()); + + return _filter; +}; /* Feather filter */ + +/** + \brief Custom predefined Matte jelly filter. + + Bulging, matte jelly covering + + Filter's parameters: + * Smoothness (0.0->10., default 7.) -> blur (stdDeviation) + * Brightness (0.0->5., default .9) -> specular (specularConstant) + * Elevation (0->360, default 60) -> feDistantLight (elevation) + * Azimuth (0->360, default 225) -> feDistantLight (azimuth) + * Lightning color (guint, default -1 [white]) -> specular (lighting-color) +*/ + +class MatteJelly : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + MatteJelly ( ) : Filter() { }; + virtual ~MatteJelly ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Matte jelly, custom (ABCs)") "\n" + "org.inkscape.effect.filter.MatteJelly\n" + "7\n" + "0.9\n" + "60\n" + "225\n" + "-1\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Bulging, matte jelly covering") "\n" + "\n" + "\n", new MatteJelly()); + }; + +}; + +gchar const * +MatteJelly::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream smooth; + std::ostringstream bright; + std::ostringstream elevation; + std::ostringstream azimuth; + std::ostringstream r; + std::ostringstream g; + std::ostringstream b; + std::ostringstream a; + + smooth << ext->get_param_float("smooth"); + bright << ext->get_param_float("bright"); + elevation << ext->get_param_int("elevation"); + azimuth << ext->get_param_int("azimuth"); + guint32 color = ext->get_param_color("color"); + + r << ((color >> 24) & 0xff); + g << ((color >> 16) & 0xff); + b << ((color >> 8) & 0xff); + a << (color & 0xff) / 255.0F; + + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n", smooth.str().c_str(), bright.str().c_str(), r.str().c_str(), g.str().c_str(), b.str().c_str(), elevation.str().c_str(), azimuth.str().c_str(), a.str().c_str()); + + return _filter; +}; /* MatteJelly filter */ + +/** + \brief Custom predefined Noise fill filter. + + Basic noise fill and transparency texture + + Filter's parameters: + * Turbulence type (enum, default fractalNoise else turbulence) -> turbulence (type) + * Horizontal frequency (*100) (0.001->1000., default 2) -> turbulence (baseFrequency [/100]) + * Vertical frequency (*100) (0.001->1000., default 4) -> turbulence (baseFrequency [/100]) + * Complexity (1->5, default 5) -> turbulence (numOctaves) + * Variation (1->360, default 1) -> turbulence (seed) + * Dilatation (1.->50., default 3) -> color (n-1th value) + * Erosion (0.->50., default 1) -> color (nth value 0->-50) + * Color (guint, default 148,115,39,255) -> flood (flood-color, flood-opacity) + * Inverted (boolean, default false) -> composite1 (operator, true="in", false="out") +*/ + +class NoiseFill : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + NoiseFill ( ) : Filter() { }; + virtual ~NoiseFill ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Noise fill, custom (ABCs)") "\n" + "org.inkscape.effect.filter.NoiseFill\n" + "\n" + "\n" + "\n" + "<_item value=\"fractalNoise\">Fractal noise\n" + "<_item value=\"turbulence\">Turbulence\n" + "\n" + "2\n" + "4\n" + "5\n" + "0\n" + "3\n" + "1\n" + "false\n" + "\n" + "\n" + "354957823\n" + "\n" + "\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Basic noise fill and transparency texture") "\n" + "\n" + "\n", new NoiseFill()); + }; + +}; + +gchar const * +NoiseFill::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream type; + std::ostringstream hfreq; + std::ostringstream vfreq; + std::ostringstream complexity; + std::ostringstream variation; + std::ostringstream dilat; + std::ostringstream erosion; + std::ostringstream r; + std::ostringstream g; + std::ostringstream b; + std::ostringstream a; + std::ostringstream inverted; + + type << ext->get_param_enum("type"); + hfreq << (ext->get_param_float("hfreq") / 100); + vfreq << (ext->get_param_float("vfreq") / 100); + complexity << ext->get_param_int("complexity"); + variation << ext->get_param_int("variation"); + dilat << ext->get_param_float("dilat"); + erosion << (- ext->get_param_float("erosion")); + guint32 color = ext->get_param_color("color"); + r << ((color >> 24) & 0xff); + g << ((color >> 16) & 0xff); + b << ((color >> 8) & 0xff); + a << (color & 0xff) / 255.0F; + if (ext->get_param_bool("inverted")) + inverted << "out"; + else + inverted << "in"; + + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n", type.str().c_str(), hfreq.str().c_str(), vfreq.str().c_str(), complexity.str().c_str(), variation.str().c_str(), inverted.str().c_str(), dilat.str().c_str(), erosion.str().c_str(), a.str().c_str(), r.str().c_str(), g.str().c_str(), b.str().c_str()); + + return _filter; +}; /* NoiseFill filter */ + +/** + \brief Custom predefined Outline filter. + + Adds a colorizable outline + + Filter's parameters: + * Width (0.01->50., default 5) -> blur1 (stdDeviation) + * Melt (0.01->50., default 2) -> blur2 (stdDeviation) + * Dilatation (1.->50., default 8) -> color2 (n-1th value) + * Erosion (0.->50., default 5) -> color2 (nth value 0->-50) + * Color (guint, default 156,102,102,255) -> flood (flood-color, flood-opacity) + * Blend (enum, default Normal) -> blend (mode) +*/ + +class Outline : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + Outline ( ) : Filter() { }; + virtual ~Outline ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Outline, custom (ABCs)") "\n" + "org.inkscape.effect.filter.Outline\n" + "\n" + "\n" + "5\n" + "2\n" + "8\n" + "5\n" + "\n" + "\n" + "1029214207\n" + "\n" + "\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Adds a colorizable outline") "\n" + "\n" + "\n", new Outline()); + }; + +}; + +gchar const * +Outline::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream width; + std::ostringstream melt; + std::ostringstream dilat; + std::ostringstream erosion; + std::ostringstream r; + std::ostringstream g; + std::ostringstream b; + std::ostringstream a; + std::ostringstream blend; + + width << ext->get_param_float("width"); + melt << ext->get_param_float("melt"); + dilat << ext->get_param_float("dilat"); + erosion << (- ext->get_param_float("erosion")); + guint32 color = ext->get_param_color("color"); + r << ((color >> 24) & 0xff); + g << ((color >> 16) & 0xff); + b << ((color >> 8) & 0xff); + a << (color & 0xff) / 255.0F; + + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n", width.str().c_str(), melt.str().c_str(), dilat.str().c_str(), erosion.str().c_str(), a.str().c_str(), r.str().c_str(), g.str().c_str(), b.str().c_str()); + + return _filter; +}; /* Outline filter */ + /** \brief Custom predefined Roughen filter. Small-scale roughening to edges and content Filter's parameters: - * Frequency (*100) (0.0->40., default 1.3) -> turbulence (baseFrequency) + * Turbulence type (enum, default fractalNoise else turbulence) -> turbulence (type) + * Horizontal frequency (*100) (0.001->1000., default 1.3) -> turbulence (baseFrequency) + * Vertical frequency (*100) (0.001->1000., default 1.3) -> turbulence (baseFrequency) + * Complexity (1->5, default 5) -> turbulence (numOctaves) + * Variation (1->360, default 1) -> turbulence (seed) * Intensity (0.0->50., default 6.6) -> displacement (scale) */ class Roughen : public Inkscape::Extension::Internal::Filter::Filter { protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - Roughen ( ) : Filter() { }; - virtual ~Roughen ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Roughen, custom (ABCs)") "\n" - "org.inkscape.effect.filter.roughen\n" - "1.3\n" - "1.3\n" - "6.6\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Small-scale roughening to edges and content") "\n" - "\n" - "\n", new Roughen()); - }; + Roughen ( ) : Filter() { }; + virtual ~Roughen ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Roughen, custom (ABCs)") "\n" + "org.inkscape.effect.filter.Roughen\n" + "\n" + "<_item value=\"fractalNoise\">Fractal noise\n" + "<_item value=\"turbulence\">Turbulence\n" + "\n" + "1.3\n" + "1.3\n" + "5\n" + "0\n" + "6.6\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Small-scale roughening to edges and content") "\n" + "\n" + "\n", new Roughen()); + }; }; gchar const * Roughen::get_filter_text (Inkscape::Extension::Extension * ext) { - if (_filter != NULL) g_free((void *)_filter); - + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream type; std::ostringstream hfreq; std::ostringstream vfreq; + std::ostringstream complexity; + std::ostringstream variation; std::ostringstream intensity; - + + type << ext->get_param_enum("type"); hfreq << (ext->get_param_float("hfreq") / 100); vfreq << (ext->get_param_float("vfreq") / 100); + complexity << ext->get_param_int("complexity"); + variation << ext->get_param_int("variation"); intensity << ext->get_param_float("intensity"); - _filter = g_strdup_printf( - "\n" - "\n" - "\n" - "\n", hfreq.str().c_str(), vfreq.str().c_str(), intensity.str().c_str()); + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n", type.str().c_str(), complexity.str().c_str(), variation.str().c_str(), hfreq.str().c_str(), vfreq.str().c_str(), intensity.str().c_str()); - return _filter; + return _filter; }; /* Roughen filter */ +/** + \brief Custom predefined Silhouette filter. + + Repaint anything visible monochrome + + Filter's parameters: + * Blur (0.->50., default 0) -> blur (stdDeviation) + * Cutout (boolean, default False) -> composite (false=in, true=out) + * Color (guint, default 0,0,0,255) -> flood (flood-color, flood-opacity) +*/ + +class Silhouette : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + Silhouette ( ) : Filter() { }; + virtual ~Silhouette ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Silhouette, custom (ABCs)") "\n" + "org.inkscape.effect.filter.Silhouette\n" + "0\n" + "false\n" + "255\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Repaint anything visible monochrome") "\n" + "\n" + "\n", new Silhouette()); + }; + +}; + +gchar const * +Silhouette::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream a; + std::ostringstream r; + std::ostringstream g; + std::ostringstream b; + std::ostringstream cutout; + std::ostringstream blur; + + guint32 color = ext->get_param_color("color"); + r << ((color >> 24) & 0xff); + g << ((color >> 16) & 0xff); + b << ((color >> 8) & 0xff); + a << (color & 0xff) / 255.0F; + if (ext->get_param_bool("cutout")) + cutout << "out"; + else + cutout << "in"; + blur << ext->get_param_float("blur"); + + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n", a.str().c_str(), r.str().c_str(), g.str().c_str(), b.str().c_str(), cutout.str().c_str(), blur.str().c_str()); + + return _filter; +}; /* Silhouette filter */ + /** \brief Custom predefined Specular light filter. @@ -237,49 +793,47 @@ Roughen::get_filter_text (Inkscape::Extension::Extension * ext) Filter's parameters: * Smoothness (0.0->10., default 6.) -> blur (stdDeviation) * Brightness (0.0->5., default 1.) -> specular (specularConstant) - * Elevation (0->360, default 25) -> feDistantLight (elevation) + * Elevation (0->360, default 45) -> feDistantLight (elevation) * Azimuth (0->360, default 235) -> feDistantLight (azimuth) * Lightning color (guint, default -1 [white]) -> specular (lighting-color) - - TODO: use the alpha channel to calculate the lightning color (but do we really need a lightning color here?) */ class SpecularLight : public Inkscape::Extension::Internal::Filter::Filter { protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - SpecularLight ( ) : Filter() { }; - virtual ~SpecularLight ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Specular light, custom (ABCs)") "\n" - "org.inkscape.effect.filter.specularlight\n" - "6\n" - "1\n" - "45\n" - "235\n" - "-1\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Basic specular bevel to use for building textures") "\n" - "\n" - "\n", new SpecularLight()); - }; + SpecularLight ( ) : Filter() { }; + virtual ~SpecularLight ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Specular light, custom (ABCs)") "\n" + "org.inkscape.effect.filter.SpecularLight\n" + "6\n" + "1\n" + "45\n" + "235\n" + "-1\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Basic specular bevel to use for building textures") "\n" + "\n" + "\n", new SpecularLight()); + }; }; gchar const * SpecularLight::get_filter_text (Inkscape::Extension::Extension * ext) { - if (_filter != NULL) g_free((void *)_filter); + if (_filter != NULL) g_free((void *)_filter); std::ostringstream smooth; std::ostringstream bright; @@ -301,17 +855,17 @@ SpecularLight::get_filter_text (Inkscape::Extension::Extension * ext) b << ((color >> 8) & 0xff); a << (color & 0xff) / 255.0F; - _filter = g_strdup_printf( - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" "\n", smooth.str().c_str(), bright.str().c_str(), r.str().c_str(), g.str().c_str(), b.str().c_str(), elevation.str().c_str(), azimuth.str().c_str(), a.str().c_str()); - return _filter; + return _filter; }; /* SpecularLight filter */ @@ -320,5 +874,5 @@ SpecularLight::get_filter_text (Inkscape::Extension::Extension * ext) }; /* namespace Extension */ }; /* namespace Inkscape */ -/* Change the 'COLOR' below to be your file name */ +/* Change the 'ABC' below to be your file name */ #endif /* __INKSCAPE_EXTENSION_INTERNAL_FILTER_ABC_H__ */ diff --git a/src/extension/internal/filter/color.h b/src/extension/internal/filter/color.h index 05173b684..559ecd3cc 100755 --- a/src/extension/internal/filter/color.h +++ b/src/extension/internal/filter/color.h @@ -3,13 +3,14 @@ /* Change the 'COLOR' above to be your file name */ /* - * Copyright (C) 2010 Authors: + * Copyright (C) 2011 Authors: * Ivan Louette (filters) * Nicolas Dufour (UI) * * Color filters * Colorize * Duochrome + * Electrize * Quadritone * Solarize * Tritone @@ -45,53 +46,59 @@ namespace Filter { class Colorize : public Inkscape::Extension::Internal::Filter::Filter { protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - Colorize ( ) : Filter() { }; - virtual ~Colorize ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Colorize, custom (color)") "\n" - "org.inkscape.effect.filter.Colorize\n" - "0\n" - "1\n" - "false\n" - "\n" - "<_item value=\"multiply\">Multiply\n" - "<_item value=\"normal\">Normal\n" - "<_item value=\"screen\">Screen\n" - "<_item value=\"lighten\">Lighten\n" - "<_item value=\"darken\">Darken\n" - "\n" - "\n" - "<_item value=\"screen\">Screen\n" - "<_item value=\"multiply\">Multiply\n" - "<_item value=\"normal\">Normal\n" - "<_item value=\"lighten\">Lighten\n" - "<_item value=\"darken\">Darken\n" - "\n" - "-1639776001\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Blend image or object with a flood color") "\n" - "\n" - "\n", new Colorize()); - }; + Colorize ( ) : Filter() { }; + virtual ~Colorize ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Colorize, custom (Color)") "\n" + "org.inkscape.effect.filter.Colorize\n" + "\n" + "\n" + "0\n" + "1\n" + "false\n" + "\n" + "<_item value=\"multiply\">Multiply\n" + "<_item value=\"normal\">Normal\n" + "<_item value=\"screen\">Screen\n" + "<_item value=\"lighten\">Lighten\n" + "<_item value=\"darken\">Darken\n" + "\n" + "\n" + "<_item value=\"screen\">Screen\n" + "<_item value=\"multiply\">Multiply\n" + "<_item value=\"normal\">Normal\n" + "<_item value=\"lighten\">Lighten\n" + "<_item value=\"darken\">Darken\n" + "\n" + "\n" + "\n" + "-1639776001\n" + "\n" + "\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Blend image or object with a flood color") "\n" + "\n" + "\n", new Colorize()); + }; }; gchar const * Colorize::get_filter_text (Inkscape::Extension::Extension * ext) { - if (_filter != NULL) g_free((void *)_filter); + if (_filter != NULL) g_free((void *)_filter); std::ostringstream a; std::ostringstream r; @@ -118,18 +125,18 @@ Colorize::get_filter_text (Inkscape::Extension::Extension * ext) else duotone << "1"; - _filter = g_strdup_printf( - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" "\n", hlight.str().c_str(), nlight.str().c_str(), duotone.str().c_str(), a.str().c_str(), r.str().c_str(), g.str().c_str(), b.str().c_str(), blend1.str().c_str(), blend2.str().c_str()); - return _filter; + return _filter; }; /* Colorize filter */ @@ -147,52 +154,52 @@ Colorize::get_filter_text (Inkscape::Extension::Extension * ext) class Duochrome : public Inkscape::Extension::Internal::Filter::Filter { protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - Duochrome ( ) : Filter() { }; - virtual ~Duochrome ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Duochrome, custom (color)") "\n" - "org.inkscape.effect.filter.Duochrome\n" - "\n" - "\n" - "0\n" - "\n" - "<_item value=\"none\">No swap\n" - "<_item value=\"full\">Color and alpha\n" - "<_item value=\"color\">Color only\n" - "<_item value=\"alpha\">Alpha only\n" - "\n" - "\n" - "\n" - "1364325887\n" - "\n" - "\n" - "-65281\n" - "\n" - "\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Convert luminance values to a duochrome palette") "\n" - "\n" - "\n", new Duochrome()); - }; + Duochrome ( ) : Filter() { }; + virtual ~Duochrome ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Duochrome, custom (Color)") "\n" + "org.inkscape.effect.filter.Duochrome\n" + "\n" + "\n" + "0\n" + "\n" + "<_item value=\"none\">No swap\n" + "<_item value=\"full\">Color and alpha\n" + "<_item value=\"color\">Color only\n" + "<_item value=\"alpha\">Alpha only\n" + "\n" + "\n" + "\n" + "1364325887\n" + "\n" + "\n" + "-65281\n" + "\n" + "\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Convert luminance values to a duochrome palette") "\n" + "\n" + "\n", new Duochrome()); + }; }; gchar const * Duochrome::get_filter_text (Inkscape::Extension::Extension * ext) { - if (_filter != NULL) g_free((void *)_filter); + if (_filter != NULL) g_free((void *)_filter); std::ostringstream a1; std::ostringstream r1; @@ -240,23 +247,107 @@ Duochrome::get_filter_text (Inkscape::Extension::Extension * ext) a2 << (color2 & 0xff) / 255.0F; } - _filter = g_strdup_printf( - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" "\n", a1.str().c_str(), r1.str().c_str(), g1.str().c_str(), b1.str().c_str(), swap1.str().c_str(), a2.str().c_str(), r2.str().c_str(), g2.str().c_str(), b2.str().c_str(), swap2.str().c_str(), fluo.str().c_str()); - return _filter; + return _filter; }; /* Duochrome filter */ +/** + \brief Custom predefined Electrize filter. + + Electro solarization effects. + + Filter's parameters: + * Simplify (0.01->10., default 2.) -> blur (stdDeviation) + * Effect type (enum: table or discrete, default "table") -> component (type) + * Level (0->10, default 3) -> component (tableValues) + * Inverted (boolean, default false) -> component (tableValues) +*/ +class Electrize : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + Electrize ( ) : Filter() { }; + virtual ~Electrize ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Electrize, custom (Color)") "\n" + "org.inkscape.effect.filter.Electrize\n" + "2.0\n" + "\n" + "<_item value=\"table\">Table\n" + "<_item value=\"discrete\">Discrete\n" + "\n" + "3\n" + "false\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Electro solarization effects") "\n" + "\n" + "\n", new Electrize()); + }; +}; + +gchar const * +Electrize::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream blur; + std::ostringstream type; + std::ostringstream values; + + blur << ext->get_param_float("blur"); + type << ext->get_param_enum("type"); + + // TransfertComponent table values are calculated based on the effect level and inverted parameters. + int val = 0; + int levels = ext->get_param_int("levels") + 1; + if (ext->get_param_bool("invert")) + val = 1; + values << val; + for ( int step = 1 ; step <= levels ; step++ ) { + if (val == 1) { + val = 0; + } + else { + val = 1; + } + values << " " << val; + } + + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n", blur.str().c_str(), type.str().c_str(), values.str().c_str(), type.str().c_str(), values.str().c_str(), type.str().c_str(), values.str().c_str()); + + return _filter; +}; /* Electrize filter */ /** \brief Custom predefined Quadritone filter. @@ -273,50 +364,50 @@ Duochrome::get_filter_text (Inkscape::Extension::Extension * ext) class Quadritone : public Inkscape::Extension::Internal::Filter::Filter { protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - Quadritone ( ) : Filter() { }; - virtual ~Quadritone ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Quadritone fantasy, custom (color)") "\n" - "org.inkscape.effect.filter.Quadritone\n" - "280\n" - "100\n" - "\n" - "<_item value=\"normal\">Normal\n" - "<_item value=\"multiply\">Multiply\n" - "<_item value=\"screen\">Screen\n" - "\n" - "0\n" - "\n" - "<_item value=\"normal\">Normal\n" - "<_item value=\"screen\">Screen\n" - "<_item value=\"multiply\">Multiply\n" - "<_item value=\"lighten\">Lighten\n" - "<_item value=\"darken\">Darken\n" - "\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Replace hue by two colors") "\n" - "\n" - "\n", new Quadritone()); - }; + Quadritone ( ) : Filter() { }; + virtual ~Quadritone ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Quadritone fantasy, custom (Color)") "\n" + "org.inkscape.effect.filter.Quadritone\n" + "280\n" + "100\n" + "\n" + "<_item value=\"normal\">Normal\n" + "<_item value=\"multiply\">Multiply\n" + "<_item value=\"screen\">Screen\n" + "\n" + "0\n" + "\n" + "<_item value=\"normal\">Normal\n" + "<_item value=\"screen\">Screen\n" + "<_item value=\"multiply\">Multiply\n" + "<_item value=\"lighten\">Lighten\n" + "<_item value=\"darken\">Darken\n" + "\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Replace hue by two colors") "\n" + "\n" + "\n", new Quadritone()); + }; }; gchar const * Quadritone::get_filter_text (Inkscape::Extension::Extension * ext) { - if (_filter != NULL) g_free((void *)_filter); + if (_filter != NULL) g_free((void *)_filter); std::ostringstream dist; std::ostringstream colors; @@ -330,18 +421,18 @@ Quadritone::get_filter_text (Inkscape::Extension::Extension * ext) sat << ext->get_param_float("sat"); blend2 << ext->get_param_enum("blend2"); - _filter = g_strdup_printf( - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" "\n", dist.str().c_str(), colors.str().c_str(), blend1.str().c_str(), sat.str().c_str(), blend2.str().c_str()); - return _filter; + return _filter; }; /* Quadritone filter */ @@ -360,40 +451,40 @@ Quadritone::get_filter_text (Inkscape::Extension::Extension * ext) class Solarize : public Inkscape::Extension::Internal::Filter::Filter { protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - Solarize ( ) : Filter() { }; - virtual ~Solarize ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Solarize, custom (color)") "\n" - "org.inkscape.effect.filter.Solarize\n" - "0\n" - "\n" - "<_item value=\"solarize\">Solarize\n" - "<_item value=\"moonarize\">Moonarize\n" - "\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Classic photographic solarization effect") "\n" - "\n" - "\n", new Solarize()); - }; + Solarize ( ) : Filter() { }; + virtual ~Solarize ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Solarize, custom (Color)") "\n" + "org.inkscape.effect.filter.Solarize\n" + "0\n" + "\n" + "<_item value=\"solarize\">Solarize\n" + "<_item value=\"moonarize\">Moonarize\n" + "\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Classic photographic solarization effect") "\n" + "\n" + "\n", new Solarize()); + }; }; gchar const * Solarize::get_filter_text (Inkscape::Extension::Extension * ext) { - if (_filter != NULL) g_free((void *)_filter); + if (_filter != NULL) g_free((void *)_filter); std::ostringstream rotate; std::ostringstream blend1; @@ -411,17 +502,17 @@ Solarize::get_filter_text (Inkscape::Extension::Extension * ext) blend2 << "multiply"; } - _filter = g_strdup_printf( - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" "\n", rotate.str().c_str(), blend1.str().c_str(), blend2.str().c_str()); - return _filter; + return _filter; }; /* Solarize filter */ @@ -447,63 +538,63 @@ Solarize::get_filter_text (Inkscape::Extension::Extension * ext) class Tritone : public Inkscape::Extension::Internal::Filter::Filter { protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - Tritone ( ) : Filter() { }; - virtual ~Tritone ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Tritone, custom (color)") "\n" - "org.inkscape.effect.filter.Tritone\n" - "\n" - "\n" - "\n" - "<_item value=\"normal\">Normal\n" - "<_item value=\"enhue\">Enhance hue\n" - "<_item value=\"rad\">Radiation\n" - "<_item value=\"htb\">Hue to background\n" - "\n" - "\n" - "<_item value=\"lighten\">Lighten\n" - "<_item value=\"screen\">Screen\n" - "<_item value=\"multiply\">Multiply\n" - "<_item value=\"darken\">Darken\n" - "\n" - "0.01\n" - "\n" - "<_item value=\"normal\">Normal\n" - "<_item value=\"multiply\">Multiply\n" - "<_item value=\"darken\">Darken\n" - "\n" - "0\n" - "1\n" - "\n" - "\n" - "0\n" - "-73203457\n" - "\n" - "\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Create a custom tritone palette with additional glow, blend modes and hue moving") "\n" - "\n" - "\n", new Tritone()); - }; + Tritone ( ) : Filter() { }; + virtual ~Tritone ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Tritone, custom (Color)") "\n" + "org.inkscape.effect.filter.Tritone\n" + "\n" + "\n" + "\n" + "<_item value=\"normal\">Normal\n" + "<_item value=\"enhue\">Enhance hue\n" + "<_item value=\"rad\">Radiation\n" + "<_item value=\"htb\">Hue to background\n" + "\n" + "\n" + "<_item value=\"lighten\">Lighten\n" + "<_item value=\"screen\">Screen\n" + "<_item value=\"multiply\">Multiply\n" + "<_item value=\"darken\">Darken\n" + "\n" + "0.01\n" + "\n" + "<_item value=\"normal\">Normal\n" + "<_item value=\"multiply\">Multiply\n" + "<_item value=\"darken\">Darken\n" + "\n" + "0\n" + "1\n" + "\n" + "\n" + "0\n" + "-73203457\n" + "\n" + "\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Create a custom tritone palette with additional glow, blend modes and hue moving") "\n" + "\n" + "\n", new Tritone()); + }; }; gchar const * Tritone::get_filter_text (Inkscape::Extension::Extension * ext) { - if (_filter != NULL) g_free((void *)_filter); + if (_filter != NULL) g_free((void *)_filter); std::ostringstream dist; std::ostringstream a; @@ -564,30 +655,30 @@ Tritone::get_filter_text (Inkscape::Extension::Extension * ext) b6in2 << "qminpc"; } - _filter = g_strdup_printf( - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" "\n", dist.str().c_str(), globalblend.str().c_str(), a.str().c_str(), r.str().c_str(), g.str().c_str(), b.str().c_str(), c1in.str().c_str(), c1in2.str().c_str(), glow.str().c_str(), b6in2.str().c_str(), glowblend.str().c_str(), c2in.str().c_str(), c2in2.str().c_str(), llight.str().c_str(), glight.str().c_str()); - return _filter; + return _filter; }; /* Tritone filter */ }; /* namespace Filter */ diff --git a/src/extension/internal/filter/drop-shadow.h b/src/extension/internal/filter/drop-shadow.h index 22890d39a..12f0c6055 100644 --- a/src/extension/internal/filter/drop-shadow.h +++ b/src/extension/internal/filter/drop-shadow.h @@ -141,71 +141,6 @@ DropGlow::get_filter_text (Inkscape::Extension::Extension * ext) return _filter; }; -class ColorizableDropShadow : public Inkscape::Extension::Internal::Filter::Filter { -protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); - -public: - ColorizableDropShadow ( ) : Filter() { }; - virtual ~ColorizableDropShadow ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Drop shadow, color") "\n" - "org.inkscape.effect.filter.colorizable-drop-shadow\n" - "3.0\n" - "6.0\n" - "6.0\n" - "127\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Colorizable Drop shadow") "\n" - "\n" - "\n", new ColorizableDropShadow()); - }; - -}; - -gchar const * -ColorizableDropShadow::get_filter_text (Inkscape::Extension::Extension * ext) -{ - if (_filter != NULL) g_free((void *)_filter); - - std::ostringstream blur; - std::ostringstream a; - std::ostringstream r; - std::ostringstream g; - std::ostringstream b; - std::ostringstream x; - std::ostringstream y; - - guint32 color = ext->get_param_color("color"); - - blur << ext->get_param_float("blur"); - x << ext->get_param_float("xoffset"); - y << ext->get_param_float("yoffset"); - a << (color & 0xff) / 255.0F; - r << ((color >> 24) & 0xff); - g << ((color >> 16) & 0xff); - b << ((color >> 8) & 0xff); - - _filter = g_strdup_printf( - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n", a.str().c_str(), r.str().c_str(), g.str().c_str(), b.str().c_str(), blur.str().c_str(), x.str().c_str(), y.str().c_str()); - - return _filter; -}; }; /* namespace Filter */ }; /* namespace Internal */ }; /* namespace Extension */ diff --git a/src/extension/internal/filter/experimental.h b/src/extension/internal/filter/experimental.h index acd258805..0375f008d 100755 --- a/src/extension/internal/filter/experimental.h +++ b/src/extension/internal/filter/experimental.h @@ -9,7 +9,9 @@ * * Experimental filters (no assigned menu) * Chromolitho + * Cross engraving * Drawing + * Neon draw * Posterize * Posterize basic * @@ -55,70 +57,70 @@ namespace Filter { */ class Chromolitho : public Inkscape::Extension::Internal::Filter::Filter { protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - Chromolitho ( ) : Filter() { }; - virtual ~Chromolitho ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Chromolitho, custom") "\n" - "org.inkscape.effect.filter.Chromolitho\n" - "\n" - "\n" - "true\n" - "\n" - "<_item value=\"darken\">Darken\n" - "<_item value=\"normal\">Normal\n" - "<_item value=\"multiply\">Multiply\n" - "<_item value=\"screen\">Screen\n" - "<_item value=\"lighten\">Lighten\n" - "\n" - "false\n" - "false\n" - "false\n" - "0\n" - "1\n" - "10\n" - "1\n" - "\n" - "\n" - "true\n" - "100\n" - "100\n" - "1\n" - "0\n" - "1\n" - "0\n" - "true\n" - "\n" - "<_item value=\"normal\">Normal\n" - "<_item value=\"multiply\">Multiply\n" - "<_item value=\"screen\">Screen\n" - "<_item value=\"lighten\">Lighten\n" - "<_item value=\"darken\">Darken\n" - "\n" - "\n" - "\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Chromo effect with customizable edge drawing and graininess") "\n" - "\n" - "\n", new Chromolitho()); - }; + Chromolitho ( ) : Filter() { }; + virtual ~Chromolitho ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Chromolitho, custom") "\n" + "org.inkscape.effect.filter.Chromolitho\n" + "\n" + "\n" + "true\n" + "\n" + "<_item value=\"darken\">Darken\n" + "<_item value=\"normal\">Normal\n" + "<_item value=\"multiply\">Multiply\n" + "<_item value=\"screen\">Screen\n" + "<_item value=\"lighten\">Lighten\n" + "\n" + "false\n" + "false\n" + "false\n" + "0\n" + "1\n" + "10\n" + "1\n" + "\n" + "\n" + "true\n" + "100\n" + "100\n" + "1\n" + "0\n" + "1\n" + "0\n" + "true\n" + "\n" + "<_item value=\"normal\">Normal\n" + "<_item value=\"multiply\">Multiply\n" + "<_item value=\"screen\">Screen\n" + "<_item value=\"lighten\">Lighten\n" + "<_item value=\"darken\">Darken\n" + "\n" + "\n" + "\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Chromo effect with customizable edge drawing and graininess") "\n" + "\n" + "\n", new Chromolitho()); + }; }; gchar const * Chromolitho::get_filter_text (Inkscape::Extension::Extension * ext) { - if (_filter != NULL) g_free((void *)_filter); + if (_filter != NULL) g_free((void *)_filter); std::ostringstream b1in; std::ostringstream b2in; @@ -178,51 +180,137 @@ Chromolitho::get_filter_text (Inkscape::Extension::Extension * ext) else graincol << "0"; - _filter = g_strdup_printf( - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" "\n" "\n" "\n" - "\n" - "\n" - "\n" - "\n" + "\n" + "\n" + "\n" + "\n" "\n", light.str().c_str(), noise.str().c_str(), b1in.str().c_str(), dblend.str().c_str(), smooth.str().c_str(), grainxf.str().c_str(), grainyf.str().c_str(), grainc.str().c_str(), grainv.str().c_str(), grainexp.str().c_str(), grainero.str().c_str(), graincol.str().c_str(), b2in.str().c_str(), gblend.str().c_str(), saturation.str().c_str(), transf.str().c_str(), transf.str().c_str(), transf.str().c_str(), col3in.str().c_str()); - return _filter; + return _filter; }; /* Chromolitho filter */ +/** + \brief Custom predefined Cross engraving filter. + + Convert image to an engraving made of vertical and horizontal lines + + Filter's parameters: + * Clean-up (1->500, default 30) -> convolve1 (kernelMatrix, central value -1001->-1500, default -1030) + * Dilatation (1.->50., default 1) -> color2 (n-1th value) + * Erosion (0.->50., default 0) -> color2 (nth value 0->-50) + * Strength (0.->10., default 0.5) -> composite2 (k2) + * Length (0.5->20, default 4) -> blur1 (stdDeviation x), blur2 (stdDeviation y) + * Transparent (boolean, default false) -> composite 4 (in, true->composite3, false->blend) +*/ +class CrossEngraving : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + CrossEngraving ( ) : Filter() { }; + virtual ~CrossEngraving ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Cross engraving, custom") "\n" + "org.inkscape.effect.filter.CrossEngraving\n" + "30\n" + "1\n" + "0\n" + "0.5\n" + "4\n" + "false\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Convert image to an engraving made of vertical and horizontal lines") "\n" + "\n" + "\n", new CrossEngraving()); + }; +}; + +gchar const * +CrossEngraving::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream clean; + std::ostringstream dilat; + std::ostringstream erosion; + std::ostringstream strength; + std::ostringstream length; + std::ostringstream trans; + + clean << (-1000 - ext->get_param_int("clean")); + dilat << ext->get_param_float("dilat"); + erosion << (- ext->get_param_float("erosion")); + strength << ext->get_param_float("strength"); + length << ext->get_param_float("length"); + if (ext->get_param_bool("trans")) + trans << "composite3"; + else + trans << "blend"; + + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n", clean.str().c_str(), dilat.str().c_str(), erosion.str().c_str(), strength.str().c_str(), length.str().c_str(), length.str().c_str(), trans.str().c_str()); + + return _filter; +}; /* CrossEngraving filter */ + /** \brief Custom predefined Drawing filter. Convert images to duochrome drawings. Filter's parameters: - * Simplification (0.01->20, default 0.6) -> blur1 (stdDeviation) - * Lightness (1->500, default 10) -> convolve1 (kernelMatrix, central value -1001->-1500, default -1010) - * Fading (0.->6., default 0) -> composite1 (k4) - * Smoothness (0.01->20, default 0.6) -> blur2 (stdDeviation) - * Dilatation (1->50, default 6) -> color2 (n-1th value) - * Erosion (0->50, default 3) -> color2 (nth value 0->-50) + * Simplification strength (0.01->20, default 0.6) -> blur1 (stdDeviation) + * Clean-up (1->500, default 10) -> convolve1 (kernelMatrix, central value -1001->-1500, default -1010) + * Erase (0.->6., default 0) -> composite1 (k4) + * Smoothness strength (0.01->20, default 0.6) -> blur2 (stdDeviation) + * Dilatation (1.->50., default 6) -> color2 (n-1th value) + * Erosion (0.->50., default 3) -> color2 (nth value 0->-50) * Transluscent (boolean, default false) -> composite 8 (in, true->merge1, false->composite7) - * Offset (-100->100, default 0) -> offset (val) - * Blur (0.01->20., default 1.) -> blur3 (stdDeviation) - * Blur spread (1->50, default 6) -> color4 (n-1th value) - * Blur erosion (0->50, default 3) -> color4 (nth value 0->-50) + * Blur strength (0.01->20., default 1.) -> blur3 (stdDeviation) + * Blur dilatation (1.->50., default 6) -> color4 (n-1th value) + * Blur erosion (0.->50., default 3) -> color4 (nth value 0->-50) * Stroke color (guint, default 64,64,64,255) -> flood2 (flood-color), composite3 (k2) * Image on stroke (boolean, default false) -> composite2 (in="flood2" true-> in="SourceGraphic") + * Offset (-100->100, default 0) -> offset (val) + * Fill color (guint, default 200,200,200,255) -> flood3 (flood-opacity), composite5 (k2) * Image on fill (boolean, default false) -> composite4 (in="flood3" true-> in="SourceGraphic") @@ -230,62 +318,64 @@ Chromolitho::get_filter_text (Inkscape::Extension::Extension * ext) class Drawing : public Inkscape::Extension::Internal::Filter::Filter { protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - Drawing ( ) : Filter() { }; - virtual ~Drawing ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Drawing, custom") "\n" - "org.inkscape.effect.filter.Drawing\n" - "\n" - "\n" - "0.6\n" - "10\n" - "0\n" - "0.6\n" - "6\n" - "3\n" - "false\n" - "<_param name=\"blurheader\" type=\"groupheader\">Blur\n" - "1\n" - "6\n" - "3\n" - "\n" - "\n" - "-1515870721\n" - "false\n" - "\n" - "\n" - "589505535\n" - "false\n" - "0\n" - "\n" - "\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Convert images to duochrome drawings") "\n" - "\n" - "\n", new Drawing()); - }; + Drawing ( ) : Filter() { }; + virtual ~Drawing ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Drawing, custom") "\n" + "org.inkscape.effect.filter.Drawing\n" + "\n" + "\n" + "<_param name=\"simplifyheader\" type=\"groupheader\">Simplify\n" + "0.6\n" + "10\n" + "0\n" + "false\n" + "<_param name=\"smoothheader\" type=\"groupheader\">Smoothness\n" + "0.6\n" + "6\n" + "3\n" + "<_param name=\"meltheader\" type=\"groupheader\">Melt\n" + "1\n" + "6\n" + "3\n" + "\n" + "\n" + "-1515870721\n" + "false\n" + "\n" + "\n" + "589505535\n" + "false\n" + "0\n" + "\n" + "\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Convert images to duochrome drawings") "\n" + "\n" + "\n", new Drawing()); + }; }; gchar const * Drawing::get_filter_text (Inkscape::Extension::Extension * ext) { - if (_filter != NULL) g_free((void *)_filter); + if (_filter != NULL) g_free((void *)_filter); std::ostringstream simply; - std::ostringstream light; - std::ostringstream fade; + std::ostringstream clean; + std::ostringstream erase; std::ostringstream smooth; std::ostringstream dilat; std::ostringstream erosion; @@ -306,8 +396,8 @@ Drawing::get_filter_text (Inkscape::Extension::Extension * ext) std::ostringstream iof; simply << ext->get_param_float("simply"); - light << (-1000 - ext->get_param_int("light")); - fade << (ext->get_param_float("fade") / 10); + clean << (-1000 - ext->get_param_int("clean")); + erase << (ext->get_param_float("erase") / 10); smooth << ext->get_param_float("smooth"); dilat << ext->get_param_float("dilat"); erosion << (- ext->get_param_float("erosion")); @@ -341,8 +431,8 @@ Drawing::get_filter_text (Inkscape::Extension::Extension * ext) else ios << "flood2"; - _filter = g_strdup_printf( - "\n" + _filter = g_strdup_printf( + "\n" "\n" "\n" "\n" @@ -373,72 +463,189 @@ Drawing::get_filter_text (Inkscape::Extension::Extension * ext) "\n" "\n" "\n" - "\n", simply.str().c_str(), light.str().c_str(), fade.str().c_str(), smooth.str().c_str(), dilat.str().c_str(), erosion.str().c_str(), blur.str().c_str(), bdilat.str().c_str(), berosion.str().c_str(), stroker.str().c_str(), strokeg.str().c_str(), strokeb.str().c_str(), ios.str().c_str(), strokea.str().c_str(), offset.str().c_str(), offset.str().c_str(), fillr.str().c_str(), fillg.str().c_str(), fillb.str().c_str(), iof.str().c_str(), filla.str().c_str(), transluscent.str().c_str()); + "\n", simply.str().c_str(), clean.str().c_str(), erase.str().c_str(), smooth.str().c_str(), dilat.str().c_str(), erosion.str().c_str(), blur.str().c_str(), bdilat.str().c_str(), berosion.str().c_str(), stroker.str().c_str(), strokeg.str().c_str(), strokeb.str().c_str(), ios.str().c_str(), strokea.str().c_str(), offset.str().c_str(), offset.str().c_str(), fillr.str().c_str(), fillg.str().c_str(), fillb.str().c_str(), iof.str().c_str(), filla.str().c_str(), transluscent.str().c_str()); - return _filter; + return _filter; }; /* Drawing filter */ + /** - \brief Custom predefined Posterize filter. + \brief Custom predefined Neon draw filter. + + Posterize and draw smooth lines around color shapes + + Filter's parameters: + * Lines type (enum, default smooth) -> + smooth = component1 (type="table"), component2 (type="table"), composite1 (in2="blur2") + hard = component1 (type="discrete"), component2 (type="discrete"), composite1 (in2="component1") + * Simplify (0.01->20., default 1.5) -> blur1 (stdDeviation) + * Line width (0.01->20., default 1.5) -> blur2 (stdDeviation) + * Lightness (0.->10., default 5) -> composite1 (k3) + * Blend (enum [normal, multiply, screen], default normal) -> blend (mode) + * Dark mode (boolean, default false) -> composite1 (true: in2="component2") +*/ +class NeonDraw : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + NeonDraw ( ) : Filter() { }; + virtual ~NeonDraw ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Neon draw, custom") "\n" + "org.inkscape.effect.filter.NeonDraw\n" + "\n" + "<_item value=\"smooth\">Smoothed\n" + "<_item value=\"hard\">Contrasted\n" + "\n" + "1.5\n" + "1.5\n" + "5\n" + "\n" + "<_item value=\"normal\">Normal\n" + "<_item value=\"multiply\">Multiply\n" + "<_item value=\"screen\">Screen\n" + "\n" + "false\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Posterize and draw smooth lines around color shapes") "\n" + "\n" + "\n", new NeonDraw()); + }; +}; + +gchar const * +NeonDraw::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream blend; + std::ostringstream simply; + std::ostringstream width; + std::ostringstream lightness; + std::ostringstream type1; + std::ostringstream type2; + std::ostringstream dark; + + const gchar *type = ext->get_param_enum("type"); + if ((g_ascii_strcasecmp("smooth", type) == 0)) { + type1 << "table"; + type2 << "table"; + } else { + type1 << "discrete"; + type2 << "discrete"; + } + + blend << ext->get_param_enum("blend"); + simply << ext->get_param_float("simply"); + width << ext->get_param_float("width"); + lightness << ext->get_param_float("lightness"); + + if (ext->get_param_bool("dark")) + dark << "component2"; + else if ((g_ascii_strcasecmp("smooth", type) == 0)) + dark << "blur2"; + else + dark << "component1"; + + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n", blend.str().c_str(), simply.str().c_str(), type1.str().c_str(), type1.str().c_str(), type1.str().c_str(), width.str().c_str(), type2.str().c_str(), type2.str().c_str(), type2.str().c_str(), dark.str().c_str(), lightness.str().c_str()); + + return _filter; +}; /* NeonDraw filter */ + +/** + \brief Custom predefined Poster paint filter. Poster and painting effects. - Filter's parameters (not finished yet): + Filter's parameters: * Effect type (enum, default "Normal") -> Normal = feComponentTransfer Dented = Normal + intermediate values - * Blur (0.01->10., default 5.) -> blur3 (stdDeviation) - + * Transfer type (enum, default "descrete") -> component (type) + * Levels (1->15, default 5) -> component (tableValues) + * Blend mode (enum, default "Lighten") -> blend (mode) + * Primary blur (0.01->100., default 4.) -> blur1 (stdDeviation) + * Secondary blur (0.01->100., default 0.5) -> blur2 (stdDeviation) + * Pre-saturation (0.->1., default 1.) -> color1 (values) + * Post-saturation (0.->1., default 1.) -> color2 (values) + * Simulate antialiasing (boolean, default false) -> blur3 (true->stdDeviation=0.5, false->stdDeviation=0.01) */ class Posterize : public Inkscape::Extension::Internal::Filter::Filter { protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - Posterize ( ) : Filter() { }; - virtual ~Posterize ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Poster and painting, custom") "\n" - "org.inkscape.effect.filter.Posterize\n" - "\n" - "<_item value=\"normal\">Normal\n" - "<_item value=\"dented\">Dented\n" - "\n" - "\n" - "<_item value=\"discrete\">Poster\n" - "<_item value=\"table\">Painting\n" - "\n" - "5\n" - "\n" - "<_item value=\"lighten\">Lighten\n" - "<_item value=\"normal\">Normal\n" - "<_item value=\"darken\">Darken\n" - "\n" - "4.0\n" - "0.5\n" - "1.00\n" - "1.00\n" - "false\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Poster and painting effects") "\n" - "\n" - "\n", new Posterize()); - }; + Posterize ( ) : Filter() { }; + virtual ~Posterize ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Poster paint, custom") "\n" + "org.inkscape.effect.filter.Posterize\n" + "\n" + "<_item value=\"normal\">Normal\n" + "<_item value=\"dented\">Dented\n" + "\n" + "\n" + "<_item value=\"discrete\">Poster\n" + "<_item value=\"table\">Painting\n" + "\n" + "5\n" + "\n" + "<_item value=\"lighten\">Lighten\n" + "<_item value=\"normal\">Normal\n" + "<_item value=\"darken\">Darken\n" + "\n" + "4.0\n" + "0.5\n" + "1.00\n" + "1.00\n" + "false\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Poster and painting effects") "\n" + "\n" + "\n", new Posterize()); + }; }; gchar const * Posterize::get_filter_text (Inkscape::Extension::Extension * ext) { - if (_filter != NULL) g_free((void *)_filter); + if (_filter != NULL) g_free((void *)_filter); std::ostringstream table; std::ostringstream blendmode; @@ -475,28 +682,28 @@ Posterize::get_filter_text (Inkscape::Extension::Extension * ext) else antialias << "0.01"; - _filter = g_strdup_printf( - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" "\n", blur1.str().c_str(), blur2.str().c_str(), blendmode.str().c_str(), presat.str().c_str(), table.str().c_str(), transf.str().c_str(), table.str().c_str(), transf.str().c_str(), table.str().c_str(), transf.str().c_str(), postsat.str().c_str(), antialias.str().c_str()); - return _filter; + return _filter; }; /* Posterize filter */ /** - \brief Custom predefined PosterizeBasic filter. + \brief Custom predefined Posterize basic filter. Simple posterizing effect @@ -506,36 +713,36 @@ Posterize::get_filter_text (Inkscape::Extension::Extension * ext) */ class PosterizeBasic : public Inkscape::Extension::Internal::Filter::Filter { protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - PosterizeBasic ( ) : Filter() { }; - virtual ~PosterizeBasic ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Posterize basic, custom") "\n" - "org.inkscape.effect.filter.PosterizeBasic\n" - "5\n" - "4.0\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Simple posterizing effect") "\n" - "\n" - "\n", new PosterizeBasic()); - }; + PosterizeBasic ( ) : Filter() { }; + virtual ~PosterizeBasic ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Posterize basic, custom") "\n" + "org.inkscape.effect.filter.PosterizeBasic\n" + "5\n" + "4.0\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Simple posterizing effect") "\n" + "\n" + "\n", new PosterizeBasic()); + }; }; gchar const * PosterizeBasic::get_filter_text (Inkscape::Extension::Extension * ext) { - if (_filter != NULL) g_free((void *)_filter); + if (_filter != NULL) g_free((void *)_filter); std::ostringstream blur; std::ostringstream transf; @@ -551,18 +758,18 @@ PosterizeBasic::get_filter_text (Inkscape::Extension::Extension * ext) } transf << " 1"; - _filter = g_strdup_printf( - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" "\n", blur.str().c_str(), transf.str().c_str(), transf.str().c_str(), transf.str().c_str()); - return _filter; + return _filter; }; /* PosterizeBasic filter */ }; /* namespace Filter */ @@ -570,5 +777,5 @@ PosterizeBasic::get_filter_text (Inkscape::Extension::Extension * ext) }; /* namespace Extension */ }; /* namespace Inkscape */ -/* Change the 'COLOR' below to be your file name */ +/* Change the 'EXPERIMENTAL' below to be your file name */ #endif /* __INKSCAPE_EXTENSION_INTERNAL_FILTER_EXPERIMENTAL_H__ */ diff --git a/src/extension/internal/filter/filter-all.cpp b/src/extension/internal/filter/filter-all.cpp index 846725472..7383b793a 100755 --- a/src/extension/internal/filter/filter-all.cpp +++ b/src/extension/internal/filter/filter-all.cpp @@ -12,6 +12,7 @@ #include "color.h" #include "drop-shadow.h" #include "morphology.h" +#include "shadows.h" #include "snow.h" #include "experimental.h" @@ -34,13 +35,21 @@ Filter::filters_all (void ) // ABCs Blur::init(); + CleanEdges::init(); + ColorShift::init(); DiffuseLight::init(); + Feather::init(); + MatteJelly::init(); + NoiseFill::init(); + Outline::init(); Roughen::init(); + Silhouette::init(); SpecularLight::init(); // Color Colorize::init(); Duochrome::init(); + Electrize::init(); Quadritone::init(); Solarize::init(); Tritone::init(); @@ -53,7 +62,9 @@ Filter::filters_all (void ) // TDB Chromolitho::init(); + CrossEngraving::init(); Drawing::init(); + NeonDraw::init(); Posterize::init(); PosterizeBasic::init(); diff --git a/src/extension/internal/filter/morphology.h b/src/extension/internal/filter/morphology.h index 8e00b47be..5584ce506 100644 --- a/src/extension/internal/filter/morphology.h +++ b/src/extension/internal/filter/morphology.h @@ -3,7 +3,7 @@ /* Change the 'MORPHOLOGY' above to be your file name */ /* - * Copyright (C) 2010 Authors: + * Copyright (C) 2011 Authors: * Ivan Louette (filters) * Nicolas Dufour (UI) * @@ -39,40 +39,40 @@ namespace Filter { class Crosssmooth : public Inkscape::Extension::Internal::Filter::Filter { protected: - virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); public: - Crosssmooth ( ) : Filter() { }; - virtual ~Crosssmooth ( ) { if (_filter != NULL) g_free((void *)_filter); return; } - - static void init (void) { - Inkscape::Extension::build_from_mem( - "\n" - "" N_("Cross-smooth, custom (morphology)") "\n" - "org.inkscape.effect.filter.crosssmooth\n" - "\n" - "<_item value=\"edges\">Smooth edges\n" - "<_item value=\"all\">Smooth all\n" - "\n" - "5\n" - "\n" - "all\n" - "\n" - "\n" - "\n" - "\n" - "\n" - "" N_("Smooth edges and angles of shapes") "\n" - "\n" - "\n", new Crosssmooth()); - }; + Crosssmooth ( ) : Filter() { }; + virtual ~Crosssmooth ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Cross-smooth, custom (Morphology)") "\n" + "org.inkscape.effect.filter.crosssmooth\n" + "\n" + "<_item value=\"edges\">Smooth edges\n" + "<_item value=\"all\">Smooth all\n" + "\n" + "5\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Smooth edges and angles of shapes") "\n" + "\n" + "\n", new Crosssmooth()); + }; }; gchar const * Crosssmooth::get_filter_text (Inkscape::Extension::Extension * ext) { - if (_filter != NULL) g_free((void *)_filter); + if (_filter != NULL) g_free((void *)_filter); std::ostringstream blur; std::ostringstream c1in; @@ -86,16 +86,16 @@ Crosssmooth::get_filter_text (Inkscape::Extension::Extension * ext) c1in << "SourceGraphic"; } - _filter = g_strdup_printf( - "\n" - "\n" - "\n" - "\n" - "\n" - "\n" + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" "\n", blur.str().c_str(), c1in.str().c_str()); - return _filter; + return _filter; }; /* Crosssmooth filter */ }; /* namespace Filter */ @@ -103,5 +103,5 @@ Crosssmooth::get_filter_text (Inkscape::Extension::Extension * ext) }; /* namespace Extension */ }; /* namespace Inkscape */ -/* Change the 'COLOR' below to be your file name */ +/* Change the 'MORPHOLOGY' below to be your file name */ #endif /* __INKSCAPE_EXTENSION_INTERNAL_FILTER_MORPHOLOGY_H__ */ diff --git a/src/extension/internal/filter/shadows.h b/src/extension/internal/filter/shadows.h new file mode 100644 index 000000000..1924c5bb3 --- /dev/null +++ b/src/extension/internal/filter/shadows.h @@ -0,0 +1,111 @@ +#ifndef __INKSCAPE_EXTENSION_INTERNAL_FILTER_SHADOWS_H__ +#define __INKSCAPE_EXTENSION_INTERNAL_FILTER_SHADOWS_H__ +/* Change the 'SHADOWS' above to be your file name */ + +/* + * Copyright (C) 2011 Authors: + * Ivan Louette (filters) + * Nicolas Dufour (UI) + * + * Color filters + * Drop shadow + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ +/* ^^^ Change the copyright to be you and your e-mail address ^^^ */ + +#include "filter.h" + +#include "extension/internal/clear-n_.h" +#include "extension/system.h" +#include "extension/extension.h" + +namespace Inkscape { +namespace Extension { +namespace Internal { +namespace Filter { + +/** + \brief Custom predefined Drop shadow filter. + + Colorizable Drop shadow. + + Filter's parameters: + * Blur radius (0.->200., default 3) -> blur (stdDeviation) + * Horizontal offset (-50.->50., default 6.0) -> offset (dx) + * Vertical offset (-50.->50., default 6.0) -> offset (dy) + * Color (guint, default 0,0,0,127) -> flood (flood-opacity, flood-color) +*/ +class ColorizableDropShadow : public Inkscape::Extension::Internal::Filter::Filter { +protected: + virtual gchar const * get_filter_text (Inkscape::Extension::Extension * ext); + +public: + ColorizableDropShadow ( ) : Filter() { }; + virtual ~ColorizableDropShadow ( ) { if (_filter != NULL) g_free((void *)_filter); return; } + + static void init (void) { + Inkscape::Extension::build_from_mem( + "\n" + "" N_("Drop shadow, custom (Shadows and Glows)") "\n" + "org.inkscape.effect.filter.ColorDropShadow\n" + "3.0\n" + "6.0\n" + "6.0\n" + "127\n" + "\n" + "all\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "" N_("Colorizable Drop shadow") "\n" + "\n" + "\n", new ColorizableDropShadow()); + }; + +}; + +gchar const * +ColorizableDropShadow::get_filter_text (Inkscape::Extension::Extension * ext) +{ + if (_filter != NULL) g_free((void *)_filter); + + std::ostringstream blur; + std::ostringstream a; + std::ostringstream r; + std::ostringstream g; + std::ostringstream b; + std::ostringstream x; + std::ostringstream y; + + guint32 color = ext->get_param_color("color"); + + blur << ext->get_param_float("blur"); + x << ext->get_param_float("xoffset"); + y << ext->get_param_float("yoffset"); + a << (color & 0xff) / 255.0F; + r << ((color >> 24) & 0xff); + g << ((color >> 16) & 0xff); + b << ((color >> 8) & 0xff); + + _filter = g_strdup_printf( + "\n" + "\n" + "\n" + "\n" + "\n" + "\n" + "\n", a.str().c_str(), r.str().c_str(), g.str().c_str(), b.str().c_str(), blur.str().c_str(), x.str().c_str(), y.str().c_str()); + + return _filter; +}; + +}; /* namespace Filter */ +}; /* namespace Internal */ +}; /* namespace Extension */ +}; /* namespace Inkscape */ + +/* Change the 'SHADOWS' below to be your file name */ +#endif /* __INKSCAPE_EXTENSION_INTERNAL_FILTER_SHADOWS_H__ */ -- cgit v1.2.3 From 1239eae9d7c71b1d440eeb795de1984740c34df8 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Fri, 14 Jan 2011 12:06:57 +0100 Subject: Filters. Some custom predefined filters fixes and tweaks (Silhouette and Neon Draw). (bzr r10005) --- src/extension/internal/filter/abc.h | 4 ++-- src/extension/internal/filter/experimental.h | 28 ++++++++++------------------ 2 files changed, 12 insertions(+), 20 deletions(-) (limited to 'src') diff --git a/src/extension/internal/filter/abc.h b/src/extension/internal/filter/abc.h index b96585113..e0eeec7cb 100755 --- a/src/extension/internal/filter/abc.h +++ b/src/extension/internal/filter/abc.h @@ -717,7 +717,7 @@ Roughen::get_filter_text (Inkscape::Extension::Extension * ext) Repaint anything visible monochrome Filter's parameters: - * Blur (0.->50., default 0) -> blur (stdDeviation) + * Blur (0.01->50., default 0.01) -> blur (stdDeviation) * Cutout (boolean, default False) -> composite (false=in, true=out) * Color (guint, default 0,0,0,255) -> flood (flood-color, flood-opacity) */ @@ -735,7 +735,7 @@ public: "\n" "" N_("Silhouette, custom (ABCs)") "\n" "org.inkscape.effect.filter.Silhouette\n" - "0\n" + "0.01\n" "false\n" "255\n" "\n" diff --git a/src/extension/internal/filter/experimental.h b/src/extension/internal/filter/experimental.h index 0375f008d..07b376954 100755 --- a/src/extension/internal/filter/experimental.h +++ b/src/extension/internal/filter/experimental.h @@ -498,8 +498,8 @@ public: "" N_("Neon draw, custom") "\n" "org.inkscape.effect.filter.NeonDraw\n" "\n" - "<_item value=\"smooth\">Smoothed\n" - "<_item value=\"hard\">Contrasted\n" + "<_item value=\"table\">Smoothed\n" + "<_item value=\"discrete\">Contrasted\n" "\n" "1.5\n" "1.5\n" @@ -532,27 +532,19 @@ NeonDraw::get_filter_text (Inkscape::Extension::Extension * ext) std::ostringstream simply; std::ostringstream width; std::ostringstream lightness; - std::ostringstream type1; - std::ostringstream type2; + std::ostringstream type; std::ostringstream dark; - const gchar *type = ext->get_param_enum("type"); - if ((g_ascii_strcasecmp("smooth", type) == 0)) { - type1 << "table"; - type2 << "table"; - } else { - type1 << "discrete"; - type2 << "discrete"; - } - + type << ext->get_param_enum("type"); blend << ext->get_param_enum("blend"); simply << ext->get_param_float("simply"); width << ext->get_param_float("width"); lightness << ext->get_param_float("lightness"); + const gchar *typestr = ext->get_param_enum("type"); if (ext->get_param_bool("dark")) dark << "component2"; - else if ((g_ascii_strcasecmp("smooth", type) == 0)) + else if ((g_ascii_strcasecmp("table", typestr) == 0)) dark << "blur2"; else dark << "component1"; @@ -562,9 +554,9 @@ NeonDraw::get_filter_text (Inkscape::Extension::Extension * ext) "\n" "\n" "\n" - "\n" - "\n" - "\n" + "\n" + "\n" + "\n" "\n" "\n" "\n" @@ -574,7 +566,7 @@ NeonDraw::get_filter_text (Inkscape::Extension::Extension * ext) "\n" "\n" "\n" - "\n", blend.str().c_str(), simply.str().c_str(), type1.str().c_str(), type1.str().c_str(), type1.str().c_str(), width.str().c_str(), type2.str().c_str(), type2.str().c_str(), type2.str().c_str(), dark.str().c_str(), lightness.str().c_str()); + "\n", blend.str().c_str(), simply.str().c_str(), width.str().c_str(), type.str().c_str(), type.str().c_str(), type.str().c_str(), dark.str().c_str(), lightness.str().c_str()); return _filter; }; /* NeonDraw filter */ -- cgit v1.2.3 From 38bfe781de137c7173df661a5b99cef685a86e46 Mon Sep 17 00:00:00 2001 From: Adib Taraben Date: Mon, 17 Jan 2011 23:17:48 +0100 Subject: remove memory boundries on bitmap renderer, optimize memory usage Fixed bugs: - https://launchpad.net/bugs/494115 (bzr r10009) --- src/extension/internal/cairo-render-context.cpp | 38 +++++++++++++++++++------ src/extension/internal/cairo-renderer.cpp | 17 ++++++++++- src/helper/pixbuf-ops.cpp | 14 +++++++++ src/libnr/nr-pixblock.cpp | 24 ++++++++++------ 4 files changed, 75 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index 18a654e27..b68105b30 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -516,7 +516,7 @@ CairoRenderContext::getClipMode(void) const CairoRenderState* CairoRenderContext::_createState(void) { - CairoRenderState *state = (CairoRenderState*)g_malloc(sizeof(CairoRenderState)); + CairoRenderState *state = (CairoRenderState*)g_try_malloc(sizeof(CairoRenderState)); g_assert( state != NULL ); state->has_filtereffect = FALSE; @@ -796,7 +796,7 @@ CairoRenderContext::setupSurface(double width, double height) case CAIRO_SURFACE_TYPE_PDF: surface = cairo_pdf_surface_create_for_stream(Inkscape::Extension::Internal::_write_callback, _stream, width, height); #if (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 10, 0)) - cairo_pdf_surface_restrict_to_version(surface, (cairo_pdf_version_t)_pdf_level); + cairo_pdf_surface_restrict_to_version(surface, (cairo_pdf_version_t)_pdf_level); #endif break; #endif @@ -1420,9 +1420,20 @@ CairoRenderContext::renderImage(guchar *px, unsigned int w, unsigned int h, unsi if (_render_mode == RENDER_MODE_CLIP) return true; - guchar* px_rgba = (guchar*)g_malloc(4 * w * h); - if (!px_rgba) + guchar* px_rgba = NULL; + guint64 size = 4L * (guint64)w * (guint64)h; + + if(size < (guint64)G_MAXSIZE) { + px_rgba = (guchar*)g_try_malloc(4 * w * h); + if (!px_rgba) { + g_warning ("Could not allocate %lu bytes for pixel buffer!", (long unsigned) size); + return false; + } + } else { + g_warning ("the requested memory exceeds the system limit"); return false; + } + float opacity; if (_state->merge_opacity) @@ -1432,15 +1443,16 @@ CairoRenderContext::renderImage(guchar *px, unsigned int w, unsigned int h, unsi // make a copy of the original pixbuf with premultiplied alpha // if we pass the original pixbuf it will get messed up + /// @todo optimize this code, it costs a lot of time for (unsigned i = 0; i < h; i++) { + guchar const *src = px + i * rs; + guint32 *dst = (guint32 *)(px_rgba + i * rs); for (unsigned j = 0; j < w; j++) { - guchar const *src = px + i * rs + j * 4; - guint32 *dst = (guint32 *)(px_rgba + i * rs + j * 4); guchar r, g, b, alpha_dst; // calculate opacity-modified alpha alpha_dst = src[3]; - if (opacity != 1.0 && _vector_based_target) + if ((opacity != 1.0) && _vector_based_target) alpha_dst = (guchar)ceil((float)alpha_dst * opacity); // premul alpha (needed because this will be undone by cairo-pdf) @@ -1449,6 +1461,9 @@ CairoRenderContext::renderImage(guchar *px, unsigned int w, unsigned int h, unsi b = src[2]*alpha_dst/255; *dst = (((alpha_dst) << 24) | (((r)) << 16) | (((g)) << 8) | (b)); + + dst++; // pointer to 4byte variables + src += 4; // pointer to 1byte variables } } @@ -1497,8 +1512,13 @@ CairoRenderContext::_showGlyphs(cairo_t *cr, PangoFont *font, std::vector GLYPH_ARRAY_SIZE) - glyphs = (cairo_glyph_t*)g_malloc(sizeof(cairo_glyph_t) * num_glyphs); + if (num_glyphs > GLYPH_ARRAY_SIZE) { + glyphs = (cairo_glyph_t*)g_try_malloc(sizeof(cairo_glyph_t) * num_glyphs); + if(glyphs == NULL) { + g_warning("CairorenderContext::_showGlyphs: can not allocate memory for %d glyphs.", num_glyphs); + return 0; + } + } unsigned int num_invalid_glyphs = 0; unsigned int i = 0; // is a counter for indexing the glyphs array, only counts the valid glyphs diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index 67f9354d8..bc3c6c484 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -452,8 +452,23 @@ static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx) Geom::OptRect bbox = item->getBounds(item->i2d_affine(), SPItem::RENDERING_BBOX); - if (!bbox) // no bbox, e.g. empty group + // no bbox, e.g. empty group + if (!bbox) { return; + } + + Geom::Rect docrect(Geom::Rect(Geom::Point(0, 0), SP_OBJECT(item)->document->getDimensions())); + Geom::Rect bboxrect(Geom::Rect(Geom::Point(bbox->min()[Geom::X], bbox->min()[Geom::Y]), Geom::Point(bbox->max()[Geom::X], bbox->max()[Geom::Y]))); + + Geom::OptRect _bbox = Geom::intersect(docrect, bboxrect); + + // assign the object dimension clipped on the document, no need to draw on area not on canvas + bbox = _bbox; + + // no bbox, e.g. empty group + if (!bbox) { + return; + } // The width and height of the bitmap in pixels unsigned width = (unsigned) floor ((bbox->max()[Geom::X] - bbox->min()[Geom::X]) * (res / PX_PER_IN)); diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp index 69becad5d..7ce5c7dd2 100644 --- a/src/helper/pixbuf-ops.cpp +++ b/src/helper/pixbuf-ops.cpp @@ -91,6 +91,19 @@ sp_export_jpg_file(SPDocument *doc, gchar const *filename, else return false; } +/** + generates a bitmap from given items + the bitmap is stored in RAM and not written to file + @param x0 + @param y0 + @param x1 + @param y1 + @param width + @param height + @param xdpi + @param ydpi + @return the created GdkPixbuf structure or NULL if no memory is allocable +*/ GdkPixbuf* sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/, double x0, double y0, double x1, double y1, @@ -164,6 +177,7 @@ sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/, dtc[2] = NR_RGBA32_B(bgcolor); dtc[3] = NR_RGBA32_A(bgcolor); + // fill pixelblock using background colour for (gsize fy = 0; fy < height; fy++) { guchar *p = NR_PIXBLOCK_PX(&B) + fy * (gsize)B.rs; for (unsigned int fx = 0; fx < width; fx++) { diff --git a/src/libnr/nr-pixblock.cpp b/src/libnr/nr-pixblock.cpp index d69b6fe54..b95d8db8d 100644 --- a/src/libnr/nr-pixblock.cpp +++ b/src/libnr/nr-pixblock.cpp @@ -41,6 +41,13 @@ nr_pixblock_setup_fast (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, i h = y1 - y0; bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4; + guint64 sizel = (guint64)bpp * (guint64)w * (guint64)h; + + if(sizel > (guint64)G_MAXSIZE) { + g_warning ("the requested memory exceeds the system limit"); + return; + } + size = bpp * w * h; if (size <= NR_TINY_MAX) { @@ -67,8 +74,9 @@ nr_pixblock_setup_fast (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, i if (size > 100000000) { // Don't even try to allocate more than 100Mb (5000x5000 RGBA // pixels). It'll just bog the system down even if successful. FIXME: // Can anyone suggest something better than the magic number? - g_warning ("%lu bytes requested for pixel buffer, I won't try to allocate that.", (long unsigned) size); - return; + g_warning ("%lu bytes requested for pixel buffer, this will slow down the system.", (long unsigned) size); + // do not quit here, let the system decide for RAM usage + // return; } pb->data.px = g_try_new (unsigned char, size); if (pb->data.px == NULL) { // memory allocation failed @@ -144,7 +152,7 @@ nr_pixblock_setup_extern (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, w = x1 - x0; bpp = (mode == NR_PIXBLOCK_MODE_A8) ? 1 : (mode == NR_PIXBLOCK_MODE_R8G8B8) ? 3 : 4; - pb->size = NR_PIXBLOCK_SIZE_STATIC; + pb->size = NR_PIXBLOCK_SIZE_STATIC; pb->mode = mode; pb->empty = empty; pb->visible_area.x0 = pb->area.x0 = x0; @@ -157,9 +165,9 @@ nr_pixblock_setup_extern (NRPixBlock *pb, NR_PIXBLOCK_MODE mode, int x0, int y0, g_assert (pb->data.px != NULL); if (clear) { if (rs == bpp * w) { - /// \todo How do you recognise if - /// px was an uncleared tiny buffer? - if (pb->data.px) + /// \todo How do you recognise if + /// px was an uncleared tiny buffer? + if (pb->data.px) memset (pb->data.px, 0x0, bpp * (y1 - y0) * w); } else { int y; @@ -289,7 +297,7 @@ nr_pixelstore_4K_new (bool clear, unsigned char val) } else { px = g_new (unsigned char, 4096); } - + if (clear) memset (px, val, 4096); return px; @@ -323,7 +331,7 @@ nr_pixelstore_16K_new (bool clear, unsigned char val) } else { px = g_new (unsigned char, 16384); } - + if (clear) memset (px, val, 16384); return px; -- cgit v1.2.3 From 59bf824c3cbdb23ae5b656500451a8224f82d977 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Fri, 21 Jan 2011 14:38:26 +0100 Subject: DBUS. Patch for Bug #696062, dbus builds no more. Fixed bugs: - https://launchpad.net/bugs/696062 (bzr r10011) --- src/extension/dbus/dbus-init.cpp | 4 ++-- src/extension/dbus/document-interface.cpp | 39 +++++++++++++++++-------------- src/extension/dbus/document-interface.h | 2 +- 3 files changed, 24 insertions(+), 21 deletions(-) (limited to 'src') diff --git a/src/extension/dbus/dbus-init.cpp b/src/extension/dbus/dbus-init.cpp index 253d6b938..2ae606940 100644 --- a/src/extension/dbus/dbus-init.cpp +++ b/src/extension/dbus/dbus-init.cpp @@ -106,10 +106,10 @@ init_document (void) { DBusGProxy *proxy; SPDocument *doc; - doc = sp_document_new(NULL, 1, TRUE); + doc = SPDocument::createNewDoc(NULL, 1, TRUE); std::string name("/org/inkscape/"); - name.append(doc->name); + name.append(doc->getName()); std::replace(name.begin(), name.end(), ' ', '_'); connection = dbus_get_connection(); diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index 836ad3397..485e92aa6 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -52,6 +52,8 @@ #include "live_effects/parameter/text.h" //text #include "display/canvas-text.h" //text +#include "display/sp-canvas.h" //text + //#include "2geom/svg-path-parser.h" //get_node_coordinates /**************************************************************************** @@ -74,7 +76,7 @@ get_repr_by_name (SPDesktop *desk, gchar *name, GError **error) /* ALTERNATIVE (is this faster if only repr is needed?) Inkscape::XML::Node *node = sp_repr_lookup_name((doc->root)->repr, name); */ - Inkscape::XML::Node * node = sp_desktop_document(desk)->getObjectById(name)->repr; + Inkscape::XML::Node * node = sp_desktop_document(desk)->getObjectById(name)->getRepr(); if (!node) { g_set_error(error, INKSCAPE_ERROR, INKSCAPE_ERROR_OBJECT, "Object '%s' not found in document.", name); @@ -120,7 +122,7 @@ dbus_check_string (gchar *string, GError ** error, const gchar * errorstr) const gchar * get_name_from_object (SPObject * obj) { - return obj->repr->attribute("id"); + return obj->getRepr()->attribute("id"); } /* @@ -218,7 +220,8 @@ finish_create_shape (DocumentInterface *object, GError **error, Inkscape::XML::N object->desk->currentLayer()->updateRepr(); if (object->updates) - sp_document_done(sp_desktop_document(object->desk), 0, (gchar *)desc); + + Inkscape::DocumentUndo::done(sp_desktop_document(object->desk), 0, (gchar *)desc); //else //document_interface_pause_updates(object, error); @@ -248,7 +251,7 @@ dbus_call_verb (DocumentInterface *object, int verbid, GError **error) //document_interface_pause_updates (object, error); sp_action_perform( action, NULL ); if (object->updates) - sp_document_done(sp_desktop_document(desk2), verb->get_code(), g_strdup(verb->get_tip())); + Inkscape::DocumentUndo::done(sp_desktop_document(desk2), verb->get_code(), g_strdup(verb->get_tip())); //if (!object->updates) //document_interface_pause_updates (object, error); return TRUE; @@ -356,7 +359,7 @@ document_interface_call_verb (DocumentInterface *object, gchar *verbid, GError * if ( action ) { sp_action_perform( action, NULL ); if (object->updates) { - sp_document_done(sp_desktop_document(desk2), verb->get_code(), g_strdup(verb->get_tip())); + Inkscape::DocumentUndo::done(sp_desktop_document(desk2), verb->get_code(), g_strdup(verb->get_tip())); } } } @@ -511,7 +514,7 @@ document_interface_image (DocumentInterface *object, int x, int y, gchar *filena object->desk->currentLayer()->updateRepr(); if (object->updates) - sp_document_done(sp_desktop_document(object->desk), 0, "Imported bitmap."); + Inkscape::DocumentUndo::done(sp_desktop_document(object->desk), 0, "Imported bitmap."); //g_free(uri); return strdup(newNode->attribute("id")); @@ -528,7 +531,7 @@ gchar *document_interface_node (DocumentInterface *object, gchar *type, GError * object->desk->currentLayer()->updateRepr(); if (object->updates) - sp_document_done(sp_desktop_document(object->desk), 0, (gchar *)"created empty node"); + Inkscape::DocumentUndo::done(sp_desktop_document(object->desk), 0, (gchar *)"created empty node"); //else //document_interface_pause_updates(object, error); @@ -541,13 +544,13 @@ gchar *document_interface_node (DocumentInterface *object, gchar *type, GError * gdouble document_interface_document_get_width (DocumentInterface *object) { - return sp_document_width(sp_desktop_document(object->desk)); + return sp_desktop_document(object->desk)->getWidth(); } gdouble document_interface_document_get_height (DocumentInterface *object) { - return sp_document_height(sp_desktop_document(object->desk)); + return sp_desktop_document(object->desk)->getHeight(); } gchar * @@ -829,9 +832,9 @@ gboolean document_interface_save (DocumentInterface *object, GError **error) { SPDocument * doc = sp_desktop_document(object->desk); - printf("1: %s\n2: %s\n3: %s\n", doc->uri, doc->base, doc->name); - if (doc->uri) - return document_interface_save_as (object, doc->uri, error); + printf("1: %s\n2: %s\n3: %s\n", doc->getURI(), doc->getBase(), doc->getName()); + if (doc->getURI()) + return document_interface_save_as (object, doc->getURI(), error); return FALSE; } @@ -843,13 +846,13 @@ document_interface_load (DocumentInterface *object, const Glib::ustring file(filename); sp_file_open(file, NULL, TRUE, TRUE); if (object->updates) - sp_document_done(sp_desktop_document(object->desk), SP_VERB_FILE_OPEN, "Opened File"); + Inkscape::DocumentUndo::done(sp_desktop_document(object->desk), SP_VERB_FILE_OPEN, "Opened File"); return TRUE; } gboolean document_interface_save_as (DocumentInterface *object, - gchar *filename, GError **error) + const gchar *filename, GError **error) { SPDocument * doc = sp_desktop_document(object->desk); #ifdef WITH_GNOME_VFS @@ -950,7 +953,7 @@ document_interface_resume_updates (DocumentInterface *object, GError **error) //sp_desktop_document(object->desk)->root->mflags = TRUE; //sp_desktop_document(object->desk)->_updateDocument(); //FIXME: use better verb than rect. - sp_document_done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions"); + Inkscape::DocumentUndo::done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions"); } void @@ -963,7 +966,7 @@ document_interface_update (DocumentInterface *object, GError **error) object->desk->disableInteraction(); sp_desktop_document(object->desk)->root->uflags = FALSE; sp_desktop_document(object->desk)->root->mflags = FALSE; - //sp_document_done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions"); + //Inkscape::DocumentUndo::done(sp_desktop_document(object->desk), SP_VERB_CONTEXT_RECT, "Multiple actions"); } /**************************************************************************** @@ -982,7 +985,7 @@ document_interface_selection_get (DocumentInterface *object, char ***out, GError int i = 0; for (GSList const *iter = oldsel; iter != NULL; iter = iter->next) { - (*out)[i] = g_strdup(SP_OBJECT(iter->data)->repr->attribute("id")); + (*out)[i] = g_strdup(SP_OBJECT(iter->data)->getRepr()->attribute("id")); i++; } (*out)[i] = NULL; @@ -1188,7 +1191,7 @@ document_interface_selection_move_to_layer (DocumentInterface *object, if (!next) return FALSE; - if (strcmp("layer", (next->repr)->attribute("inkscape:groupmode")) == 0) { + if (strcmp("layer", (next->getRepr())->attribute("inkscape:groupmode")) == 0) { sp_selection_cut(dt); diff --git a/src/extension/dbus/document-interface.h b/src/extension/dbus/document-interface.h index 8cf9b7ec1..ac9fd11c1 100644 --- a/src/extension/dbus/document-interface.h +++ b/src/extension/dbus/document-interface.h @@ -224,7 +224,7 @@ document_interface_load (DocumentInterface *object, gboolean document_interface_save_as (DocumentInterface *object, - gchar *filename, GError **error); + const gchar *filename, GError **error); gboolean document_interface_mark_as_unmodified (DocumentInterface *object, GError **error); -- cgit v1.2.3 From b628a592e914a1e273bb8bfafe68d6f867f638fe Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Fri, 21 Jan 2011 15:09:54 +0100 Subject: Packaging. New Brazilian Portuguese NSH file. Set trunk package date to 2011. (bzr r10012) --- src/inkscape.rc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/inkscape.rc b/src/inkscape.rc index 08746aa77..e3e79ffe5 100644 --- a/src/inkscape.rc +++ b/src/inkscape.rc @@ -15,7 +15,7 @@ BEGIN VALUE "FileDescription", "Inkscape" VALUE "FileVersion", "0.48+devel" VALUE "InternalName", "Inkscape" - VALUE "LegalCopyright", " 2010 Inkscape" + VALUE "LegalCopyright", " 2011 Inkscape" VALUE "ProductName", "Inkscape" VALUE "ProductVersion", "0.48+devel" END -- cgit v1.2.3 From 424fa910ddd905695dd4b318bca01374109e16c4 Mon Sep 17 00:00:00 2001 From: Adib Taraben Date: Sat, 22 Jan 2011 22:34:27 +0100 Subject: add pdf import filter via poppler-cairo (bzr r10014) --- src/extension/init.cpp | 4 ++-- src/extension/internal/pdf-input-cairo.cpp | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/extension/init.cpp b/src/extension/init.cpp index 8578e8c6c..230d4b50f 100644 --- a/src/extension/init.cpp +++ b/src/extension/init.cpp @@ -166,7 +166,7 @@ init() Internal::PdfInput::init(); #endif #ifdef HAVE_POPPLER_GLIB - if (0) { + if (1) { Internal::PdfInputCairo::init(); } #endif @@ -192,7 +192,7 @@ init() #ifdef WITH_DBUS Dbus::init(); #endif - + /* Raster Effects */ #ifdef WITH_IMAGE_MAGICK Internal::Bitmap::AdaptiveThreshold::init(); diff --git a/src/extension/internal/pdf-input-cairo.cpp b/src/extension/internal/pdf-input-cairo.cpp index 2c7ea3b33..6657ea222 100644 --- a/src/extension/internal/pdf-input-cairo.cpp +++ b/src/extension/internal/pdf-input-cairo.cpp @@ -87,11 +87,11 @@ PdfInputCairo::init(void) { ext = Inkscape::Extension::build_from_mem( "\n" "PDF Input\n" - "org.inkscape.input.pdf\n" + "org.inkscape.input.cairo-pdf\n" "\n" ".pdf\n" "application/pdf\n" - "Adobe PDF (*.pdf)\n" + "Adobe PDF via poppler-cairo (*.pdf)\n" "PDF Document\n" "\n" "", new PdfInputCairo()); -- cgit v1.2.3 From 7ba5c49ab85443492e06351c360c4879610127f4 Mon Sep 17 00:00:00 2001 From: Alvin Penner Date: Mon, 24 Jan 2011 19:02:40 -0500 Subject: emf import: redefine the device scale (Bug 341847) Fixed bugs: - https://launchpad.net/bugs/341847 (bzr r10017) --- src/extension/internal/emf-win32-inout.cpp | 25 +++++++++++++++---------- 1 file changed, 15 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/extension/internal/emf-win32-inout.cpp b/src/extension/internal/emf-win32-inout.cpp index 34cdecdca..d147a0c81 100644 --- a/src/extension/internal/emf-win32-inout.cpp +++ b/src/extension/internal/emf-win32-inout.cpp @@ -80,6 +80,7 @@ namespace Inkscape { namespace Extension { namespace Internal { +static float device_scale = DEVICESCALE; EmfWin32::EmfWin32 (void) // The null constructor { @@ -340,7 +341,7 @@ pix_to_x_point(PEMF_CALLBACK_DATA d, double px, double py) double ppy = _pix_y_to_point(d, py); double x = ppx * d->dc[d->level].worldTransform.eM11 + ppy * d->dc[d->level].worldTransform.eM21 + d->dc[d->level].worldTransform.eDx; - x *= d->dc[d->level].ScaleOutX ? d->dc[d->level].ScaleOutX : DEVICESCALE; + x *= d->dc[d->level].ScaleOutX ? d->dc[d->level].ScaleOutX : device_scale; return x; } @@ -352,7 +353,7 @@ pix_to_y_point(PEMF_CALLBACK_DATA d, double px, double py) double ppy = _pix_y_to_point(d, py); double y = ppx * d->dc[d->level].worldTransform.eM12 + ppy * d->dc[d->level].worldTransform.eM22 + d->dc[d->level].worldTransform.eDy; - y *= d->dc[d->level].ScaleOutY ? d->dc[d->level].ScaleOutY : DEVICESCALE; + y *= d->dc[d->level].ScaleOutY ? d->dc[d->level].ScaleOutY : device_scale; return y; } @@ -364,9 +365,9 @@ pix_to_size_point(PEMF_CALLBACK_DATA d, double px) double ppy = 0; double dx = ppx * d->dc[d->level].worldTransform.eM11 + ppy * d->dc[d->level].worldTransform.eM21; - dx *= d->dc[d->level].ScaleOutX ? d->dc[d->level].ScaleOutX : DEVICESCALE; + dx *= d->dc[d->level].ScaleOutX ? d->dc[d->level].ScaleOutX : device_scale; double dy = ppx * d->dc[d->level].worldTransform.eM12 + ppy * d->dc[d->level].worldTransform.eM22; - dy *= d->dc[d->level].ScaleOutY ? d->dc[d->level].ScaleOutY : DEVICESCALE; + dy *= d->dc[d->level].ScaleOutY ? d->dc[d->level].ScaleOutY : device_scale; double tmp = sqrt(dx * dx + dy * dy); return tmp; @@ -785,14 +786,18 @@ myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD const * d->xDPI = 2540; d->yDPI = 2540; - d->dc[d->level].PixelsInX = pEmr->rclFrame.right - pEmr->rclFrame.left; - d->dc[d->level].PixelsInY = pEmr->rclFrame.bottom - pEmr->rclFrame.top; + d->dc[d->level].PixelsInX = pEmr->rclFrame.right; // - pEmr->rclFrame.left; + d->dc[d->level].PixelsInY = pEmr->rclFrame.bottom; // - pEmr->rclFrame.top; d->MMX = d->dc[d->level].PixelsInX / 100.0; d->MMY = d->dc[d->level].PixelsInY / 100.0; d->dc[d->level].PixelsOutX = d->MMX * PX_PER_MM; d->dc[d->level].PixelsOutY = d->MMY * PX_PER_MM; + + // calculate ratio of Inkscape dpi/device dpi + if (pEmr->szlMillimeters.cx && pEmr->szlDevice.cx) + device_scale = PX_PER_MM*pEmr->szlMillimeters.cx/pEmr->szlDevice.cx; tmp_outsvg << " width=\"" << d->MMX << "mm\"\n" << @@ -1071,8 +1076,8 @@ myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD const * d->dc[d->level].ScaleOutY = (double) d->dc[d->level].PixelsOutY / (double) d->dc[d->level].sizeView.cy; } else { - d->dc[d->level].ScaleOutX = DEVICESCALE; - d->dc[d->level].ScaleOutY = DEVICESCALE; + d->dc[d->level].ScaleOutX = device_scale; + d->dc[d->level].ScaleOutY = device_scale; } break; @@ -1122,8 +1127,8 @@ myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD const * d->dc[d->level].ScaleOutY = (double) d->dc[d->level].PixelsOutY / (double) d->dc[d->level].sizeView.cy; } else { - d->dc[d->level].ScaleOutX = DEVICESCALE; - d->dc[d->level].ScaleOutY = DEVICESCALE; + d->dc[d->level].ScaleOutX = device_scale; + d->dc[d->level].ScaleOutY = device_scale; } break; -- cgit v1.2.3 From 92bc8e6b4a43a30db9a9aff628bde011434cef0d Mon Sep 17 00:00:00 2001 From: Alvin Penner Date: Thu, 27 Jan 2011 18:42:51 -0500 Subject: emf import : recalculate text alignment for rotated text (Bug 341847) (bzr r10019) --- src/extension/internal/emf-win32-inout.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/extension/internal/emf-win32-inout.cpp b/src/extension/internal/emf-win32-inout.cpp index d147a0c81..c817f6d46 100644 --- a/src/extension/internal/emf-win32-inout.cpp +++ b/src/extension/internal/emf-win32-inout.cpp @@ -1777,8 +1777,13 @@ myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD const * } if (!(d->dc[d->level].textAlign & TA_BOTTOM)) - y1 += fabs(d->dc[d->level].style.font_size.computed); - + if (d->dc[d->level].style.text_transform.value) { + x1 += std::sin(d->dc[d->level].style.text_transform.value*M_PI/180.0)*fabs(d->dc[d->level].style.font_size.computed); + y1 += std::cos(d->dc[d->level].style.text_transform.value*M_PI/180.0)*fabs(d->dc[d->level].style.font_size.computed); + } + else + y1 += fabs(d->dc[d->level].style.font_size.computed); + double x = pix_to_x_point(d, x1, y1); double y = pix_to_y_point(d, x1, y1); -- cgit v1.2.3 From 68a87c54e8134effdb8169d895d434441d3b2299 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Mon, 31 Jan 2011 17:48:10 +0100 Subject: Extensions. Fix for Bug #668895 (Extensions with tags fail to load). (bzr r10020) --- src/extension/implementation/script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index bc143fd14..428ee626f 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -236,7 +236,7 @@ bool Script::check_existence(const std::string &command) } //Don't search when it is an absolute path. */ - if (!Glib::path_is_absolute(command)) { + if (Glib::path_is_absolute(command)) { if (Glib::file_test(command, Glib::FILE_TEST_EXISTS)) { return true; } else { -- cgit v1.2.3 From 73ffe9d1cd4a0e099668d2c7f9c13a859df015a6 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Mon, 31 Jan 2011 22:29:13 +0100 Subject: OCAL. Fix for Bug #638844 (Errors printed to console if openclipart search fails). (bzr r10021) --- src/ui/dialog/ocaldialogs.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/ui/dialog/ocaldialogs.cpp b/src/ui/dialog/ocaldialogs.cpp index d3887b1ca..2ae7d6989 100644 --- a/src/ui/dialog/ocaldialogs.cpp +++ b/src/ui/dialog/ocaldialogs.cpp @@ -470,7 +470,7 @@ void FileImportFromOCALDialog::searchTagEntryChangedCallback() doc = xmlReadIO ((xmlInputReadCallback) vfs_read_callback, (xmlInputCloseCallback) gnome_vfs_close, from_handle, uri.c_str(), NULL, - XML_PARSE_RECOVER); + XML_PARSE_RECOVER + XML_PARSE_NOWARNING + XML_PARSE_NOERROR); if (doc == NULL) { sp_ui_error_dialog(_("Server supplied malformed Clip Art feed")); g_warning("Failed to parse %s\n", uri.c_str()); -- cgit v1.2.3 From 0f535660ee7c8ba0a6befb9066a9f97168e034db Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Wed, 2 Feb 2011 18:26:59 +0100 Subject: Extensions. Check element now search in the extension directory (see Bug #668895, Extensions with tags fail to load). (bzr r10023) --- src/extension/implementation/script.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index 428ee626f..0f234c7d4 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -45,7 +45,7 @@ #include "xml/attribute-record.h" #include "util/glib-list-iterators.h" - +#include "path-prefix.h" #ifdef WIN32 @@ -229,7 +229,6 @@ Script::solve_reldir(Inkscape::XML::Node *reprin) { */ bool Script::check_existence(const std::string &command) { - // Check the simple case first if (command.empty()) { return false; @@ -243,13 +242,14 @@ bool Script::check_existence(const std::string &command) return false; } } - - std::string path = Glib::getenv("PATH"); - if (path.empty()) { - /* There is no `PATH' in the environment. - The default search path is the current directory */ - path = G_SEARCHPATH_SEPARATOR_S; - } + + // First search in the extension path and the current directory + std::string path = INKSCAPE_EXTENSIONDIR; + path.append(";"); + path.append(G_SEARCHPATH_SEPARATOR_S); + path.append(";"); + // And then the PATH environment variable. + path.append(Glib::getenv("PATH")); std::string::size_type pos = 0; std::string::size_type pos2 = 0; -- cgit v1.2.3 From 99d8844117a8f40fb971afe92f87b1751a82e9f7 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Wed, 2 Feb 2011 19:57:09 +0100 Subject: Translations. French translation minor update. Contributors. Authors and translators lists update. (bzr r10024) --- src/ui/dialog/aboutbox.cpp | 552 +++++++++++++++++++++++---------------------- 1 file changed, 279 insertions(+), 273 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/aboutbox.cpp b/src/ui/dialog/aboutbox.cpp index 61851c56c..56c794713 100644 --- a/src/ui/dialog/aboutbox.cpp +++ b/src/ui/dialog/aboutbox.cpp @@ -225,152 +225,156 @@ void AboutBox::initStrings() { * and paste the result from the combo box here. */ authors_text = - "Maximilian Albert\n" - "Josh Andler\n" - "Tavmjong Bah\n" - "Pierre Barbry-Blot\n" - "Jean-François Barraud\n" - "Bill Baxter\n" - "John Beard\n" - "John Bintz\n" - "Arpad Biro\n" - "Nicholas Bishop\n" - "Joshua L. Blocher\n" - "Henrik Bohre\n" - "Boldewyn\n" - "Daniel Borgmann\n" - "Bastien Bouclet\n" - "Hans Breuer\n" - "Gustav Broberg\n" - "Christopher Brown\n" - "Marcus Brubaker\n" - "Luca Bruno\n" - "Nicu Buculei\n" - "Bulia Byak\n" - "Pierre Caclin\n" - "Ian Caldwell\n" - "Gail Carmichael\n" - "Ed Catmur\n" - "Chema Celorio\n" - "Johan Ceuppens\n" - "Zbigniew Chyla\n" - "Alexander Clausen\n" - "John Cliff\n" - "Kees Cook\n" - "Ben Cromwell\n" - "Robert Crosbie\n" - "Jon Cruz\n" - "Aurélie De-Cooman\n" - "Milosz Derezynski\n" - "Daniel Díaz\n" - "Bruno Dilly\n" - "Larry Doolittle\n" - "Tim Dwyer\n" - "Maxim V. Dziumanenko\n" - "Johan Engelen\n" - "Miklos Erdelyi\n" - "Ulf Erikson\n" - "Noé Falzon\n" - "Frank Felfe\n" - "Andrew Fitzsimon\n" - "Edward Flick\n" - "Marcin Floryan\n" - "Ben Fowler\n" - "Fred\n" - "Cedric Gemy\n" - "Steren Giannini\n" - "Olivier Gondouin\n" - "Ted Gould\n" - "Toine de Greef\n" - "Michael Grosberg\n" - "Bryce Harrington\n" - "Dale Harvey\n" - "Aurélio A. Heckert\n" - "Carl Hetherington\n" - "Jos Hirth\n" - "Hannes Hochreiner\n" - "Thomas Holder\n" - "Joel Holdsworth\n" - "Alan Horkan\n" - "Karl Ove Hufthammer\n" - "Richard Hughes\n" - "Nathan Hurst\n" - "inductiveload\n" - "Thomas Ingham\n" - "Jean-Olivier Irisson\n" - "Bob Jamison\n" - "jEsuSdA\n" - "Lauris Kaplinski\n" - "Lynn Kerby\n" - "Niko Kiirala\n" - "James Kilfiger\n" - "Jason Kivlighn\n" - "Adrian Knoth\n" - "Krzysztof Kosiński\n" - "Petr Kovar\n" - "Benoît Lavorata\n" - "Alex Leone\n" - "Julien Leray\n" - "Raph Levien\n" - "Diederik van Lierop\n" - "Nicklas Lindgren\n" - "Vitaly Lipatov\n" - "Ivan Louette\n" - "Pierre-Antoine Marc\n" - "Aurel-Aimé Marmion\n" - "Colin Marquardt\n" - "Dmitry G. Mastrukov\n" - "Matiphas\n" - "Michael Meeks\n" - "Federico Mena\n" - "MenTaLguY\n" - "Aubanel Monnier\n" - "Vincent Montagne\n" - "Tim Mooney\n" - "Derek P. Moore\n" - "Peter Moulder\n" - "Jörg Müller\n" - "Yukihiro Nakai\n" - "Victor Navez\n" - "Christian Neumair\n" - "Andreas Nilsson\n" - "Mitsuru Oka\n" - "Marten Owens\n" - "Alvin Penner\n" - "Jon Phillips\n" - "Zdenko Podobny\n" - "Alexandre Prokoudine\n" - "Jean-René Reinhard\n" - "Alexey Remizov\n" - "Frederic Rodrigo\n" - "Hugo Rodrigues\n" - "Juarez Rudsatz\n" - "Xavier Conde Rueda\n" - "Felipe Corrêa da Silva Sanches\n" - "Christian Schaller\n" - "Marco Scholten\n" - "Tom von Schwerdtner\n" - "Danilo Šegan\n" - "Shivaken\n" - "Michael Sloan\n" - "Boštjan Špetič\n" - "Aaron Spike\n" - "Kaushik Sridharan\n" - "Ralf Stephan\n" - "Dariusz Stojek\n" - "Martin Sucha\n" - "Pat Suwalski\n" - "Adib Taraben\n" - "Hugh Tebby\n" - "Jonas Termeau\n" - "David Turner\n" - "Andre Twupack\n" - "Aleksandar Urošević\n" - "Lucas Vieites\n" - "Michael Wybrow\n" - "Daniel Yacob\n" - "Masatake Yamato\n" - "David Yip"; +"Maximilian Albert\n" +"Josh Andler\n" +"Tavmjong Bah\n" +"Pierre Barbry-Blot\n" +"Jean-François Barraud\n" +"Bill Baxter\n" +"John Beard\n" +"John Bintz\n" +"Arpad Biro\n" +"Nicholas Bishop\n" +"Joshua L. Blocher\n" +"Henrik Bohre\n" +"Boldewyn\n" +"Daniel Borgmann\n" +"Bastien Bouclet\n" +"Hans Breuer\n" +"Gustav Broberg\n" +"Christopher Brown\n" +"Marcus Brubaker\n" +"Luca Bruno\n" +"Nicu Buculei\n" +"Bulia Byak\n" +"Pierre Caclin\n" +"Ian Caldwell\n" +"Gail Carmichael\n" +"Ed Catmur\n" +"Chema Celorio\n" +"Johan Ceuppens\n" +"Zbigniew Chyla\n" +"Alexander Clausen\n" +"John Cliff\n" +"Kees Cook\n" +"Ben Cromwell\n" +"Robert Crosbie\n" +"Jon Cruz\n" +"Aurélie De-Cooman\n" +"Milosz Derezynski\n" +"Daniel Díaz\n" +"Bruno Dilly\n" +"Larry Doolittle\n" +"Nicolas Dufour\n" +"Tim Dwyer\n" +"Maxim V. Dziumanenko\n" +"Johan Engelen\n" +"Miklos Erdelyi\n" +"Ulf Erikson\n" +"Noé Falzon\n" +"Frank Felfe\n" +"Andrew Fitzsimon\n" +"Edward Flick\n" +"Marcin Floryan\n" +"Ben Fowler\n" +"Fred\n" +"Cedric Gemy\n" +"Steren Giannini\n" +"Olivier Gondouin\n" +"Ted Gould\n" +"Toine de Greef\n" +"Michael Grosberg\n" +"Bryce Harrington\n" +"Dale Harvey\n" +"Aurélio Heckert\n" +"Aurélio A. Heckert\n" +"Carl Hetherington\n" +"Jos Hirth\n" +"Hannes Hochreiner\n" +"Thomas Holder\n" +"Joel Holdsworth\n" +"Alan Horkan\n" +"Karl Ove Hufthammer\n" +"Richard Hughes\n" +"Nathan Hurst\n" +"inductiveload\n" +"Thomas Ingham\n" +"Jean-Olivier Irisson\n" +"Bob Jamison\n" +"jEsuSdA\n" +"Lauris Kaplinski\n" +"Lynn Kerby\n" +"Niko Kiirala\n" +"James Kilfiger\n" +"Jason Kivlighn\n" +"Adrian Knoth\n" +"Krzysztof Kosiński\n" +"Petr Kovar\n" +"Benoît Lavorata\n" +"Alex Leone\n" +"Julien Leray\n" +"Raph Levien\n" +"Diederik van Lierop\n" +"Nicklas Lindgren\n" +"Vitaly Lipatov\n" +"Ivan Louette\n" +"Pierre-Antoine Marc\n" +"Aurel-Aimé Marmion\n" +"Colin Marquardt\n" +"Craig Marshall\n" +"Dmitry G. Mastrukov\n" +"Matiphas\n" +"Michael Meeks\n" +"Federico Mena\n" +"MenTaLguY\n" +"Aubanel Monnier\n" +"Vincent Montagne\n" +"Tim Mooney\n" +"Derek P. Moore\n" +"Peter Moulder\n" +"Jörg Müller\n" +"Yukihiro Nakai\n" +"Victor Navez\n" +"Christian Neumair\n" +"Andreas Nilsson\n" +"Mitsuru Oka\n" +"Marten Owens\n" +"Alvin Penner\n" +"Jon Phillips\n" +"Zdenko Podobny\n" +"Alexandre Prokoudine\n" +"Jean-René Reinhard\n" +"Alexey Remizov\n" +"Frederic Rodrigo\n" +"Hugo Rodrigues\n" +"Juarez Rudsatz\n" +"Xavier Conde Rueda\n" +"Felipe Corrêa da Silva Sanches\n" +"Christian Schaller\n" +"Marco Scholten\n" +"Tom von Schwerdtner\n" +"Danilo Šegan\n" +"Abhishek Sharma\n" +"Shivaken\n" +"Michael Sloan\n" +"Boštjan Špetič\n" +"Aaron Spike\n" +"Kaushik Sridharan\n" +"Ralf Stephan\n" +"Dariusz Stojek\n" +"Martin Sucha\n" +"Pat Suwalski\n" +"Adib Taraben\n" +"Hugh Tebby\n" +"Jonas Termeau\n" +"David Turner\n" +"Andre Twupack\n" +"Aleksandar Urošević\n" +"Lucas Vieites\n" +"Michael Wybrow\n" +"Daniel Yacob\n" +"Masatake Yamato\n" +"David Yip"; //############################## //# T R A N S L A T O R S @@ -409,133 +413,135 @@ void AboutBox::initStrings() { * and paste the result from the combo box here. */ gchar const *allTranslators = - "3ARRANO.com <3arrano@3arrano.com>, 2005.\n" - "Adib Taraben , 2004.\n" - "Alan Monfort , 2009-2010.\n" - "Alastair McKinstry , 2000.\n" - "Aleksandar Urošević , 2004, 2005, 2006.\n" - "Alessio Frusciante , 2002, 2003.\n" - "Alexander Shopov , 2006.\n" - "Alexandre Prokoudine , 2005.\n" - "Alexey Remizov , 2004.\n" - "Ali Ghanavatian , 2010.\n" - "Álvaro Lopes , 2001, 2002.\n" - "Andreas Hyden , 2000.\n" - "Andrius Ramanauskas , 2006.\n" - "Antonio Codazzi , 2006, 2007.\n" - "Antônio Cláudio (LedStyle) , 2006.\n" - "Amanpreet Singh Brar Alamwalia , 2005.\n" - "Arman Aksoy , 2003.\n" - "Arpad Biro , 2004, 2005.\n" - "Benedikt Roth , 2000.\n" - "Benno Schulenberg , 2008.\n" - "Boštjan Špetič , 2004, 2005.\n" - "Brisa Francesco , 2000.\n" - "bulia byak , 2004.\n" - "Chris jia , 2006.\n" - "Christian Meyer , 2000-2002.\n" - "Christian Neumair , 2002, 2003.\n" - "Christian Rose , 2000, 2001, 2002, 2003.\n" - "Cristian Secară , 2010.\n" - "Christophe Merlet (RedFox) , 2000-2002.\n" - "Clytie Siddall , 2004-2008.\n" - "Colin Marquardt , 2004-2006.\n" - "Cédric Gemy , 2006.\n" - "Daniel Díaz , 2004.\n" - "Didier Conchaudron , 2003.\n" - "Dorji Tashi , 2006.\n" - "Duarte Loreto 2002, 2003 (Maintainer).\n" - "Equipe de Tradução Inkscape Brasil , 2007.\n" - "Fatih Demir , 2000.\n" - "Foppe Benedictus , 2007-2009.\n" - "Francesc Dorca , 2003. Traducció sodipodi.\n" - "Francisco Javier F. Serrador , 2003.\n" - "Francisco Xosé Vázquez Grandal , 2001.\n" - "Frederic Rodrigo , 2004-2005.\n" - "Ge'ez Frontier Foundation , 2002.\n" - "Hleb Valoshka <375gnu@gmail.com>, 2008-2009.\n" - "Hizkuntza Politikarako Sailburuordetza , 2005.\n" - "Ilia Penev , 2006.\n" - "Ivan Masár , 2006, 2007, 2008, 2009, 2010. \n" - "Iñaki Larrañaga , 2006.\n" - "Jeffrey Steve Borbón Sanabria , 2005.\n" - "Joaquim Perez i Noguer , 2008-2009.\n" - "Jörg Müller , 2005.\n" - "Jeroen van der Vegt , 2003, 2005, 2008.\n" - "Jin-Hwan Jeong , 2009.\n" - "Jonathan Ernst , 2006.\n" - "Jose Antonio Salgueiro Aquino , 2003.\n" - "Josef Vybiral , 2005-2006.\n" - "Juarez Rudsatz , 2004.\n" - "Junichi Uekawa , 2002.\n" - "Jurmey Rabgay , 2006.\n" - "Kai Lahmann , 2000.\n" - "Karl Ove Hufthammer , 2004, 2005.\n" - "KATSURAGAWA Naoki , 2006.\n" - "Keld Simonsen , 2000, 2001.\n" - "Kenji Inoue , 2006-2007.\n" - "Khandakar Mujahidul Islam , 2006.\n" - "Kitae , 2006.\n" - "Kjartan Maraas , 2000-2002.\n" - "Kris De Gussem , 2008-2010.\n" - "Lauris Kaplinski , 2000.\n" - "Leandro Regueiro , 2006-2008,2010.\n" - "Liu Xiaoqin , 2008.\n" - "Luca Bruno , 2005.\n" - "Lucas Vieites Fariña, 2003-2010.\n" - "Mahesh subedi , 2006.\n" - "Martin Srebotnjak, , 2005, 2010.\n" - "Masatake YAMATO , 2002.\n" - "Masato Hashimoto , 2009-2010.\n" - "Matiphas , 2004-2006.\n" - "Mattias Hultgren , 2005.\n" - "Maxim Dziumanenko , 2004.\n" - "Mətin Əmirov , 2003.\n" - "Mitsuru Oka , 2002.\n" - "Morphix User , 2006.\n" - "Mufit Eribol , 2000.\n" - "Muhammad Bashir Al-Noimi , 2008.\n" - "Myckel Habets , 2008.\n" - "Nguyen Dinh Trung , 2007, 2008.\n" - "Nicolas Dufour , 2008-2010.\n" - "Pawan Chitrakar , 2006.\n" - "Przemysław Loesch , 2005.\n" - "Quico Llach , 2000. Traducció sodipodi.\n" - "Raymond Ostertag , 2002, 2003.\n" - "Riku Leino , 2006.\n" - "Rune Rønde Laursen , 2006.\n" - "Ruud Steltenpool , 2006.\n" - "Serdar Soytetir , 2005.\n" - "shivaken , 2004.\n" - "Shyam Krishna Bal , 2006.\n" - "Simos Xenitellis , 2001.\n" - "Spyros Blanas , 2006.\n" - "Stefan Graubner , 2005.\n" - "Supranee Thirawatthanasuk , 2006.\n" - "Takeshi Aihana , 2000, 2001.\n" - "Tim Sheridan , 2007-2010.\n" - "Theppitak Karoonboonyanan , 2006.\n" - "Thiago Pimentel , 2006.\n" - "Toshifumi Sato , 2005.\n" - "Jon South , 2006. \n" - "Uwe Schöler , 2006.\n" - "Valek Filippov , 2000, 2003.\n" - "Victor Dachev , 2006.\n" - "Vincent van Adrighem , 2003.\n" - "Vital Khilko , 2003.\n" - "Vitaly Lipatov , 2002, 2004.\n" - "vonHalenbach , 2005.\n" - "Wang Li , 2002.\n" - "Wei-Lun Chao , 2006.\n" - "Wolfram Strempfer , 2006.\n" - "Xavier Conde Rueda , 2004-2008.\n" - "Yaron Shahrabani , 2009.\n" - "Yukihiro Nakai , 2000, 2003.\n" - "Yuri Beznos , 2006.\n" - "Yuri Chornoivan , 2007-2010.\n" - "Yuri Syrota , 2000.\n" - "Yves Guillou , 2004.\n" - "Zdenko Podobný , 2003, 2004." +"3ARRANO.com <3arrano@3arrano.com>, 2005.\n" +"Adib Taraben , 2004.\n" +"Alan Monfort , 2009-2010.\n" +"Alastair McKinstry , 2000.\n" +"Aleksandar Urošević , 2004-2006.\n" +"Alessio Frusciante , 2002, 2003.\n" +"Alexander Shopov , 2006.\n" +"Alexandre Prokoudine , 2005.\n" +"Alexey Remizov , 2004.\n" +"Ali Ghanavatian , 2010.\n" +"Álvaro Lopes , 2001, 2002.\n" +"Andreas Hyden , 2000.\n" +"Andrius Ramanauskas , 2006.\n" +"Antonio Codazzi , 2006, 2007.\n" +"Antônio Cláudio (LedStyle) , 2006.\n" +"Amanpreet Singh Brar Alamwalia , 2005.\n" +"Arman Aksoy , 2003.\n" +"Arpad Biro , 2004, 2005.\n" +"Benedikt Roth , 2000.\n" +"Benno Schulenberg , 2008.\n" +"Boštjan Špetič , 2004, 2005.\n" +"Brisa Francesco , 2000.\n" +"bulia byak , 2004.\n" +"Chris jia , 2006.\n" +"Christian Meyer , 2000-2002.\n" +"Christian Neumair , 2002, 2003.\n" +"Christian Rose , 2000-2003.\n" +"Cristian Secară , 2010.\n" +"Christophe Merlet (RedFox) , 2000-2002.\n" +"Clytie Siddall , 2004-2008.\n" +"Colin Marquardt , 2004-2006.\n" +"Cédric Gemy , 2006.\n" +"Daniel Díaz , 2004.\n" +"Didier Conchaudron , 2003.\n" +"Dorji Tashi , 2006.\n" +"Duarte Loreto 2002, 2003 (Maintainer).\n" +"Elias Norberg , 2009.\n" +"Equipe de Tradução Inkscape Brasil , 2007.\n" +"Fatih Demir , 2000.\n" +"Foppe Benedictus , 2007-2009.\n" +"Francesc Dorca , 2003. Traducció sodipodi.\n" +"Francisco Javier F. Serrador , 2003.\n" +"Francisco Xosé Vázquez Grandal , 2001.\n" +"Frederic Rodrigo , 2004-2005.\n" +"Ge'ez Frontier Foundation , 2002.\n" +"Hleb Valoshka <375gnu@gmail.com>, 2008-2009.\n" +"Hizkuntza Politikarako Sailburuordetza , 2005.\n" +"Ilia Penev , 2006.\n" +"Ivan Masár , 2006, 2007, 2008, 2009, 2010. \n" +"Iñaki Larrañaga , 2006.\n" +"Jeffrey Steve Borbón Sanabria , 2005.\n" +"Jesper Öqvist , 2010, 2011.\n" +"Joaquim Perez i Noguer , 2008-2009.\n" +"Jörg Müller , 2005.\n" +"Jeroen van der Vegt , 2003, 2005, 2008.\n" +"Jin-Hwan Jeong , 2009.\n" +"Jonathan Ernst , 2006.\n" +"Jose Antonio Salgueiro Aquino , 2003.\n" +"Josef Vybiral , 2005-2006.\n" +"Juarez Rudsatz , 2004.\n" +"Junichi Uekawa , 2002.\n" +"Jurmey Rabgay , 2006.\n" +"Kai Lahmann , 2000.\n" +"Karl Ove Hufthammer , 2004, 2005.\n" +"KATSURAGAWA Naoki , 2006.\n" +"Keld Simonsen , 2000, 2001.\n" +"Kenji Inoue , 2006-2007.\n" +"Khandakar Mujahidul Islam , 2006.\n" +"Kitae , 2006.\n" +"Kjartan Maraas , 2000-2002.\n" +"Kris De Gussem , 2008-2010.\n" +"Lauris Kaplinski , 2000.\n" +"Leandro Regueiro , 2006-2008, 2010.\n" +"Liu Xiaoqin , 2008.\n" +"Luca Bruno , 2005.\n" +"Lucas Vieites Fariña, 2003-2010.\n" +"Mahesh subedi , 2006.\n" +"Martin Srebotnjak, , 2005, 2010.\n" +"Masatake YAMATO , 2002.\n" +"Masato Hashimoto , 2009-2011.\n" +"Matiphas , 2004-2006.\n" +"Mattias Hultgren , 2005, 2006.\n" +"Maxim Dziumanenko , 2004.\n" +"Mətin Əmirov , 2003.\n" +"Mitsuru Oka , 2002.\n" +"Morphix User , 2006.\n" +"Mufit Eribol , 2000.\n" +"Muhammad Bashir Al-Noimi , 2008.\n" +"Myckel Habets , 2008.\n" +"Nguyen Dinh Trung , 2007, 2008.\n" +"Nicolas Dufour , 2008-2011.\n" +"Pawan Chitrakar , 2006.\n" +"Przemysław Loesch , 2005.\n" +"Quico Llach , 2000. Traducció sodipodi.\n" +"Raymond Ostertag , 2002, 2003.\n" +"Riku Leino , 2006.\n" +"Rune Rønde Laursen , 2006.\n" +"Ruud Steltenpool , 2006.\n" +"Serdar Soytetir , 2005.\n" +"shivaken , 2004.\n" +"Shyam Krishna Bal , 2006.\n" +"Simos Xenitellis , 2001.\n" +"Spyros Blanas , 2006.\n" +"Stefan Graubner , 2005.\n" +"Supranee Thirawatthanasuk , 2006.\n" +"Takeshi Aihana , 2000, 2001.\n" +"Tim Sheridan , 2007-2010.\n" +"Theppitak Karoonboonyanan , 2006.\n" +"Thiago Pimentel , 2006.\n" +"Toshifumi Sato , 2005.\n" +"Jon South , 2006. \n" +"Uwe Schöler , 2006.\n" +"Valek Filippov , 2000, 2003.\n" +"Victor Dachev , 2006.\n" +"Vincent van Adrighem , 2003.\n" +"Vital Khilko , 2003.\n" +"Vitaly Lipatov , 2002, 2004.\n" +"vonHalenbach , 2005.\n" +"Wang Li , 2002.\n" +"Wei-Lun Chao , 2006.\n" +"Wolfram Strempfer , 2006.\n" +"Xavier Conde Rueda , 2004-2008.\n" +"Yaron Shahrabani , 2009.\n" +"Yukihiro Nakai , 2000, 2003.\n" +"Yuri Beznos , 2006.\n" +"Yuri Chornoivan , 2007-2010.\n" +"Yuri Syrota , 2000.\n" +"Yves Guillou , 2004.\n" +"Zdenko Podobný , 2003, 2004." ; translators_text.append(allTranslators); -- cgit v1.2.3 From 53933f5fea9d07d1ba6304b88439fba257ee8c34 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Wed, 2 Feb 2011 22:24:36 +0100 Subject: update to latest 2geom ! (bzr r10025) --- src/2geom/Makefile_insert | 2 +- src/2geom/angle.h | 208 ++- src/2geom/basic-intersection.cpp | 2 +- src/2geom/bezier-curve.h | 390 ++--- src/2geom/bezier-utils.cpp | 20 +- src/2geom/bezier.h | 11 +- src/2geom/chebyshev.cpp | 2 +- src/2geom/choose.h | 56 +- src/2geom/circle.cpp | 3 +- src/2geom/circle.h | 8 +- src/2geom/convex-cover.cpp | 137 +- src/2geom/convex-cover.h | 3 +- src/2geom/coord.h | 11 +- src/2geom/curve.h | 328 ++-- src/2geom/curves.h | 13 +- src/2geom/d2-sbasis.cpp | 53 +- src/2geom/d2-sbasis.h | 9 +- src/2geom/d2.h | 4 +- src/2geom/ellipse.cpp | 26 +- src/2geom/ellipse.h | 13 +- src/2geom/elliptical-arc.cpp | 1601 ++++++++++---------- src/2geom/elliptical-arc.h | 420 +++-- src/2geom/exception.h | 26 +- src/2geom/forward.h | 59 +- src/2geom/hvlinesegment.h | 536 ++----- src/2geom/interval.h | 414 +++-- src/2geom/line.cpp | 164 +- src/2geom/line.h | 471 +++--- src/2geom/matrix.cpp | 258 ---- src/2geom/matrix.h | 165 -- src/2geom/numeric/fitting-model.h | 50 +- src/2geom/numeric/matrix.cpp | 43 +- src/2geom/numeric/matrix.h | 42 +- src/2geom/numeric/vector.h | 18 + src/2geom/path-intersection.cpp | 130 +- src/2geom/path.cpp | 18 +- src/2geom/path.h | 4 +- src/2geom/pathvector.cpp | 2 +- src/2geom/pathvector.h | 7 +- src/2geom/piecewise.cpp | 74 + src/2geom/piecewise.h | 135 +- src/2geom/point.cpp | 149 +- src/2geom/point.h | 410 +++-- src/2geom/poly.cpp | 1 - src/2geom/poly.h | 3 + src/2geom/ray.h | 32 +- src/2geom/rect.h | 252 ++- src/2geom/recursive-bezier-intersection.cpp | 26 +- src/2geom/region.cpp | 4 +- src/2geom/region.h | 2 +- src/2geom/sbasis-curve.h | 127 +- src/2geom/sbasis-geometric.cpp | 41 +- src/2geom/sbasis-roots.cpp | 232 ++- src/2geom/sbasis.h | 84 +- src/2geom/shape.cpp | 2 +- src/2geom/shape.h | 2 +- src/2geom/solve-bezier-one-d.cpp | 267 ++-- src/2geom/solver.h | 15 +- src/2geom/svg-elliptical-arc.cpp | 938 +----------- src/2geom/svg-elliptical-arc.h | 383 +---- src/2geom/svg-path-parser.cpp | 47 +- src/2geom/svg-path.cpp | 4 +- src/2geom/sweep.h | 3 + src/2geom/transforms.cpp | 199 ++- src/2geom/transforms.h | 260 +++- src/2geom/utils.h | 41 +- src/arc-context.cpp | 2 +- src/box3d.cpp | 12 +- src/conn-avoid-ref.cpp | 18 +- src/conn-avoid-ref.h | 2 +- src/connector-context.cpp | 10 +- src/desktop-style.cpp | 10 +- src/desktop.cpp | 8 +- src/desktop.h | 14 +- src/dialogs/clonetiler.cpp | 186 +-- src/display/canvas-arena.cpp | 4 +- src/display/canvas-axonomgrid.cpp | 2 +- src/display/canvas-axonomgrid.h | 2 +- src/display/canvas-bpath.cpp | 4 +- src/display/canvas-bpath.h | 2 +- src/display/canvas-grid.cpp | 6 +- src/display/canvas-grid.h | 4 +- src/display/canvas-text.cpp | 4 +- src/display/canvas-text.h | 2 +- src/display/curve.cpp | 2 +- src/display/curve.h | 2 +- src/display/gnome-canvas-acetate.cpp | 4 +- src/display/guideline.cpp | 8 +- src/display/inkscape-cairo.cpp | 12 +- src/display/inkscape-cairo.h | 2 +- src/display/nr-3dutils.cpp | 2 +- src/display/nr-3dutils.h | 2 +- src/display/nr-arena-glyphs.cpp | 12 +- src/display/nr-arena-glyphs.h | 8 +- src/display/nr-arena-group.cpp | 6 +- src/display/nr-arena-group.h | 6 +- src/display/nr-arena-image.cpp | 4 +- src/display/nr-arena-image.h | 2 +- src/display/nr-arena-item.cpp | 12 +- src/display/nr-arena-item.h | 12 +- src/display/nr-arena-shape.cpp | 14 +- src/display/nr-arena-shape.h | 6 +- src/display/nr-filter-colormatrix.cpp | 2 +- src/display/nr-filter-colormatrix.h | 2 +- src/display/nr-filter-component-transfer.cpp | 2 +- src/display/nr-filter-component-transfer.h | 2 +- src/display/nr-filter-convolve-matrix.cpp | 2 +- src/display/nr-filter-convolve-matrix.h | 2 +- src/display/nr-filter-diffuselighting.cpp | 4 +- src/display/nr-filter-diffuselighting.h | 2 +- src/display/nr-filter-displacement-map.cpp | 4 +- src/display/nr-filter-displacement-map.h | 2 +- src/display/nr-filter-flood.cpp | 2 +- src/display/nr-filter-flood.h | 2 +- src/display/nr-filter-gaussian.cpp | 6 +- src/display/nr-filter-gaussian.h | 2 +- src/display/nr-filter-image.cpp | 8 +- src/display/nr-filter-morphology.cpp | 4 +- src/display/nr-filter-morphology.h | 2 +- src/display/nr-filter-offset.cpp | 4 +- src/display/nr-filter-offset.h | 2 +- src/display/nr-filter-primitive.cpp | 2 +- src/display/nr-filter-primitive.h | 2 +- src/display/nr-filter-slot.cpp | 4 +- src/display/nr-filter-specularlighting.cpp | 4 +- src/display/nr-filter-specularlighting.h | 2 +- src/display/nr-filter-tile.cpp | 2 +- src/display/nr-filter-tile.h | 2 +- src/display/nr-filter-turbulence.cpp | 2 +- src/display/nr-filter-units.cpp | 36 +- src/display/nr-filter-units.h | 24 +- src/display/nr-filter.cpp | 6 +- src/display/nr-filter.h | 2 +- src/display/nr-light.cpp | 4 +- src/display/nr-light.h | 4 +- src/display/nr-svgfonts.cpp | 2 +- src/display/pixblock-scaler.cpp | 6 +- src/display/pixblock-scaler.h | 2 +- src/display/pixblock-transform.cpp | 10 +- src/display/pixblock-transform.h | 4 +- src/display/sodipodi-ctrl.cpp | 6 +- src/display/sodipodi-ctrlrect.cpp | 6 +- src/display/sodipodi-ctrlrect.h | 2 +- src/display/sp-canvas-item.h | 8 +- src/display/sp-canvas-util.cpp | 8 +- src/display/sp-canvas-util.h | 6 +- src/display/sp-canvas.cpp | 18 +- src/display/sp-canvas.h | 2 +- src/display/sp-ctrlline.cpp | 4 +- src/display/sp-ctrlline.h | 2 +- src/display/sp-ctrlpoint.cpp | 4 +- src/display/sp-ctrlpoint.h | 2 +- src/display/sp-ctrlquadr.cpp | 6 +- src/draw-context.cpp | 2 +- src/dropper-context.cpp | 4 +- src/dyna-draw-context.cpp | 10 +- src/extension/implementation/implementation.cpp | 8 +- src/extension/implementation/implementation.h | 8 +- src/extension/internal/cairo-render-context.cpp | 28 +- src/extension/internal/cairo-render-context.h | 20 +- src/extension/internal/cairo-renderer-pdf-out.cpp | 2 +- src/extension/internal/cairo-renderer.cpp | 46 +- src/extension/internal/emf-win32-print.cpp | 22 +- src/extension/internal/emf-win32-print.h | 16 +- src/extension/internal/javafx-out.cpp | 4 +- src/extension/internal/latex-pstricks.cpp | 18 +- src/extension/internal/latex-pstricks.h | 10 +- src/extension/internal/latex-text-renderer.cpp | 16 +- src/extension/internal/latex-text-renderer.h | 8 +- src/extension/internal/odf.cpp | 38 +- src/extension/internal/odf.h | 2 +- src/extension/internal/pdfinput/svg-builder.cpp | 16 +- src/extension/internal/pdfinput/svg-builder.h | 4 +- src/extension/internal/pov-out.cpp | 2 +- src/extension/internal/win32.cpp | 2 +- src/extension/internal/win32.h | 4 +- src/extension/print.cpp | 8 +- src/extension/print.h | 8 +- src/file.cpp | 2 +- src/filter-chemistry.cpp | 4 +- src/flood-context.cpp | 10 +- src/gradient-chemistry.cpp | 44 +- src/gradient-chemistry.h | 2 +- src/helper/geom.cpp | 32 +- src/helper/geom.h | 14 +- src/helper/pixbuf-ops.cpp | 2 +- src/helper/png-write.cpp | 2 +- src/knot-holder-entity.cpp | 22 +- src/knotholder.cpp | 2 +- src/libnr/nr-convert2geom.h | 8 +- src/libnr/nr-matrix.h | 8 +- src/libnrtype/FontInstance.cpp | 2 +- src/libnrtype/Layout-TNG-OutIter.cpp | 4 +- src/libnrtype/Layout-TNG-Output.cpp | 28 +- src/libnrtype/Layout-TNG-Scanline-Makers.cpp | 6 +- src/libnrtype/Layout-TNG.h | 12 +- src/libnrtype/font-instance.h | 2 +- src/libnrtype/font-style.h | 4 +- src/livarot/Path.cpp | 2 +- src/livarot/Path.h | 6 +- src/livarot/PathCutting.cpp | 14 +- src/livarot/PathSimplify.cpp | 4 +- src/livarot/Shape.h | 6 +- src/livarot/ShapeMisc.cpp | 6 +- src/livarot/ShapeSweep.cpp | 2 +- src/livarot/path-description.cpp | 14 +- src/livarot/path-description.h | 14 +- src/live_effects/effect.cpp | 4 +- src/live_effects/effect.h | 2 +- src/live_effects/lpe-copy_rotate.cpp | 4 +- src/live_effects/lpe-curvestitch.cpp | 8 +- src/live_effects/lpe-curvestitch.h | 2 +- src/live_effects/lpe-dynastroke.cpp | 10 +- src/live_effects/lpe-knot.cpp | 4 +- src/live_effects/lpe-mirror_symmetry.cpp | 12 +- src/live_effects/lpe-patternalongpath.cpp | 2 +- src/live_effects/lpe-patternalongpath.h | 2 +- src/live_effects/lpe-rough-hatches.cpp | 8 +- src/live_effects/lpe-sketch.cpp | 2 +- src/live_effects/lpe-spiro.cpp | 2 +- src/live_effects/lpe-vonkoch.cpp | 28 +- src/live_effects/lpegroupbbox.cpp | 2 +- src/live_effects/parameter/parameter.h | 2 +- src/live_effects/parameter/path.cpp | 2 +- src/live_effects/parameter/path.h | 2 +- src/live_effects/parameter/point.cpp | 4 +- src/live_effects/parameter/point.h | 2 +- .../parameter/powerstrokepointarray.cpp | 4 +- src/live_effects/parameter/powerstrokepointarray.h | 2 +- src/live_effects/parameter/vector.cpp | 4 +- src/live_effects/parameter/vector.h | 2 +- src/lpe-tool-context.cpp | 2 +- src/marker.cpp | 18 +- src/marker.h | 8 +- src/object-edit.cpp | 4 +- src/object-snapper.cpp | 6 +- src/object-snapper.h | 2 +- src/persp3d.cpp | 2 +- src/persp3d.h | 2 +- src/print.cpp | 12 +- src/print.h | 10 +- src/selection-chemistry.cpp | 66 +- src/selection-chemistry.h | 2 +- src/selection.cpp | 2 +- src/seltrans.cpp | 24 +- src/seltrans.h | 12 +- src/snap-candidate.h | 4 +- src/snapped-curve.cpp | 4 +- src/snapped-curve.h | 4 +- src/sp-clippath.cpp | 14 +- src/sp-clippath.h | 4 +- src/sp-conn-end-pair.cpp | 6 +- src/sp-conn-end.cpp | 10 +- src/sp-ellipse.cpp | 4 +- src/sp-flowregion.cpp | 2 +- src/sp-flowtext.cpp | 6 +- src/sp-gradient-fns.h | 8 +- src/sp-gradient-test.h | 30 +- src/sp-gradient.cpp | 60 +- src/sp-gradient.h | 2 +- src/sp-image.cpp | 16 +- src/sp-item-group.cpp | 12 +- src/sp-item-group.h | 2 +- src/sp-item-transform.cpp | 26 +- src/sp-item-transform.h | 4 +- src/sp-item.cpp | 68 +- src/sp-item.h | 52 +- src/sp-line.cpp | 4 +- src/sp-line.h | 2 +- src/sp-mask.cpp | 8 +- src/sp-mask.h | 2 +- src/sp-offset.cpp | 10 +- src/sp-paint-server.cpp | 4 +- src/sp-paint-server.h | 4 +- src/sp-path.cpp | 8 +- src/sp-pattern.cpp | 36 +- src/sp-pattern.h | 8 +- src/sp-rect.cpp | 16 +- src/sp-rect.h | 2 +- src/sp-root.cpp | 2 +- src/sp-root.h | 2 +- src/sp-shape.cpp | 50 +- src/sp-shape.h | 8 +- src/sp-spiral.cpp | 2 +- src/sp-star.cpp | 4 +- src/sp-symbol.cpp | 12 +- src/sp-symbol.h | 4 +- src/sp-text.cpp | 20 +- src/sp-text.h | 2 +- src/sp-tref.cpp | 4 +- src/sp-tspan.cpp | 4 +- src/sp-use-reference.cpp | 12 +- src/sp-use.cpp | 36 +- src/sp-use.h | 4 +- src/splivarot.cpp | 48 +- src/splivarot.h | 2 +- src/spray-context.cpp | 8 +- src/svg/svg-affine-test.h | 80 +- src/svg/svg-affine.cpp | 16 +- src/svg/svg-path.cpp | 6 +- src/svg/svg.h | 6 +- src/text-editing.cpp | 12 +- src/text-editing.h | 2 +- src/text-tag-attributes.h | 2 +- src/trace/trace.cpp | 2 +- src/transf_mat_3x4.cpp | 6 +- src/transf_mat_3x4.h | 4 +- src/tweak-context.cpp | 12 +- src/ui/cache/svg_preview_cache.cpp | 2 +- src/ui/clipboard.cpp | 2 +- src/ui/dialog/filedialogimpl-win32.cpp | 2 +- src/ui/dialog/svg-fonts-dialog.cpp | 4 +- src/ui/dialog/tile.cpp | 2 +- src/ui/dialog/transformation.cpp | 12 +- src/ui/tool/control-point-selection.cpp | 14 +- src/ui/tool/control-point-selection.h | 6 +- src/ui/tool/control-point.cpp | 2 +- src/ui/tool/control-point.h | 2 +- src/ui/tool/node.cpp | 34 +- src/ui/tool/node.h | 2 +- src/ui/tool/path-manipulator.cpp | 12 +- src/ui/tool/path-manipulator.h | 12 +- src/ui/tool/shape-record.h | 4 +- src/ui/tool/transform-handle-set.cpp | 28 +- src/ui/tool/transform-handle-set.h | 4 +- src/ui/widget/registered-widget.cpp | 2 +- src/ui/widget/registered-widget.h | 6 +- src/unclump.cpp | 4 +- src/widgets/font-selector.cpp | 2 +- src/widgets/icon.cpp | 6 +- src/widgets/select-toolbar.cpp | 2 +- src/widgets/stroke-style.cpp | 2 +- src/widgets/toolbox.cpp | 2 +- 333 files changed, 5950 insertions(+), 6024 deletions(-) delete mode 100644 src/2geom/matrix.cpp delete mode 100644 src/2geom/matrix.h (limited to 'src') diff --git a/src/2geom/Makefile_insert b/src/2geom/Makefile_insert index 7ded3a637..ead0e3517 100644 --- a/src/2geom/Makefile_insert +++ b/src/2geom/Makefile_insert @@ -22,7 +22,7 @@ 2geom/elliptical-arc.cpp \ 2geom/geom.cpp \ 2geom/line.cpp \ - 2geom/matrix.cpp \ + 2geom/affine.cpp \ 2geom/nearest-point.cpp \ 2geom/path-intersection.cpp \ 2geom/path.cpp \ diff --git a/src/2geom/angle.h b/src/2geom/angle.h index c950dd803..42e3531f3 100644 --- a/src/2geom/angle.h +++ b/src/2geom/angle.h @@ -1,11 +1,13 @@ /** - * \file angle.h + * \file * \brief Various trigoniometric helper functions - * + *//* * Authors: * Johan Engelen + * Marco Cecchetti + * Krzysztof Kosiński * - * Copyright (C) 2007 authors + * Copyright (C) 2007-2010 Authors * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -35,12 +37,177 @@ #ifndef LIB2GEOM_SEEN_ANGLE_H #define LIB2GEOM_SEEN_ANGLE_H +#include +#include +#include <2geom/exception.h> +#include <2geom/coord.h> +#include <2geom/point.h> + namespace Geom { #ifndef M_PI # define M_PI 3.14159265358979323846 #endif +/** @brief Wrapper for angular values. + * + * This class is a convenience wrapper that implements the behavior generally expected of angles, + * like addition modulo \f$2\pi\f$. The value returned from the default conversion + * to double is in the range \f$[-\pi, \pi)\f$ - the convention used by C's + * math library. + * + * @ingroup Primitives + */ +class Angle + : boost::additive< Angle + , boost::equality_comparable< Angle + > > +{ +public: + Angle(Coord v) : _angle(v) { _normalize(); } // this can be called implicitly + explicit Angle(Point p) : _angle(atan2(p)) { _normalize(); } + Angle(Point a, Point b) : _angle(angle_between(a, b)) { _normalize(); } + operator Coord() const { return radians(); } + Angle &operator+=(Angle const &o) { + _angle += o._angle; + _normalize(); + return *this; + } + Angle &operator-=(Angle const &o) { + _angle -= o._angle; + _normalize(); + return *this; + } + bool operator==(Angle const &o) const { + return _angle == o._angle; + } + + /** @brief Get the angle as radians. + * @return Number in range \f$[-\pi, \pi)\f$. */ + Coord radians() const { + return _angle > M_PI ? _angle - 2*M_PI : _angle; + } + /** @brief Get the angle as positive radians. + * @return Number in range \f$[0, 2\pi)\f$. */ + Coord radians0() const { + return _angle; + } + /** @brief Get the angle as degrees in math convention. + * @return Number in range [-180, 180) obtained by scaling the result of radians() + * by \f$180/\pi\f$. */ + Coord degrees() const { return radians() / M_PI * 180.0; } + /** @brief Get the angle as degrees in clock convention. + * This method converts the angle to the "clock convention": angles start from the +Y axis + * and grow clockwise. This means that 0 corresponds to \f$\pi/2\f$ radians, + * 90 to 0 radians, 180 to \f$-\pi/2\f$ radians, and 270 to \f$\pi\f$ radians. + * @return A number in the range [0, 360). + */ + Coord degreesClock() const { + Coord ret = 90.0 - _angle / M_PI * 180.0; + if (ret < 0) ret += 360; + return ret; + } + + static Angle from_degrees(Coord d) { + Angle a(d * M_PI / 180); + return a; + } + static Angle from_degrees_clock(Coord d) { + // first make sure d is in [0, 360) + d = std::fmod(d, 360.0); + if (d < 0) d += 360.0; + Coord rad = M_PI/2 - d * M_PI / 180.0; + if (rad < 0) rad += 2*M_PI; + Angle a; + a._angle = rad; + return a; + } +private: + Angle() {} + void _normalize() { + _angle -= floor(_angle / (2*M_PI)) * 2*M_PI; + } + Coord _angle; // this is always in [0, 2pi) + friend class AngleInterval; +}; + +/** @brief Directed angular interval. + * + * Wrapper for directed angles with defined start and end values. Useful e.g. for representing + * the portion of an ellipse in an elliptical arc. Both extreme angles are contained + * in the interval (it is a closed interval). Angular intervals can also be interptered + * as functions \f$f: [0, 1] \to [-\pi, \pi)\f$, which return the start angle for 0, + * the end angle for 1, and interpolate linearly for other values. Note that such functions + * are not continuous if the interval contains the zero angle. + * + * This class is immutable - you cannot change the values of start and end angles + * without creating a new instance of this class. + * + * @ingroup Primitives + */ +class AngleInterval { +public: + AngleInterval(Angle const &s, Angle const &e, bool cw = false) + : _start_angle(s), _end_angle(e), _sweep(cw) + {} + AngleInterval(double s, double e, bool cw = false) + : _start_angle(s), _end_angle(e), _sweep(cw) + {} + /** @brief Get the angular coordinate of the interval's initial point + * @return Angle in range \f$[0,2\pi)\f$ corresponding to the start of arc */ + Angle const &initialAngle() const { return _start_angle; } + /** @brief Get the angular coordinate of the interval's final point + * @return Angle in range \f$[0,2\pi)\f$ corresponding to the end of arc */ + Angle const &finalAngle() const { return _end_angle; } + bool isDegenerate() const { return initialAngle() == finalAngle(); } + /** @brief Get an angle corresponding to the specified time value. */ + Angle angleAt(Coord t) const { + Coord span = extent(); + Angle ret = _start_angle.radians0() + span * (_sweep ? t : -t); + return ret; + } + Angle operator()(Coord t) const { return angleAt(t); } +#if 0 + /** @brief Find an angle nearest to the specified time value. + * @param a Query angle + * @return If the interval contains the query angle, a number from the range [0, 1] + * such that a = angleAt(t); otherwise, 0 or 1, depending on which extreme + * angle is nearer. */ + Coord nearestAngle(Angle const &a) const { + Coord dist = distance(_start_angle, a, _sweep).radians0(); + Coord span = distance(_start_angle, _end_angle, _sweep).radians0(); + if (dist <= span) return dist / span; + else return distance_abs(_start_angle, a).radians0() > distance_abs(_end_angle, a).radians0() ? 1.0 : 0.0; + } +#endif + /** @brief Check whether the interval includes the given angle. */ + bool contains(Angle const &a) const { + Coord s = _start_angle.radians0(); + Coord e = _end_angle.radians0(); + Coord x = a.radians0(); + if (_sweep) { + if (s < e) return x >= s && x <= e; + return x >= s || x <= e; + } else { + if (s > e) return x <= s && x >= e; + return x <= s || x >= e; + } + } + /** @brief Extent of the angle interval. + * @return Extent in range \f$[0, 2\pi)\f$ */ + Coord extent() const { + Coord d = _end_angle - _start_angle; + if (!_sweep) d = -d; + if (d < 0) d += 2*M_PI; + return d; + } +protected: + AngleInterval() {} + Angle _start_angle; + Angle _end_angle; + 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;} @@ -89,9 +256,44 @@ Coord map_unit_interval_on_circular_arc(Coord t, double start_angle, double end_ return angle; } +/* + * Return true if the given angle is contained in the circular arc determined + * by the passed angles. + * + * a: the angle to be tested + * sa: the angle the arc start from + * ia: an angle strictly inner to the arc + * ea: the angle the arc end to + * + * prerequisite: the inner angle has to be not equal (mod 2PI) to the start + * or the end angle, except when they are equal each other, too. + * warning: when sa == ea (mod 2PI) they define a whole circle + * if ia != sa (mod 2PI), on the contrary if ia == sa == ea (mod 2PI) + * they define a single point. + */ +inline +bool arc_contains (double a, double sa, double ia, double ea) +{ + a -= sa; + a = std::fmod(a, 2*M_PI); + if (a < 0) a += 2*M_PI; + ia -= sa; + ia = std::fmod(ia, 2*M_PI); + if (ia < 0) ia += 2*M_PI; + ea -= sa; + ea = std::fmod(ea, 2*M_PI); + if (ea < 0) ea += 2*M_PI; + if (ia == 0 && ea == 0) return (a == 0); + if (ia == 0 || ia == ea) + { + THROW_RANGEERROR ("arc_contains: passed angles do not define an arc"); + } + return (ia < ea && a <= ea) || (ia > ea && (a >= ea || a == 0)); } +} // end namespace Geom + #endif diff --git a/src/2geom/basic-intersection.cpp b/src/2geom/basic-intersection.cpp index 66f174da6..3be6792b9 100644 --- a/src/2geom/basic-intersection.cpp +++ b/src/2geom/basic-intersection.cpp @@ -202,7 +202,7 @@ static void intersect_polish_root (D2 const &A, double &s, // We're using the standard transformation matricies, which is numerically rather poor. Much better to solve the equation using elimination. - Matrix jack(as[1][0], as[1][1], + Affine jack(as[1][0], as[1][1], -bs[1][0], -bs[1][1], 0, 0); Point soln = (F)*jack.inverse(); diff --git a/src/2geom/bezier-curve.h b/src/2geom/bezier-curve.h index c943512c7..1014c79f0 100644 --- a/src/2geom/bezier-curve.h +++ b/src/2geom/bezier-curve.h @@ -1,12 +1,14 @@ /** * \file - * \brief Bezier-Curve + * \brief Bezier curve * + *//* * Authors: - * MenTaLguY - * Marco Cecchetti + * MenTaLguY + * Marco Cecchetti + * Krzysztof Kosiński * - * Copyright 2007-2008 authors + * 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 @@ -32,217 +34,225 @@ * the specific language governing rights and limitations. */ - - - -#ifndef _2GEOM_BEZIER_CURVE_H_ -#define _2GEOM_BEZIER_CURVE_H_ - +#ifndef SEEN_LIB2GEOM_BEZIER_CURVE_H +#define SEEN_LIB2GEOM_BEZIER_CURVE_H #include <2geom/curve.h> #include <2geom/sbasis-curve.h> // for non-native winding method #include <2geom/bezier.h> -#include - - namespace Geom { - - -template class BezierCurve : public Curve { - -private: - D2 inner; - -public: - template - static void assert_degree(BezierCurve const *) {} - - BezierCurve() : inner(Bezier::Order(order), Bezier::Order(order)) { - } - - explicit BezierCurve(D2 const &x) : inner(x) {} - - BezierCurve(Bezier x, Bezier y) : inner(x, y) {} - - // default copy - // default assign - - BezierCurve(Point c0, Point c1) { - assert_degree<1>(this); - for(unsigned d = 0; d < 2; d++) - inner[d] = Bezier(c0[d], c1[d]); - } - - BezierCurve(Point c0, Point c1, Point c2) { - assert_degree<2>(this); - for(unsigned d = 0; d < 2; d++) - inner[d] = Bezier(c0[d], c1[d], c2[d]); - } - - BezierCurve(Point c0, Point c1, Point c2, Point c3) { - assert_degree<3>(this); - for(unsigned d = 0; d < 2; d++) - inner[d] = Bezier(c0[d], c1[d], c2[d], c3[d]); - } - - unsigned degree() const { return order; } - - Curve *duplicate() const { return new BezierCurve(*this); } - - Point initialPoint() const { return inner.at0(); } - Point finalPoint() const { return inner.at1(); } - - bool isDegenerate() const { return inner.isConstant(); } - - void setInitial(Point v) { setPoint(0, v); } - void setFinal(Point v) { setPoint(order, v); } - - void setPoint(unsigned ix, Point v) { inner[X].setPoint(ix, v[X]); inner[Y].setPoint(ix, v[Y]); } - Point const operator[](unsigned ix) const { return Point(inner[X][ix], inner[Y][ix]); } - - virtual OptRect boundsFast() const { return bounds_fast(inner); } - virtual OptRect boundsExact() const { return bounds_exact(inner); } - virtual OptRect boundsLocal(OptInterval i, unsigned deg) const { - if (!i) return OptRect(); - if(i->min() == 0 && i->max() == 1) return boundsFast(); - if(deg == 0) return bounds_local(inner, i); - // TODO: UUUUUUGGGLLY - if(deg == 1 && order > 1) return OptRect(bounds_local(Geom::derivative(inner[X]), i), - bounds_local(Geom::derivative(inner[Y]), i)); - return OptRect(); - } -//TODO: local - -//TODO: implement next 3 natively - int winding(Point p) const { - return SBasisCurve(toSBasis()).winding(p); - } - - virtual int degreesOfFreedom() const { - return 2*order; - } - - std::vector - roots(double v, Dim2 d) const { - return (inner[d] - v).roots(); - } - - double nearestPoint( Point const& p, double from = 0, double to = 1 ) const - { - return Curve::nearestPoint(p, from, to); - } - - void setPoints(std::vector ps) { - for(unsigned i = 0; i <= order; i++) { - setPoint(i, ps[i]); - } - } - std::vector points() const { return bezier_points(inner); } - - std::pair, BezierCurve > subdivide(Coord t) const { - std::pair sx = inner[X].subdivide(t), sy = inner[Y].subdivide(t); - return std::pair, BezierCurve >( - BezierCurve(sx.first, sy.first), - BezierCurve(sx.second, sy.second)); - } - - Curve *portion(double f, double t) const { - return new BezierCurve(Geom::portion(inner, f, t)); - } - - Curve *reverse() const { - return new BezierCurve(Geom::reverse(inner)); - } - - Curve *transformed(Matrix const &m) const { - BezierCurve *ret = new BezierCurve(); - std::vector ps = points(); - for(unsigned i = 0; i <= order; i++) ps[i] = ps[i] * m; - ret->setPoints(ps); - return ret; - } - - Curve *derivative() const; - - Point pointAt(double t) const { return inner.valueAt(t); } - std::vector pointAndDerivatives(Coord t, unsigned n) const { return inner.valueAndDerivatives(t, n); } - - double valueAt(double t, Dim2 d) const { return inner[d].valueAt(t); } - - D2 toSBasis() const {return inner.toSBasis(); } - protected: - BezierCurve(Point c[]) { - Coord x[order+1], y[order+1]; - for(unsigned i = 0; i <= order; i++) { - x[i] = c[i][X]; y[i] = c[i][Y]; + D2 inner; + +public: + /// @name Construct the curve + /// @{ + /** @brief Construct a Bezier curve of the specified order with all points zero. */ + explicit BezierCurve(unsigned order) + : inner(Bezier::Order(order), Bezier::Order(order)) + {} + /** @brief Construct from 2D Bezier polynomial. */ + explicit BezierCurve(D2 const &x) + : inner(x) + { + if (inner[X].order() != inner[Y].order()) + THROW_LOGICALERROR("Beziers used to construct a BezierCurve " + "are not of the same order"); + } + /** @brief Construct from two 1D Bezier polynomials of the same order. */ + BezierCurve(Bezier x, Bezier y) + : inner(x, y) + { + // throw an error if the orders do not match + if (x.order() != y.order()) + THROW_LOGICALERROR("Beziers used to construct a BezierCurve " + "are not of the same order"); + } + /** @brief Construct a linear segment from its endpoints. */ + BezierCurve(Point c0, Point c1) { + for(unsigned d = 0; d < 2; d++) + inner[d] = Bezier(c0[d], c1[d]); + } + /** @brief Construct a quadratic Bezier curve from its control points. */ + BezierCurve(Point c0, Point c1, Point c2) { + for(unsigned d = 0; d < 2; d++) + inner[d] = Bezier(c0[d], c1[d], c2[d]); + } + /** @brief Construct a cubic Bezier curve from its control points. */ + BezierCurve(Point c0, Point c1, Point c2, Point c3) { + for(unsigned d = 0; d < 2; d++) + inner[d] = Bezier(c0[d], c1[d], c2[d], c3[d]); + } + /** @brief Construct a Bezier curve from a vector of its control points. */ + BezierCurve(std::vector const &points) { + unsigned ord = points.size() - 1; + if (ord < 1) THROW_LOGICALERROR("Not enough points to construct a Bezier curve"); + for (unsigned d = 0; d < 2; ++d) { + inner[d] = Bezier(Bezier::Order(ord)); + for(unsigned i = 0; i <= ord; i++) + inner[d][i] = points[i][d]; + } + } + /// @} + + // methods new to BezierCurve go here + + /// @name Access and modify control points + /// @{ + /** @brief Get the order of the Bezier curve. + * A Bezier curve has order() + 1 control points. */ + unsigned order() const { return inner[X].order(); } + /** @brief Get the control points. + * @return Vector with order() + 1 control points. */ + std::vector points() const { return bezier_points(inner); } + /** @brief Modify a control point. + * @param ix The zero-based index of the point to modify + * @param v The new value of the point */ + void setPoint(unsigned ix, Point v) { + 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. */ + virtual void setPoints(std::vector const &ps) { + // must be virtual, because HLineSegment will need to redefine it + if (ps.size() != order() + 1) + THROW_LOGICALERROR("BezierCurve::setPoints: incorrect number of points in vector"); + for(unsigned i = 0; i <= order(); i++) { + setPoint(i, ps[i]); + } + } + /** Access control points of the curve. + * @param ix Index of the control point + * @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]); } + /// @} + + /** @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 subdivide(Coord t) const { + std::pair sx = inner[X].subdivide(t), sy = inner[Y].subdivide(t); + return std::make_pair( + BezierCurve(sx.first, sy.first), + BezierCurve(sx.second, sy.second)); + } + BezierCurve *optimize() const; + + // implementation of virtual methods goes here +#ifndef DOXYGEN_SHOULD_SKIP_THIS + virtual Curve *duplicate() const; + virtual Point initialPoint() const { return inner.at0(); } + virtual Point finalPoint() const { return inner.at1(); } + virtual bool isDegenerate() const { return inner.isConstant(); } + virtual void setInitial(Point const &v) { setPoint(0, v); } + virtual void setFinal(Point const &v) { setPoint(order(), v); } + virtual Rect boundsFast() const { return *bounds_fast(inner); } + virtual Rect boundsExact() const { return *bounds_exact(inner); } + virtual OptRect boundsLocal(OptInterval const &i, unsigned deg) const { + if (!i) return OptRect(); + if(i->min() == 0 && i->max() == 1) return boundsFast(); + if(deg == 0) return bounds_local(inner, i); + // TODO: UUUUUUGGGLLY + if(deg == 1 && order() > 1) return OptRect(bounds_local(Geom::derivative(inner[X]), i), + bounds_local(Geom::derivative(inner[Y]), i)); + return OptRect(); + } + virtual int degreesOfFreedom() const { + return 2 * (order() + 1); + } + virtual std::vector roots(Coord v, Dim2 d) const { + return (inner[d] - v).roots(); + } + Curve *portion(Coord f, Coord t) const { + return new BezierCurve(Geom::portion(inner, f, t)); } - inner = Bezier(x, y); - } + Curve *reverse() const { + return new BezierCurve(Geom::reverse(inner)); + } + virtual Curve *transformed(Affine const &m) const { + BezierCurve *ret = new BezierCurve(order()); + std::vector ps = points(); + for(unsigned i = 0; i <= order(); i++) ps[i] = ps[i] * m; + ret->setPoints(ps); + return ret; + } + virtual Curve *derivative() const; + virtual Coord length(Coord tolerance) const; + virtual Point pointAt(Coord t) const { return inner.valueAt(t); } + virtual std::vector pointAndDerivatives(Coord t, unsigned n) const { return inner.valueAndDerivatives(t, n); } + virtual Coord valueAt(Coord t, Dim2 d) const { return inner[d].valueAt(t); } + virtual D2 toSBasis() const {return inner.toSBasis(); } +#endif }; -// BezierCurve<0> is meaningless; specialize it out -template<> class BezierCurve<0> : public BezierCurve<1> { public: BezierCurve();}; - -typedef BezierCurve<1> LineSegment; -typedef BezierCurve<2> QuadraticBezier; -typedef BezierCurve<3> CubicBezier; - - -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; - double l2v = L2sq(v); - if(l2v == 0) return 0; - double t = dot( p - ip, v ) / l2v; - if ( t <= 0 ) return from; - else if ( t >= 1 ) return to; - else return from + t*(to-from); -} +class LineSegment : public BezierCurve { +public: + LineSegment() : BezierCurve(1) {} + LineSegment(Point c0, Point c1) : BezierCurve(c0, c1) {} + +#ifndef DOXYGEN_SHOULD_SKIP_THIS + virtual Curve *duplicate() const { return new LineSegment(*this); } + virtual Rect boundsFast() const { return Rect(initialPoint(), finalPoint()); } + virtual Rect boundsExact() const { return boundsFast(); } + virtual Coord nearestPoint(Point const& p, Coord from = 0, Coord to = 1) const; + virtual Curve *portion(Coord f, Coord t) const { + return new LineSegment(pointAt(f), pointAt(t)); + } + virtual Curve *reverse() const { return new LineSegment(finalPoint(), initialPoint()); } + virtual Curve *transformed(Affine const &m) const { + return new LineSegment(initialPoint() * m, finalPoint() * m); + } + virtual Curve *derivative() const { + Coord dx = inner[X][1] - inner[X][0], dy = inner[Y][1] - inner[Y][0]; + return new LineSegment(Point(dx,dy),Point(dx,dy)); + } + virtual Coord length(Coord) const { return distance(initialPoint(), finalPoint()); } +#endif +}; -inline -Point middle_point(LineSegment const& _segment) -{ - return ( _segment.initialPoint() + _segment.finalPoint() ) / 2; -} +class QuadraticBezier : public BezierCurve { +public: + QuadraticBezier(Point c0, Point c1, Point c2) : BezierCurve(c0, c1, c2) {} +#ifndef DOXYGEN_SHOULD_SKIP_THIS + virtual Coord length(Coord tolerance) const; +#endif +}; -inline -double length(LineSegment const& _segment) -{ - return distance(_segment.initialPoint(), _segment.finalPoint()); -} +/** @brief Cubic Bezier curve. + * Note that if you created a BezierCurve, you will not be able to cast it to a CubicBezier + * using a dynamic cast regardless of its order - use the optimize() method. + * @ingroup Curves */ +class CubicBezier : public BezierCurve { +public: + CubicBezier(Point c0, Point c1, Point c2, Point c3) : BezierCurve(c0, c1, c2, c3) {} +#ifndef DOXYGEN_SHOULD_SKIP_THIS + virtual Coord length(Coord tolerance) const; +#endif +}; -template -inline -Curve *BezierCurve::derivative() const { - return new BezierCurve(Geom::derivative(inner[X]), Geom::derivative(inner[Y])); +inline Point middle_point(LineSegment const& _segment) { + return ( _segment.initialPoint() + _segment.finalPoint() ) / 2; } -template <> -inline -Curve *BezierCurve<1>::derivative() const { - double dx = inner[X][1] - inner[X][0], dy = inner[Y][1] - inner[Y][0]; - return new BezierCurve<1>(Point(dx,dy),Point(dx,dy)); +inline Coord length(LineSegment const& seg) { + return distance(seg.initialPoint(), seg.finalPoint()); } +Coord bezier_length(std::vector const &points, Coord tolerance = 0.01); +Coord bezier_length(Point p0, Point p1, Point p2, Coord tolerance = 0.01); +Coord bezier_length(Point p0, Point p1, Point p2, Point p3, Coord tolerance = 0.01); } // end namespace Geom - #endif // _2GEOM_BEZIER_CURVE_H_ - - - /* Local Variables: mode:c++ diff --git a/src/2geom/bezier-utils.cpp b/src/2geom/bezier-utils.cpp index dc8025115..eb317940f 100644 --- a/src/2geom/bezier-utils.cpp +++ b/src/2geom/bezier-utils.cpp @@ -56,9 +56,7 @@ #include <2geom/isnan.h> #include -namespace Geom{ - -typedef Point BezierCurve[]; +namespace Geom { /* Forward declarations */ static void generate_bezier(Point b[], Point const d[], double const u[], unsigned len, @@ -68,16 +66,16 @@ static void estimate_lengths(Point bezier[], Point const &tHat1, Point const &tHat2); static void estimate_bi(Point b[4], unsigned ei, Point const data[], double const u[], unsigned len); -static void reparameterize(Point const d[], unsigned len, double u[], BezierCurve const bezCurve); -static double NewtonRaphsonRootFind(BezierCurve const Q, Point const &P, double u); +static void reparameterize(Point const d[], unsigned len, double u[], Point const bezCurve[]); +static double NewtonRaphsonRootFind(Point const Q[], Point const &P, double u); static Point darray_center_tangent(Point const d[], unsigned center, unsigned length); static Point darray_right_tangent(Point const d[], unsigned const len); static unsigned copy_without_nans_or_adjacent_duplicates(Point const src[], unsigned src_len, Point dest[]); static void chord_length_parameterize(Point const d[], double u[], unsigned len); static double compute_max_error_ratio(Point const d[], double const u[], unsigned len, - BezierCurve const bezCurve, double tolerance, + Point const bezCurve[], double tolerance, unsigned *splitPoint); -static double compute_hook(Point const &a, Point const &b, double const u, BezierCurve const bezCurve, +static double compute_hook(Point const &a, Point const &b, double const u, Point const bezCurve[], double const tolerance); @@ -546,7 +544,7 @@ static void reparameterize(Point const d[], unsigned const len, double u[], - BezierCurve const bezCurve) + Point const bezCurve[]) { assert( 2 <= len ); @@ -572,7 +570,7 @@ reparameterize(Point const d[], * \return Improved u */ static double -NewtonRaphsonRootFind(BezierCurve const Q, Point const &P, double const u) +NewtonRaphsonRootFind(Point const Q[], Point const &P, double const u) { assert( 0.0 <= u ); assert( u <= 1.0 ); @@ -904,7 +902,7 @@ chord_length_parameterize(Point const d[], double u[], unsigned const len) */ static double compute_max_error_ratio(Point const d[], double const u[], unsigned const len, - BezierCurve const bezCurve, double const tolerance, + Point const bezCurve[], double const tolerance, unsigned *const splitPoint) { assert( 2 <= len ); @@ -974,7 +972,7 @@ compute_max_error_ratio(Point const d[], double const u[], unsigned const len, * distance.) */ static double -compute_hook(Point const &a, Point const &b, double const u, BezierCurve const bezCurve, +compute_hook(Point const &a, Point const &b, double const u, Point const bezCurve[], double const tolerance) { Point const P = bezier_pt(3, bezCurve, u); diff --git a/src/2geom/bezier.h b/src/2geom/bezier.h index 2a06d44f5..a7d75da45 100644 --- a/src/2geom/bezier.h +++ b/src/2geom/bezier.h @@ -46,7 +46,7 @@ namespace Geom { inline Coord subdivideArr(Coord t, Coord const *v, Coord *left, Coord *right, unsigned order) { /* * Bernstein : - * Evaluate a Bernstein function at a particular parameter value + * Evaluate a Bernstein function at a particular parameter value * Fill in control points for resulting sub-curves. * */ @@ -248,7 +248,7 @@ public: // initialize temp storage variables std::valarray d_(order()+1); - for (unsigned i = 0; i < size(); i++) { + for(unsigned i = 0; i < size(); i++) { d_[i] = c_[i]; } @@ -256,10 +256,10 @@ public: if(n_derivs > order()) { nn = order()+1; // only calculate the non zero derivs } - for (unsigned di = 0; di < nn; di++) { + for(unsigned di = 0; di < nn; di++) { //val_n_der[di] = (subdivideArr(t, &d_[0], NULL, NULL, order() - di)); val_n_der[di] = bernsteinValueAt(t, &d_[0], order() - di); - for (unsigned i = 0; i < order() - di; i++) { + for(unsigned i = 0; i < order() - di; i++) { d_[i] = (order()-di)*(d_[i+1] - d_[i]); } } @@ -381,7 +381,8 @@ inline Bezier integral(const Bezier & a) { } inline OptInterval bounds_fast(Bezier const & b) { - return Interval::fromArray(&const_cast(b).c_[0], b.size()); + OptInterval ret = Interval::from_array(&const_cast(b).c_[0], b.size()); + return ret; } //TODO: better bounds exact diff --git a/src/2geom/chebyshev.cpp b/src/2geom/chebyshev.cpp index d0d6edab4..c886daf88 100644 --- a/src/2geom/chebyshev.cpp +++ b/src/2geom/chebyshev.cpp @@ -93,7 +93,7 @@ SBasis chebyshev_approximant_interpolating (double (*f)(double,void*), wr.fa = fa; wr.fb = fb; wr.in = in; - //printf("%f %f\n", fa, fb); + printf("%f %f\n", fa, fb); wr.f = f; wr.pp = p; return compose(Linear(in[0], in[1]), Linear(fa, fb)) + chebyshev_approximant(f_interp, order, in, &wr) + Linear(fa, fb); diff --git a/src/2geom/choose.h b/src/2geom/choose.h index 579c46718..3fecf1ba2 100644 --- a/src/2geom/choose.h +++ b/src/2geom/choose.h @@ -33,7 +33,7 @@ #define _CHOOSE_H #include -// XXX: Can we keep only the left terms easily? +// 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 // we could also leave off the ones @@ -54,7 +54,7 @@ T choose(unsigned n, unsigned k) { unsigned p = pascals_triangle.size() - rows_done; pascals_triangle.push_back(1); for(unsigned i = 0; i < rows_done-1; i++) { - pascals_triangle.push_back(pascals_triangle[p] + pascals_triangle.push_back(pascals_triangle[p] + pascals_triangle[p+1]); p++; } @@ -75,6 +75,58 @@ T choose(unsigned n, unsigned k) { return r; }*/ + + +template +class BinomialCoefficient +{ + public: + typedef ValueType value_type; + typedef std::vector container_type; + + BinomialCoefficient(unsigned int _n) + : n(_n), m(n >> 1) + { + coefficients.reserve(m+1); + coefficients.push_back(1); + int h = m + 1; + value_type bct = 1; + for (int i = 1; i < h; ++i) + { + bct *= (n-i+1); + bct /= i; + coefficients.push_back(bct); + } + } + + unsigned int size() const + { + return degree() +1; + } + + unsigned int degree() const + { + return n; + } + + value_type operator[] (unsigned int k) const + { + if (k > m) k = n - k; + return coefficients[k]; + } + + private: + const int n; + const unsigned int m; + container_type coefficients; +}; + + + + + + + #endif /* diff --git a/src/2geom/circle.cpp b/src/2geom/circle.cpp index 8a0704735..06eb4c2a1 100644 --- a/src/2geom/circle.cpp +++ b/src/2geom/circle.cpp @@ -89,10 +89,11 @@ void Circle::set(std::vector const& points) } -SVGEllipticalArc +EllipticalArc * Circle::arc(Point const& initial, Point const& inner, Point const& final, bool _svg_compliant) { + // TODO native implementation! Ellipse e(center(X), center(Y), ray(), ray(), 0); return e.arc(initial, inner, final, _svg_compliant); } diff --git a/src/2geom/circle.h b/src/2geom/circle.h index 987570b62..ec58e163a 100644 --- a/src/2geom/circle.h +++ b/src/2geom/circle.h @@ -39,11 +39,12 @@ #include <2geom/point.h> #include <2geom/exception.h> #include <2geom/path.h> +#include namespace Geom { -class SVGEllipticalArc; +class EllipticalArc; class Circle { @@ -87,12 +88,11 @@ class Circle // prerequisite: at least 3 points must be passed void set(std::vector const& points); - SVGEllipticalArc + EllipticalArc * arc(Point const& initial, Point const& inner, Point const& final, bool _svg_compliant = true); - void - getPath(std::vector &path_out); + void getPath(std::vector &path_out); Point center() const { diff --git a/src/2geom/convex-cover.cpp b/src/2geom/convex-cover.cpp index db8094540..21a5c3107 100644 --- a/src/2geom/convex-cover.cpp +++ b/src/2geom/convex-cover.cpp @@ -33,6 +33,7 @@ #include <2geom/exception.h> #include #include +#include /** Todo: + modify graham scan to work top to bottom, rather than around angles @@ -48,6 +49,7 @@ using std::vector; using std::map; using std::pair; +using std::make_pair; namespace Geom{ @@ -338,40 +340,74 @@ ConvexHull::is_degenerate() const { } -/* Here we really need a rotating calipers implementation. This implementation is slow and incorrect. - This incorrectness is a problem because it throws off the algorithms. Perhaps I will come up with - something better tomorrow. The incorrectness is in the order of the bridges - they must be in the - order of traversal around. Since the a->b and b->a bridges are seperated, they don't need to be merge - order, just the order of the traversal of the host hull. Currently some situations make a n->0 bridge - first.*/ -pair< map, map > -bridges(ConvexHull a, ConvexHull b) { - map abridges; - map bbridges; - - for(unsigned ia = 0; ia < a.boundary.size(); ia++) { - for(unsigned ib = 0; ib < b.boundary.size(); ib++) { - Point d = b[ib] - a[ia]; - Geom::Coord e = cross(d, a[ia - 1] - a[ia]), f = cross(d, a[ia + 1] - a[ia]); - Geom::Coord g = cross(d, b[ib - 1] - a[ia]), h = cross(d, b[ib + 1] - a[ia]); - if (e > 0 && f > 0 && g > 0 && h > 0) abridges[ia] = ib; - else if(e < 0 && f < 0 && g < 0 && h < 0) bbridges[ib] = ia; - } - } - - return make_pair(abridges, bbridges); +int sgn(double x) { + if(x == 0) return 0; + return (x<0)?-1:1; } -std::vector bridge_points(ConvexHull a, ConvexHull b) { - vector ret; - pair< map, map > indices = bridges(a, b); - for(map::iterator it = indices.first.begin(); it != indices.first.end(); it++) { - ret.push_back(a[it->first]); - ret.push_back(b[it->second]); +bool same_side(Point L[2], Point xs[4]) { + int side = 0; + for(int i = 0; i < 4; i++) { + int sn = sgn(SignedTriangleArea(L[0], L[1], xs[i])); + if(sn and not side) + side = sn; + else if(sn != side) return false; } - for(map::iterator it = indices.second.begin(); it != indices.second.end(); it++) { - ret.push_back(b[it->first]); - ret.push_back(a[it->second]); + return true; +} + +/** find bridging pairs between two convex hulls. + * this code is based on Hormoz Pirzadeh's masters thesis. There is room for optimisation: + * 1. reduce recomputation + * 2. use more efficient angle code + * 3. write as iterator + */ +std::vector > bridges(ConvexHull a, ConvexHull b) { + vector > ret; + + // 1. find maximal points on a and b + int ai = 0, bi = 0; + // 2. find first copodal pair + double ap_angle = atan2(a[ai+1] - a[ai]); + double bp_angle = atan2(b[bi+1] - b[bi]); + Point L[2] = {a[ai], b[bi]}; + while(ai < int(a.size()) or bi < int(b.size())) { + if(ap_angle == bp_angle) { + // In the case of parallel support lines, we must consider all four pairs of copodal points + { + assert(0); // untested + Point xs[4] = {a[ai-1], a[ai+1], b[bi-1], b[bi+1]}; + if(same_side(L, xs)) ret.push_back(make_pair(ai, bi)); + xs[2] = b[bi]; + xs[3] = b[bi+2]; + if(same_side(L, xs)) ret.push_back(make_pair(ai, bi)); + xs[0] = a[ai]; + xs[1] = a[ai+2]; + if(same_side(L, xs)) ret.push_back(make_pair(ai, bi)); + xs[2] = b[bi-1]; + xs[3] = b[bi+1]; + if(same_side(L, xs)) ret.push_back(make_pair(ai, bi)); + } + ai++; + ap_angle += angle_between(a[ai] - a[ai-1], a[ai+1] - a[ai]); + L[0] = a[ai]; + bi++; + bp_angle += angle_between(b[bi] - b[bi-1], b[bi+1] - b[bi]); + L[1] = b[bi]; + std::cout << "parallel\n"; + } else if(ap_angle < bp_angle) { + ai++; + ap_angle += angle_between(a[ai] - a[ai-1], a[ai+1] - a[ai]); + L[0] = a[ai]; + Point xs[4] = {a[ai-1], a[ai+1], b[bi-1], b[bi+1]}; + if(same_side(L, xs)) ret.push_back(make_pair(ai, bi)); + } else { + bi++; + bp_angle += angle_between(b[bi] - b[bi-1], b[bi+1] - b[bi]); + L[1] = b[bi]; + Point xs[4] = {a[ai-1], a[ai+1], b[bi-1], b[bi+1]}; + if(same_side(L, xs)) ret.push_back(make_pair(ai, bi)); + } } return ret; } @@ -428,16 +464,48 @@ ConvexHull intersection(ConvexHull /*a*/, ConvexHull /*b*/) { return ret; } +template +T idx_to_pair(pair p, int idx) { + return idx?p.second:p.first; +} + /*** ConvexHull merge(ConvexHull a, ConvexHull b); * find the smallest convex hull that surrounds a and b. */ ConvexHull merge(ConvexHull a, ConvexHull b) { ConvexHull ret; - pair< map, map > bpair = bridges(a, b); - map ab = bpair.first; - map bb = bpair.second; + std::cout << "---\n"; + std::vector > bpair = bridges(a, b); + + // Given our list of bridges {(pb1, qb1), ..., (pbk, qbk)} + // we start with the highest point in p0, q0, say it is p0. + // then the merged hull is p0, ..., pb1, qb1, ..., qb2, pb2, ... + // In other words, either of the two polygons vertices are added in order until the vertex coincides with a bridge point, at which point we swap. + + unsigned state = (a[0][Y] < b[0][Y])?0:1; + ret.boundary.reserve(a.size() + b.size()); + ConvexHull chs[2] = {a, b}; + unsigned idx = 0; + + for(unsigned k = 0; k < bpair.size(); k++) { + unsigned limit = idx_to_pair(bpair[k], state); + std::cout << bpair[k].first << " , " << bpair[k].second << "; " + << idx << ", " << limit << ", s: " + << state + << " \n"; + while(idx <= limit) { + ret.boundary.push_back(chs[state][idx++]); + } + state = 1-state; + idx = idx_to_pair(bpair[k], state); + } + while(idx < chs[state].size()) { + ret.boundary.push_back(chs[state][idx++]); + } + return ret; + /* ab[-1] = 0; bb[-1] = 0; @@ -460,6 +528,7 @@ ConvexHull merge(ConvexHull a, ConvexHull b) { if(bb[i] == 0 && i != -1) break; i = bb[i]; } + */ return ret; } diff --git a/src/2geom/convex-cover.h b/src/2geom/convex-cover.h index 8a5124019..d5e2dee44 100644 --- a/src/2geom/convex-cover.h +++ b/src/2geom/convex-cover.h @@ -67,6 +67,7 @@ public: bool contains_point(Point p); bool strict_contains_point(Point p); + inline size_t size() const { return boundary.size();} inline Point operator[](int i) const { int l = boundary.size(); @@ -133,7 +134,7 @@ public: // do two convex hulls intersect? bool intersectp(ConvexHull a, ConvexHull b); -std::vector bridge_points(ConvexHull a, ConvexHull b); +std::vector > bridges(ConvexHull a, ConvexHull b); // find the convex hull intersection ConvexHull intersection(ConvexHull a, ConvexHull b); diff --git a/src/2geom/coord.h b/src/2geom/coord.h index 481723413..9c42f6bfc 100644 --- a/src/2geom/coord.h +++ b/src/2geom/coord.h @@ -37,8 +37,11 @@ namespace Geom { +/** @brief Axis enum (X or Y). */ +enum Dim2 { X=0, Y=1 }; + /** - * A "real" type with sufficient precision for coordinates. + * @brief Floating point type used to store 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 @@ -51,7 +54,11 @@ const Coord EPSILON = 1e-5; //1e-18; inline Coord infinity() { return std::numeric_limits::infinity(); } //IMPL: NearConcept -inline bool are_near(Coord a, Coord b, double eps=EPSILON) { return fabs(a-b) <= eps; } +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; } + + +typedef long IntCoord; } /* namespace Geom */ diff --git a/src/2geom/curve.h b/src/2geom/curve.h index 65bf86ef6..77f6808e1 100644 --- a/src/2geom/curve.h +++ b/src/2geom/curve.h @@ -1,12 +1,14 @@ /** * \file - * \brief Abstract Curve Type + * \brief Abstract curve type * + *//* * Authors: - * MenTaLguY - * Marco Cecchetti + * MenTaLguY + * Marco Cecchetti + * Krzysztof Kosiński * - * Copyright 2007-2008 authors + * 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 @@ -33,23 +35,16 @@ */ - - #ifndef _2GEOM_CURVE_H_ #define _2GEOM_CURVE_H_ - +#include #include <2geom/coord.h> #include <2geom/point.h> #include <2geom/interval.h> -#include <2geom/nearest-point.h> #include <2geom/sbasis.h> #include <2geom/d2.h> -#include <2geom/matrix.h> -#include <2geom/exception.h> - -#include - +#include <2geom/affine.h> namespace Geom { @@ -61,99 +56,230 @@ protected: static int root_winding(Curve const &c, Point p); }; + +/** + * @brief Abstract continuous curve on a plane defined on [0,1]. + * + * Formally, a curve in 2Geom is defined as a function + * \f$\mathbf{C}: [0, 1] \to \mathbb{R}^2\f$ + * (a function that maps the unit interval to points on a 2D plane). Its image (the set of points + * the curve passes through) will be denoted \f$\mathcal{C} = \mathbf{C}[ [0, 1] ]\f$. + * All curve types available in 2Geom are continuous and differentiable on their + * interior, e.g. \f$(0, 1)\f$. Sometimes the curve's image (value set) is referred to as the curve + * itself for simplicity, but keep in mind that it's not strictly correct. + * + * It is common to think of the parameter as time. The curve can then be interpreted as + * describing the position of some moving object from time \f$t=0\f$ to \f$t=1\f$. + * Because of this, the parameter is frequently called the time value. + * + * Some methods return pointers to newly allocated curves. They are expected to be freed + * by the caller when no longer used. Default implementations are provided for some methods. + * + * @ingroup Curves + */ class Curve : private CurveHelpers { public: - virtual ~Curve() {} - - virtual Point initialPoint() const = 0; - virtual Point finalPoint() const = 0; - - /* isDegenerate returns true if the curve has "zero length". - * For a bezier curve this means for example that all handles are at the same point */ - virtual bool isDegenerate() const = 0; - - virtual Curve *duplicate() const = 0; - - virtual OptRect boundsFast() const = 0; - virtual OptRect boundsExact() const = 0; - virtual OptRect boundsLocal(OptInterval i, unsigned deg) const = 0; - OptRect boundsLocal(OptInterval i) const { return boundsLocal(i, 0); } - - virtual std::vector roots(double v, Dim2 d) const = 0; - - virtual int winding(Point p) const { return root_winding(*this, p); } - - virtual int degreesOfFreedom() const { return 0;} - - //mental: review these - virtual Curve *portion(double f, double t) const = 0; - virtual Curve *reverse() const { return portion(1, 0); } - virtual Curve *derivative() const = 0; - - virtual void setInitial(Point v) = 0; - virtual void setFinal(Point v) = 0; - - virtual - double nearestPoint( Point const& p, double from = 0, double to = 1 ) const - { - return nearest_point(p, toSBasis(), from, to); - } - - virtual - std::vector - allNearestPoints( Point const& p, double from = 0, double to = 1 ) const - { - return all_nearest_points(p, toSBasis(), from, to); - } - - /* - Path operator*=(Matrix) - This is not possible, because: - A Curve can be many things, for example a HLineSegment. - Such a segment cannot be transformed and stay a HLineSegment in general (take for example rotations). - This means that these curves become a different type of curve, hence one should use "transformed(Matrix). - */ - - virtual Curve *transformed(Matrix const &m) const = 0; - - virtual Point pointAt(Coord t) const { return pointAndDerivatives(t, 0).front(); } - virtual Coord valueAt(Coord t, Dim2 d) const { return pointAt(t)[d]; } - virtual Point operator() (double t) const { return pointAt(t); } - - /* pointAndDerivatives returns a vector that looks like the following: - * [ point at t, 1st derivative at t, 2nd derivative at t, ... , n'th derivative at t] */ - virtual std::vector pointAndDerivatives(Coord t, unsigned n) const = 0; - - /* unitTangentAt returns the unit vector tangent to the curve at position t - * (in the direction of increasing t). The method uses l'Hopital's rule when the derivative - * is (0,0), parameter n determines the maximum nr of iterations (for when higher derivatives are also (0,0) ). - * Point(0,0) is returned if no non-zero derivative could be found. - * Note that unitTangentAt(1) will probably not give the desired result. Probably one should do: - * Curve * c_reverse = c.reverse(); - * Point tangent = - c_reverse->unitTangentAt(0); - * delete c_reverse; - */ - virtual Point unitTangentAt(Coord t, unsigned n = 3) const - { - std::vector derivs = pointAndDerivatives(t, n); - for (unsigned deriv_n = 1; deriv_n < derivs.size(); deriv_n++) { - Coord length = derivs[deriv_n].length(); - if ( ! are_near(length, 0) ) { - // length of derivative is non-zero, so return unit vector - return derivs[deriv_n] / length; - } + virtual ~Curve() {} + + /// @name Evaluate the curve + /// @{ + /** @brief Retrieve the start of the curve. + * @return The point corresponding to \f$\mathbf{C}(0)\f$. */ + virtual Point initialPoint() const = 0; + /** Retrieve the end of the curve. + * @return The point corresponding to \f$\mathbf{C}(1)\f$. */ + virtual Point finalPoint() const = 0; + /** @brief Check whether the curve has exactly zero length. + * @return True if the curve's initial point is exactly the same as its final point, and it contains + * no other points (its value set contains only one element). + */ + virtual bool isDegenerate() const = 0; + /** @brief Evaluate the curve at a specified time value. + * @param t Time value + * @return \f$\mathbf{C}(t)\f$ */ + virtual Point pointAt(Coord t) const { return pointAndDerivatives(t, 0).front(); } + /** @brief Evaluate one of the coordinates at the specified time value. + * @param t Time value + * @param d The dimension to evaluate + * @return The specified coordinate of \f$\mathbf{C}(t)\f$ */ + virtual Coord valueAt(Coord t, Dim2 d) const { return pointAt(t)[d]; } + /** @brief Evaluate the function at the specified time value. Allows curves to be used + * as functors. */ + virtual Point operator() (Coord t) const { return pointAt(t); } + /** @brief Evaluate the curve and its derivatives. + * This will return a vector that contains the value of the curve and the specified number + * of derivatives. However, the returned vector might contain less elements than specified + * if some derivatives do not exist. + * @param t Time value + * @param n The number of derivatives to compute + * @return Vector of at most \f$n+1\f$ elements of the form \f$[\mathbf{C}(t), + \mathbf{C}'(t), \mathbf{C}''(t), \ldots]\f$ */ + virtual std::vector pointAndDerivatives(Coord t, unsigned n) const = 0; + /// @} + + /// @name Change the curve's endpoints + /// @{ + /** @brief Change the starting point of the curve. + * After calling this method, it is guaranteed that \f$\mathbf{C}(0) = \mathbf{p}\f$, + * and the curve is still continuous. The precise new shape of the curve varies with curve + * type. + * @param p New starting point of the curve */ + virtual void setInitial(Point const &v) = 0; + /** @brief Change the ending point of the curve. + * After calling this method, it is guaranteed that \f$\mathbf{C}(0) = \mathbf{p}\f$, + * and the curve is still continuous. The precise new shape of the curve varies + * with curve type. + * @param p New ending point of the curve */ + virtual void setFinal(Point const &v) = 0; + /// @} + + /// @name Compute the bounding box + /// @{ + /** @brief Quickly compute the curve's approximate bounding box. + * The resulting rectangle is guaranteed to contain all points belonging to the curve, + * but it might not be the smallest such rectangle. This method is usually fast. + * @return A rectangle that contains all points belonging to the curve. */ + virtual Rect boundsFast() const = 0; + /** @brief Compute the curve's exact bounding box. + * This method can be dramatically slower than boundsExact() depending on the curve type. + * @return The smallest possible rectangle containing all of the curve's points. */ + virtual Rect boundsExact() const = 0; + // I have no idea what the 'deg' parameter is for, so this is undocumented for now. + virtual OptRect boundsLocal(OptInterval const &i, unsigned deg) const = 0; + /** @brief Compute the bounding box of a part of the curve. + * Since this method returns the smallest possible bounding rectangle of the specified portion, + * it can also be rather slow. + * @param a An interval specifying a part of the curve, or nothing. + * If \f$[0, 1] \subseteq a\f$, then the bounding box for the entire curve + * is calculated. + * @return The smallest possible rectangle containing all points in \f$\mathbf{C}[a]\f$, + * or nothing if the supplied interval is empty. */ + OptRect boundsLocal(OptInterval const &a) const { return boundsLocal(a, 0); } + /// @} + + /// @name Create new curves based on this one + /// @{ + /** @brief Create an exact copy of this curve. + * @return Pointer to a newly allocated curve, identical to the original */ + virtual Curve *duplicate() const = 0; + /** @brief Create a curve transformed by an affine transformation. + * This method returns a new curve instead modifying the existing one, because some curve + * types are not closed under affine transformations. The returned curve may be of different + * underlying type (as is the case for horizontal and vertical line segments). + * @param m Affine describing the affine transformation + * @return Pointer to a new, transformed curve */ + virtual Curve *transformed(Affine const &m) const = 0; + /** @brief Create a curve that corresponds to a part of this curve. + * For \f$a > b\f$, the returned portion will be reversed with respect to the original. + * The returned curve will always be of the same type. + * @param a Beginning of the interval specifying the portion of the curve + * @param b End of the interval + * @return New curve \f$\mathbf{D}\f$ such that: + * - \f$\mathbf{D}(0) = \mathbf{C}(a)\f$ + * - \f$\mathbf{D}(1) = \mathbf{C}(b)\f$ + * - \f$\mathbf{D}[ [0, 1] ] = \mathbf{C}[ [a?b] ]\f$, + * where \f$[a?b] = [\min(a, b), \max(a, b)]\f$ */ + virtual Curve *portion(Coord a, Coord b) const = 0; + /** @brief A version of that accepts an Interval. */ + Curve *portion(Interval const &i) const { return portion(i.min(), i.max()); } + /** @brief Create a reversed version of this curve. + * The result corresponds to portion(1, 0), but this method might be faster. + * @return Pointer to a new curve \f$\mathbf{D}\f$ such that + * \f$\forall_{x \in [0, 1]} \mathbf{D}(x) = \mathbf{C}(1-x)\f$ */ + virtual Curve *reverse() const { return portion(1, 0); } + /** @brief Create a derivative of this curve. + * It's best to think of the derivative in physical terms: if the curve describes + * the position of some object on the plane from time \f$t=0\f$ to \f$t=1\f$ as said in the + * introduction, then the curve's derivative describes that object's speed at the same times. + * The second derivative refers to its acceleration, the third to jerk, etc. + * @return New curve \f$\mathbf{D} = \mathbf{C}'\f$. */ + virtual Curve *derivative() const = 0; + /// @} + + /// @name Advanced operations + /// @{ + /** @brief Compute a time value at which the curve comes closest to a specified point. + * The first value with the smallest distance is returned if there are multiple such points. + * @param p Query point + * @param a Minimum time value to consider + * @param b Maximum time value to consider; \f$a < b\f$ + * @return \f$q \in [a, b]: ||\mathbf{C}(q) - \mathbf{p}|| = + \inf(\{r \in \mathbb{R} : ||\mathbf{C}(r) - \mathbf{p}||\})\f$ */ + virtual Coord nearestPoint( Point const& p, Coord a = 0, Coord b = 1 ) const; + /** @brief A version that takes an Interval. */ + Coord nearestPoint(Point const &p, Interval const &i) const { + return nearestPoint(p, i.min(), i.max()); } - return Point (0,0); - }; - - virtual D2 toSBasis() const = 0; - virtual bool operator==(Curve const &c) const { return this == &c;} + /** @brief Compute time values at which the curve comes closest to a specified point. + * @param p Query point + * @param a Minimum time value to consider + * @param b Maximum time value to consider; \f$a < b\f$ + * @return Vector of points closest and equally far away from the query point */ + virtual std::vector allNearestPoints( Point const& p, Coord from = 0, + Coord to = 1 ) const; + /** @brief A version that takes an Interval. */ + std::vector allNearestPoints(Point const &p, Interval const &i) { + return allNearestPoints(p, i.min(), i.max()); + } + /** @brief Compute the arc length of this curve. + * For a curve \f$\mathbf{C}(t) = (C_x(t), C_y(t))\f$, arc length is defined for 2D curves as + * \f[ \ell = \int_{0}^{1} \sqrt { [C_x'(t)]^2 + [C_y'(t)]^2 }\, \text{d}t \f] + * In other words, we divide the curve into infinitely small linear segments + * and add together their lengths. Of course we can't subdivide the curve into + * infinitely many segments on a computer, so this method returns an approximation. + * Not that there is usually no closed form solution to such integrals, so this + * method might be slow. + * @param tolerance Maximum allowed error + * @return Total distance the curve's value travels on the plane when going from 0 to 1 */ + virtual Coord length(Coord tolerance=0.01) const; + /** @brief Computes time values at which the curve intersects an axis-aligned line. + * @param v The coordinate of the line + * @param d Which axis the coordinate is on. X means a vertical line, Y a horizontal line. */ + virtual std::vector roots(Coord v, Dim2 d) const = 0; + /** @brief Compute the winding number of the curve at the specified point. + * @todo Does this makes sense for curves at all? */ + virtual int winding(Point const &p) const { return root_winding(*this, p); } + /** @brief Compute a vector tangent to the curve. + * This will return an unit vector (a Point with length() equal to 1) that denotes a vector + * tangent to the curve. This vector is defined as + * \f$ \mathbf{v}(t) = \frac{\mathbf{C}'(t)}{||\mathbf{C}'(t)||} \f$. It is pointed + * in the direction of increasing \f$t\f$, at the specfied time value. The method uses + * l'Hopital's rule when the derivative is zero. A zero vector is returned if no non-zero + * derivative could be found. + * @param t Time value + * @param n The maximum order of derivative to consider + * @return Unit tangent vector \f$\mathbf{v}(t)\f$ + * @bug This method might currently break for the case of t being exactly 1. A workaround + * is to reverse the curve and use the negated unit tangent at 0 like this: + * @code + Curve *c_reverse = c.reverse(); + Point tangent = - c_reverse->unitTangentAt(0); + delete c_reverse; @endcode */ + virtual Point unitTangentAt(Coord t, unsigned n = 3) const; + /** @brief Convert the curve to a symmetric power basis polynomial. + * Symmetric power basis polynomials (S-basis for short) are numerical representations + * of curves with excellent numerical properties. Most high level operations provided by 2Geom + * are implemented in terms of S-basis operations, so every curve has to provide a method + * to convert it to an S-basis polynomial on two variables. See SBasis class reference + * for more information. */ + virtual D2 toSBasis() const = 0; + /// @} + + /// @name Miscellaneous + /// @{ + /** Return the number of independent parameters required to represent all variations + * of this curve. For example, for Bezier curves it returns the curve's order + * multiplied by 2. */ + virtual int degreesOfFreedom() const { return 0;} + /** @brief Test equality of two curves. + * @return True if the curves are identical, false otherwise */ + virtual bool operator==(Curve const &c) const { return this == &c;} + /// @} }; inline -Coord nearest_point(Point const& p, Curve const& c) -{ - return c.nearestPoint(p); +Coord nearest_point(Point const& p, Curve const& c) { + return c.nearestPoint(p); } } // end namespace Geom @@ -161,8 +287,6 @@ Coord nearest_point(Point const& p, Curve const& c) #endif // _2GEOM_CURVE_H_ - - /* Local Variables: mode:c++ diff --git a/src/2geom/curves.h b/src/2geom/curves.h index 6c8435387..64cf3d4fb 100644 --- a/src/2geom/curves.h +++ b/src/2geom/curves.h @@ -1,7 +1,7 @@ /** * \file - * \brief this file is only a helper header to include all curve types at once - * + * \brief Include all curve types + *//* * Authors: * MenTaLguY * Marco Cecchetti @@ -32,9 +32,6 @@ * the specific language governing rights and limitations. */ - - - #ifndef _2GEOM_CURVES_H_ #define _2GEOM_CURVES_H_ @@ -43,15 +40,11 @@ #include <2geom/sbasis-curve.h> #include <2geom/bezier-curve.h> #include <2geom/hvlinesegment.h> -//#include <2geom/elliptical-arc.h> +#include <2geom/elliptical-arc.h> #include <2geom/svg-elliptical-arc.h> - #endif // _2GEOM_CURVES_H_ - - - /* Local Variables: mode:c++ diff --git a/src/2geom/d2-sbasis.cpp b/src/2geom/d2-sbasis.cpp index 4f5a53cd2..697a9d84e 100644 --- a/src/2geom/d2-sbasis.cpp +++ b/src/2geom/d2-sbasis.cpp @@ -121,7 +121,7 @@ Piecewise cross(Piecewise > const &a, return result; } -Piecewise > operator*(Piecewise > const &a, Matrix const &m) { +Piecewise > operator*(Piecewise > const &a, Affine const &m) { Piecewise > result; if(a.empty()) return result; result.push_cut(a.cuts[0]); @@ -259,6 +259,57 @@ std::vector > > fuse_nearby_ends(std::vector intersect( std::vector const &a, std::vector const &b){ + std::vector result; + //TODO: use order! + for (unsigned i=0; i < a.size(); i++){ + for (unsigned j=0; j < b.size(); j++){ + OptInterval c( a[i] ); + c &= b[j]; + if ( c ) { + result.push_back( *c ); + } + } + } + return result; +} + +std::vector level_set( D2 const &f, Rect region){ + std::vector regions( 1, region ); + return level_sets( f, regions ).front(); +} +std::vector level_set( D2 const &f, Point p, double tol){ + Rect region(p, p); + region.expandBy( tol ); + return level_set( f, region ); +} +std::vector > level_sets( D2 const &f, std::vector regions){ + std::vector regsX (regions.size(), Interval() ); + std::vector regsY (regions.size(), Interval() ); + for ( unsigned i=0; i < regions.size(); i++ ){ + regsX[i] = regions[i][X]; + regsY[i] = regions[i][Y]; + } + std::vector > x_in_regs = level_sets( f[X], regsX ); + std::vector > y_in_regs = level_sets( f[Y], regsY ); + std::vector >result(regions.size(), std::vector() ); + for (unsigned i=0; i > level_sets( D2 const &f, std::vector pts, double tol){ + std::vector regions( pts.size(), Rect() ); + for (unsigned i=0; i #include <2geom/sbasis-2d.h> #include <2geom/piecewise.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> //TODO: implement intersect @@ -76,7 +76,7 @@ Piecewise dot(Piecewise > const &a, Piecewise > co Piecewise dot(Piecewise > const &a, Point const &b); Piecewise cross(Piecewise > const &a, Piecewise > const &b); -Piecewise > operator*(Piecewise > const &a, Matrix const &m); +Piecewise > operator*(Piecewise > const &a, Affine const &m); Piecewise > force_continuity(Piecewise > const &f, double tol=0, bool closed=false); @@ -138,6 +138,11 @@ inline OptRect bounds_local(D2 const & s, OptInterval i, unsigned order= return retval; } +std::vector level_set( D2 const &f, Rect region); +std::vector level_set( D2 const &f, Point p, double tol); +std::vector > level_sets( D2 const &f, std::vector regions); +std::vector > level_sets( D2 const &f, std::vector pts, double tol); + } #endif diff --git a/src/2geom/d2.h b/src/2geom/d2.h index bdf042806..3e4de430e 100644 --- a/src/2geom/d2.h +++ b/src/2geom/d2.h @@ -34,7 +34,7 @@ #include <2geom/point.h> #include <2geom/interval.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> #include #include <2geom/concepts.h> @@ -251,7 +251,7 @@ template inline D2 operator/=(D2 & a, double b) { a[0] /= b; a[1] /= b; return a; } template -D2 operator*(D2 const &v, Matrix const &m) { +D2 operator*(D2 const &v, Affine const &m) { boost::function_requires >(); boost::function_requires >(); D2 ret; diff --git a/src/2geom/ellipse.cpp b/src/2geom/ellipse.cpp index 8030ea517..bea99e5dd 100644 --- a/src/2geom/ellipse.cpp +++ b/src/2geom/ellipse.cpp @@ -170,7 +170,7 @@ void Ellipse::set(std::vector const& points) } -SVGEllipticalArc +EllipticalArc * Ellipse::arc(Point const& initial, Point const& inner, Point const& final, bool _svg_compliant) { @@ -212,21 +212,27 @@ Ellipse::arc(Point const& initial, Point const& inner, Point const& final, } } - SVGEllipticalArc ea( initial, ray(X), ray(Y), rot_angle(), - large_arc_flag, sweep_flag, final, _svg_compliant); - return ea; + EllipticalArc *ret_arc; + if (_svg_compliant) { + ret_arc = new SVGEllipticalArc(initial, ray(X), ray(Y), rot_angle(), + large_arc_flag, sweep_flag, final); + } else { + ret_arc = new EllipticalArc(initial, ray(X), ray(Y), rot_angle(), + large_arc_flag, sweep_flag, final); + } + return ret_arc; } -Ellipse Ellipse::transformed(Matrix const& m) const +Ellipse Ellipse::transformed(Affine const& m) const { double cosrot = std::cos(rot_angle()); double sinrot = std::sin(rot_angle()); - Matrix A( ray(X) * cosrot, ray(X) * sinrot, + Affine A( ray(X) * cosrot, ray(X) * sinrot, -ray(Y) * sinrot, ray(Y) * cosrot, 0, 0 ); Point new_center = center() * m; - Matrix M = m.without_translation(); - Matrix AM = A * M; + Affine M = m.withoutTranslation(); + Affine AM = A * M; if ( are_near(AM.det(), 0) ) { double angle; @@ -250,11 +256,11 @@ Ellipse Ellipse::transformed(Matrix const& m) const } std::vector coeff = implicit_form_coefficients(); - Matrix Q( coeff[0], coeff[1]/2, + Affine Q( coeff[0], coeff[1]/2, coeff[1]/2, coeff[2], 0, 0 ); - Matrix invm = M.inverse(); + Affine invm = M.inverse(); Q = invm * Q ; std::swap( invm[1], invm[2] ); Q *= invm; diff --git a/src/2geom/ellipse.h b/src/2geom/ellipse.h index 8e44f3395..297254366 100644 --- a/src/2geom/ellipse.h +++ b/src/2geom/ellipse.h @@ -35,15 +35,15 @@ #ifndef _2GEOM_ELLIPSE_H_ #define _2GEOM_ELLIPSE_H_ - +#include #include <2geom/point.h> #include <2geom/exception.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> namespace Geom { -class SVGEllipticalArc; +class EllipticalArc; class Circle; class Ellipse @@ -88,9 +88,8 @@ class Ellipse // prerequisite: at least 5 points must be passed void set(std::vector const& points); - SVGEllipticalArc - arc(Point const& initial, Point const& inner, Point const& final, - bool _svg_compliant = true); + EllipticalArc * + arc(Point const& initial, Point const& inner, Point const& final, bool svg_compliant = true); Point center() const { @@ -114,7 +113,7 @@ class Ellipse std::vector implicit_form_coefficients() const; - Ellipse transformed(Matrix const& m) const; + Ellipse transformed(Affine const& m) const; private: Point m_centre, m_ray; diff --git a/src/2geom/elliptical-arc.cpp b/src/2geom/elliptical-arc.cpp index fd0e7cf9b..acaad82cf 100644 --- a/src/2geom/elliptical-arc.cpp +++ b/src/2geom/elliptical-arc.cpp @@ -1,7 +1,10 @@ /* * SVG Elliptical Arc Class * - * Copyright 2008 Marco Cecchetti + * Authors: + * Marco Cecchetti + * Krzysztof Kosiński + * Copyright 2008-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 @@ -27,896 +30,881 @@ * the specific language governing rights and limitations. */ +#include +#include +#include #include <2geom/elliptical-arc.h> +#include <2geom/ellipse.h> +#include <2geom/sbasis-geometric.h> #include <2geom/bezier-curve.h> #include <2geom/poly.h> -#include <2geom/sbasis-math.h> - -#include -#include - +#include <2geom/transforms.h> +#include <2geom/utils.h> +#include <2geom/numeric/vector.h> +#include <2geom/numeric/fitting-tool.h> +#include <2geom/numeric/fitting-model.h> namespace Geom { +/** + * @class EllipticalArc + * @brief Elliptical arc curve + * + * Elliptical arc is a curve taking the shape of a section of an ellipse. + * + * The arc function has two forms: the regular one, mapping the unit interval to points + * on 2D plane (the linear domain), and a second form that maps some interval + * \f$A \subseteq [0,2\pi)\f$ to the same points (the angular domain). The interval \f$A\f$ + * determines which part of the ellipse forms the arc. The arc is said to contain an angle + * if its angular domain includes that angle (and therefore it is defined for that angle). + * + * The angular domain considers each ellipse to be + * a rotated, scaled and translated unit circle: 0 corresponds to \f$(1,0)\f$ on the unit circle, + * \f$\pi/2\f$ corresponds to \f$(0,1)\f$, \f$\pi\f$ to \f$(-1,0)\f$ and \f$3\pi/2\f$ + * to \f$(0,-1)\f$. After the angle is mapped to a point from a unit circle, the point is + * transformed using a matrix of this form + * \f[ M = \left[ \begin{array}{ccc} + r_X \cos(\theta) & -r_Y \sin(\theta) & 0 \\ + r_X \sin(\theta) & r_Y \cos(\theta) & 0 \\ + c_X & c_Y & 1 \end{array} \right] \f] + * where \f$r_X, r_Y\f$ are the X and Y rays of the ellipse, \f$\theta\f$ is its angle of rotation, + * and \f$c_X, c_Y\f$ the coordinates of the ellipse's center - thus mapping the angle + * to some point on the ellipse. Note that for example the point at angluar coordinate 0, + * the center and the point at angular coordinate \f$\pi/4\f$ do not necessarily + * create an angle of \f$\pi/4\f$ radians; it is only the case if both axes of the ellipse + * are of the same length (i.e. it is a circle). + * + * @image html ellipse-angular-coordinates.png "An illustration of the angular domain" + * + * Each arc is defined by five variables: The initial and final point, the ellipse's rays, + * and the ellipse's rotation. Each set of those parameters corresponds to four different arcs, + * with two of them larger than half an ellipse and two of them turning clockwise while traveling + * from initial to final point. The two flags disambiguate between them: "large arc flag" selects + * the bigger arc, while the "sweep flag" selects the clockwise arc. + * + * @image html elliptical-arc-flags.png "The four possible arcs and the meaning of flags" + * + * @ingroup Curves + */ -OptRect EllipticalArc::boundsExact() const +Rect EllipticalArc::boundsExact() const { - std::vector extremes(4); - double cosrot = std::cos(rotation_angle()); - double sinrot = std::sin(rotation_angle()); - extremes[0] = std::atan2( -ray(Y) * sinrot, ray(X) * cosrot ); - extremes[1] = extremes[0] + M_PI; - if ( extremes[0] < 0 ) extremes[0] += 2*M_PI; - extremes[2] = std::atan2( ray(Y) * cosrot, ray(X) * sinrot ); - extremes[3] = extremes[2] + M_PI; - if ( extremes[2] < 0 ) extremes[2] += 2*M_PI; - - - std::vectorarc_extremes(4); - arc_extremes[0] = initialPoint()[X]; - arc_extremes[1] = finalPoint()[X]; - if ( arc_extremes[0] < arc_extremes[1] ) - std::swap(arc_extremes[0], arc_extremes[1]); - arc_extremes[2] = initialPoint()[Y]; - arc_extremes[3] = finalPoint()[Y]; - if ( arc_extremes[2] < arc_extremes[3] ) - std::swap(arc_extremes[2], arc_extremes[3]); - - - if ( start_angle() < end_angle() ) - { - if ( sweep_flag() ) - { - for ( unsigned int i = 0; i < extremes.size(); ++i ) - { - if ( start_angle() < extremes[i] && extremes[i] < end_angle() ) - { - arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1]; - } - } - } - else - { - for ( unsigned int i = 0; i < extremes.size(); ++i ) - { - if ( start_angle() > extremes[i] || extremes[i] > end_angle() ) - { - arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1]; - } - } - } - } - else - { - if ( sweep_flag() ) - { - for ( unsigned int i = 0; i < extremes.size(); ++i ) - { - if ( start_angle() < extremes[i] || extremes[i] < end_angle() ) - { - arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1]; - } - } - } - else - { - for ( unsigned int i = 0; i < extremes.size(); ++i ) - { - if ( start_angle() > extremes[i] && extremes[i] > end_angle() ) - { - arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1]; - } - } - } - } - - return Rect( Point(arc_extremes[1], arc_extremes[3]) , - Point(arc_extremes[0], arc_extremes[2]) ); + double extremes[4]; + double sinrot, cosrot; + sincos(_rot_angle, sinrot, cosrot); + + extremes[0] = std::atan2( -ray(Y) * sinrot, ray(X) * cosrot ); + extremes[1] = extremes[0] + M_PI; + if ( extremes[0] < 0 ) extremes[0] += 2*M_PI; + extremes[2] = std::atan2( ray(Y) * cosrot, ray(X) * sinrot ); + extremes[3] = extremes[2] + M_PI; + if ( extremes[2] < 0 ) extremes[2] += 2*M_PI; + + + double arc_extremes[4]; + arc_extremes[0] = initialPoint()[X]; + arc_extremes[1] = finalPoint()[X]; + if ( arc_extremes[0] < arc_extremes[1] ) + std::swap(arc_extremes[0], arc_extremes[1]); + arc_extremes[2] = initialPoint()[Y]; + arc_extremes[3] = finalPoint()[Y]; + if ( arc_extremes[2] < arc_extremes[3] ) + std::swap(arc_extremes[2], arc_extremes[3]); + + for (unsigned i = 0; i < 4; ++i) { + if (containsAngle(extremes[i])) { + arc_extremes[i] = valueAtAngle(extremes[i], i >> 1 ? Y : X); + } + } + return Rect( Point(arc_extremes[1], arc_extremes[3]) , + Point(arc_extremes[0], arc_extremes[2]) ); } -std::vector -EllipticalArc::roots(double v, Dim2 d) const +Point EllipticalArc::pointAtAngle(Coord t) const { - if ( d > Y ) - { - THROW_RANGEERROR("dimention out of range"); - } - - std::vector sol; - if ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) - { - if ( center(d) == v ) - sol.push_back(0); - return sol; - } - - const char* msg[2][2] = - { - { "d == X; ray(X) == 0; " - "s = (v - center(X)) / ( -ray(Y) * std::sin(rotation_angle()) ); " - "s should be contained in [-1,1]", - "d == X; ray(Y) == 0; " - "s = (v - center(X)) / ( ray(X) * std::cos(rotation_angle()) ); " - "s should be contained in [-1,1]" - }, - { "d == Y; ray(X) == 0; " - "s = (v - center(X)) / ( ray(Y) * std::cos(rotation_angle()) ); " - "s should be contained in [-1,1]", - "d == Y; ray(Y) == 0; " - "s = (v - center(X)) / ( ray(X) * std::sin(rotation_angle()) ); " - "s should be contained in [-1,1]" - }, - }; - - for ( unsigned int dim = 0; dim < 2; ++dim ) - { - if ( are_near(ray(dim), 0) ) - { - - if ( initialPoint()[d] == v && finalPoint()[d] == v ) - { - THROW_INFINITESOLUTIONS(0); - } - if ( (initialPoint()[d] < finalPoint()[d]) - && (initialPoint()[d] > v || finalPoint()[d] < v) ) - { - return sol; - } - if ( (initialPoint()[d] > finalPoint()[d]) - && (finalPoint()[d] > v || initialPoint()[d] < v) ) - { - return sol; - } - double ray_prj; - switch(d) - { - case X: - switch(dim) - { - case X: ray_prj = -ray(Y) * std::sin(rotation_angle()); - break; - case Y: ray_prj = ray(X) * std::cos(rotation_angle()); - break; - } - break; - case Y: - switch(dim) - { - case X: ray_prj = ray(Y) * std::cos(rotation_angle()); - break; - case Y: ray_prj = ray(X) * std::sin(rotation_angle()); - break; - } - break; - } - - double s = (v - center(d)) / ray_prj; - if ( s < -1 || s > 1 ) - { - THROW_LOGICALERROR(msg[d][dim]); - } - switch(dim) - { - case X: - s = std::asin(s); // return a value in [-PI/2,PI/2] - if ( logical_xor( sweep_flag(), are_near(start_angle(), M_PI/2) ) ) - { - if ( s < 0 ) s += 2*M_PI; - } - else - { - s = M_PI - s; - if (!(s < 2*M_PI) ) s -= 2*M_PI; - } - break; - case Y: - s = std::acos(s); // return a value in [0,PI] - if ( logical_xor( sweep_flag(), are_near(start_angle(), 0) ) ) - { - s = 2*M_PI - s; - if ( !(s < 2*M_PI) ) s -= 2*M_PI; - } - break; - } - - //std::cerr << "s = " << rad_to_deg(s); - s = map_to_01(s); - //std::cerr << " -> t: " << s << std::endl; - if ( !(s < 0 || s > 1) ) - sol.push_back(s); - return sol; - } - } - - double rotx, roty; - switch(d) - { - case X: - rotx = std::cos(rotation_angle()); - roty = -std::sin(rotation_angle()); - break; - case Y: - rotx = std::sin(rotation_angle()); - roty = std::cos(rotation_angle()); - break; - } - double rxrotx = ray(X) * rotx; - double c_v = center(d) - v; - - double a = -rxrotx + c_v; - double b = ray(Y) * roty; - double c = rxrotx + c_v; - //std::cerr << "a = " << a << std::endl; - //std::cerr << "b = " << b << std::endl; - //std::cerr << "c = " << c << std::endl; - - if ( are_near(a,0) ) - { - sol.push_back(M_PI); - if ( !are_near(b,0) ) - { - double s = 2 * std::atan(-c/(2*b)); - if ( s < 0 ) s += 2*M_PI; - sol.push_back(s); - } - } - else - { - double delta = b * b - a * c; - //std::cerr << "delta = " << delta << std::endl; - if ( are_near(delta, 0) ) - { - double s = 2 * std::atan(-b/a); - if ( s < 0 ) s += 2*M_PI; - sol.push_back(s); - } - else if ( delta > 0 ) - { - double sq = std::sqrt(delta); - double s = 2 * std::atan( (-b - sq) / a ); - if ( s < 0 ) s += 2*M_PI; - sol.push_back(s); - s = 2 * std::atan( (-b + sq) / a ); - if ( s < 0 ) s += 2*M_PI; - sol.push_back(s); - } - } - - std::vector arc_sol; - for (unsigned int i = 0; i < sol.size(); ++i ) - { - //std::cerr << "s = " << rad_to_deg(sol[i]); - sol[i] = map_to_01(sol[i]); - //std::cerr << " -> t: " << sol[i] << std::endl; - if ( !(sol[i] < 0 || sol[i] > 1) ) - arc_sol.push_back(sol[i]); - } - return arc_sol; - - -// return SBasisCurve(toSBasis()).roots(v, d); + Point ret = Point::polar(t) * unitCircleTransform(); + return ret; } -// D(E(t,C),t) = E(t+PI/2,O) -Curve* EllipticalArc::derivative() const +Coord EllipticalArc::valueAtAngle(Coord t, Dim2 d) const { - EllipticalArc* result = new EllipticalArc(*this); - result->m_center[X] = result->m_center[Y] = 0; - result->m_start_angle += M_PI/2; - if( !( result->m_start_angle < 2*M_PI ) ) - { - result->m_start_angle -= 2*M_PI; - } - result->m_end_angle += M_PI/2; - if( !( result->m_end_angle < 2*M_PI ) ) - { - result->m_end_angle -= 2*M_PI; - } - result->m_initial_point = result->pointAtAngle( result->start_angle() ); - result->m_final_point = result->pointAtAngle( result->end_angle() ); - return result; + Coord sinrot, cosrot, cost, sint; + sincos(_rot_angle, sinrot, cosrot); + sincos(t, sint, cost); + if ( d == X ) { + return ray(X) * cosrot * cost + - ray(Y) * sinrot * sint + + center(X); + } else { + return ray(X) * sinrot * cost + + ray(Y) * cosrot * sint + + center(Y); + } } -std::vector -EllipticalArc::pointAndDerivatives(Coord t, unsigned int n) const +Affine EllipticalArc::unitCircleTransform() const { - unsigned int nn = n+1; // nn represents the size of the result vector. - std::vector result; - result.reserve(nn); - double angle = map_unit_interval_on_circular_arc(t, start_angle(), - end_angle(), sweep_flag()); - EllipticalArc ea(*this); - ea.m_center = Point(0,0); - unsigned int m = std::min(nn, 4u); - for ( unsigned int i = 0; i < m; ++i ) - { - result.push_back( ea.pointAtAngle(angle) ); - angle += M_PI/2; - if ( !(angle < 2*M_PI) ) angle -= 2*M_PI; - } - m = nn / 4; - for ( unsigned int i = 1; i < m; ++i ) - { - for ( unsigned int j = 0; j < 4; ++j ) - result.push_back( result[j] ); - } - m = nn - 4 * m; - for ( unsigned int i = 0; i < m; ++i ) - { - result.push_back( result[i] ); - } - if ( !result.empty() ) // nn != 0 - result[0] = pointAtAngle(angle); - return result; + Affine ret = Scale(ray(X), ray(Y)) * Rotate(_rot_angle); + ret.setTranslation(center()); + return ret; } -D2 EllipticalArc::toSBasis() const +std::vector EllipticalArc::roots(Coord v, Dim2 d) const { - // the interval of parametrization has to be [0,1] - Coord et = start_angle() + ( sweep_flag() ? sweep_angle() : -sweep_angle() ); - Linear param(start_angle(), et); - Coord cos_rot_angle = std::cos(rotation_angle()); - Coord sin_rot_angle = std::sin(rotation_angle()); - // order = 4 seems to be enough to get a perfect looking elliptical arc - // should it be choosen in function of the arc length anyway ? - // or maybe a user settable parameter: toSBasis(unsigned int order) ? - SBasis arc_x = ray(X) * cos(param,4); - SBasis arc_y = ray(Y) * sin(param,4); - D2 arc; - arc[0] = arc_x * cos_rot_angle - arc_y * sin_rot_angle + Linear(center(X),center(X)); - arc[1] = arc_x * sin_rot_angle + arc_y * cos_rot_angle + Linear(center(Y),center(Y)); - return arc; + std::vector sol; + + if ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) { + if ( center(d) == v ) + sol.push_back(0); + return sol; + } + + static const char* msg[2][2] = + { + { "d == X; ray(X) == 0; " + "s = (v - center(X)) / ( -ray(Y) * std::sin(_rot_angle) ); " + "s should be contained in [-1,1]", + "d == X; ray(Y) == 0; " + "s = (v - center(X)) / ( ray(X) * std::cos(_rot_angle) ); " + "s should be contained in [-1,1]" + }, + { "d == Y; ray(X) == 0; " + "s = (v - center(X)) / ( ray(Y) * std::cos(_rot_angle) ); " + "s should be contained in [-1,1]", + "d == Y; ray(Y) == 0; " + "s = (v - center(X)) / ( ray(X) * std::sin(_rot_angle) ); " + "s should be contained in [-1,1]" + }, + }; + + for ( unsigned int dim = 0; dim < 2; ++dim ) + { + if ( are_near(ray((Dim2) dim), 0) ) + { + if ( initialPoint()[d] == v && finalPoint()[d] == v ) + { + THROW_INFINITESOLUTIONS(0); + } + if ( (initialPoint()[d] < finalPoint()[d]) + && (initialPoint()[d] > v || finalPoint()[d] < v) ) + { + return sol; + } + if ( (initialPoint()[d] > finalPoint()[d]) + && (finalPoint()[d] > v || initialPoint()[d] < v) ) + { + return sol; + } + double ray_prj; + switch(d) + { + case X: + switch(dim) + { + case X: ray_prj = -ray(Y) * std::sin(_rot_angle); + break; + case Y: ray_prj = ray(X) * std::cos(_rot_angle); + break; + } + break; + case Y: + switch(dim) + { + case X: ray_prj = ray(Y) * std::cos(_rot_angle); + break; + case Y: ray_prj = ray(X) * std::sin(_rot_angle); + break; + } + break; + } + + double s = (v - center(d)) / ray_prj; + if ( s < -1 || s > 1 ) + { + THROW_LOGICALERROR(msg[d][dim]); + } + switch(dim) + { + case X: + s = std::asin(s); // return a value in [-PI/2,PI/2] + if ( logical_xor( _sweep, are_near(initialAngle(), M_PI/2) ) ) + { + if ( s < 0 ) s += 2*M_PI; + } + else + { + s = M_PI - s; + if (!(s < 2*M_PI) ) s -= 2*M_PI; + } + break; + case Y: + s = std::acos(s); // return a value in [0,PI] + if ( logical_xor( _sweep, are_near(initialAngle(), 0) ) ) + { + s = 2*M_PI - s; + if ( !(s < 2*M_PI) ) s -= 2*M_PI; + } + break; + } + + //std::cerr << "s = " << rad_to_deg(s); + s = map_to_01(s); + //std::cerr << " -> t: " << s << std::endl; + if ( !(s < 0 || s > 1) ) + sol.push_back(s); + return sol; + } + } + + double rotx, roty; + sincos(_rot_angle, roty, rotx); + if (d == X) roty = -roty; + + double rxrotx = ray(X) * rotx; + double c_v = center(d) - v; + + double a = -rxrotx + c_v; + double b = ray(Y) * roty; + double c = rxrotx + c_v; + //std::cerr << "a = " << a << std::endl; + //std::cerr << "b = " << b << std::endl; + //std::cerr << "c = " << c << std::endl; + + if ( are_near(a,0) ) + { + sol.push_back(M_PI); + if ( !are_near(b,0) ) + { + double s = 2 * std::atan(-c/(2*b)); + if ( s < 0 ) s += 2*M_PI; + sol.push_back(s); + } + } + else + { + double delta = b * b - a * c; + //std::cerr << "delta = " << delta << std::endl; + if ( are_near(delta, 0) ) + { + double s = 2 * std::atan(-b/a); + if ( s < 0 ) s += 2*M_PI; + sol.push_back(s); + } + else if ( delta > 0 ) + { + double sq = std::sqrt(delta); + double s = 2 * std::atan( (-b - sq) / a ); + if ( s < 0 ) s += 2*M_PI; + sol.push_back(s); + s = 2 * std::atan( (-b + sq) / a ); + if ( s < 0 ) s += 2*M_PI; + sol.push_back(s); + } + } + + std::vector arc_sol; + for (unsigned int i = 0; i < sol.size(); ++i ) + { + //std::cerr << "s = " << rad_to_deg(sol[i]); + sol[i] = map_to_01(sol[i]); + //std::cerr << " -> t: " << sol[i] << std::endl; + if ( !(sol[i] < 0 || sol[i] > 1) ) + arc_sol.push_back(sol[i]); + } + return arc_sol; } -bool EllipticalArc::containsAngle(Coord angle) const +// D(E(t,C),t) = E(t+PI/2,O), where C is the ellipse center +// the derivative doesn't rotate the ellipse but there is a translation +// of the parameter t by an angle of PI/2 so the ellipse points are shifted +// of such an angle in the cw direction +Curve *EllipticalArc::derivative() const { - if ( sweep_flag() ) - if ( start_angle() < end_angle() ) - return ( !( angle < start_angle() || angle > end_angle() ) ); - else - return ( !( angle < start_angle() && angle > end_angle() ) ); - else - if ( start_angle() > end_angle() ) - return ( !( angle > start_angle() || angle < end_angle() ) ); - else - return ( !( angle > start_angle() && angle < end_angle() ) ); + EllipticalArc *result = static_cast(duplicate()); + result->_center[X] = result->_center[Y] = 0; + result->_start_angle += M_PI/2; + if( !( result->_start_angle < 2*M_PI ) ) + { + result->_start_angle -= 2*M_PI; + } + result->_end_angle += M_PI/2; + if( !( result->_end_angle < 2*M_PI ) ) + { + result->_end_angle -= 2*M_PI; + } + result->_initial_point = result->pointAtAngle( result->initialAngle() ); + result->_final_point = result->pointAtAngle( result->finalAngle() ); + return result; } -double EllipticalArc::valueAtAngle(Coord t, Dim2 d) const +std::vector +EllipticalArc::pointAndDerivatives(Coord t, unsigned int n) const { - double sin_rot_angle = std::sin(rotation_angle()); - double cos_rot_angle = std::cos(rotation_angle()); - if ( d == X ) + unsigned int nn = n+1; // nn represents the size of the result vector. + std::vector result; + result.reserve(nn); + double angle = map_unit_interval_on_circular_arc(t, initialAngle(), + finalAngle(), _sweep); + std::auto_ptr ea( static_cast(duplicate()) ); + ea->_center = Point(0,0); + unsigned int m = std::min(nn, 4u); + for ( unsigned int i = 0; i < m; ++i ) { - return ray(X) * cos_rot_angle * std::cos(t) - - ray(Y) * sin_rot_angle * std::sin(t) - + center(X); + result.push_back( ea->pointAtAngle(angle) ); + angle += M_PI/2; + if ( !(angle < 2*M_PI) ) angle -= 2*M_PI; } - else if ( d == Y ) + m = nn / 4; + for ( unsigned int i = 1; i < m; ++i ) { - return ray(X) * sin_rot_angle * std::cos(t) - + ray(Y) * cos_rot_angle * std::sin(t) - + center(Y); + for ( unsigned int j = 0; j < 4; ++j ) + result.push_back( result[j] ); + } + m = nn - 4 * m; + for ( unsigned int i = 0; i < m; ++i ) + { + result.push_back( result[i] ); } - THROW_RANGEERROR("dimension parameter out of range"); + if ( !result.empty() ) // nn != 0 + result[0] = pointAtAngle(angle); + return result; } +bool EllipticalArc::containsAngle(Coord angle) const +{ + return AngleInterval::contains(angle); +} Curve* EllipticalArc::portion(double f, double t) const { - if (f < 0) f = 0; - if (f > 1) f = 1; - if (t < 0) t = 0; - if (t > 1) t = 1; - if ( are_near(f, t) ) - { - EllipticalArc* arc = new EllipticalArc(); - arc->m_center = arc->m_initial_point = arc->m_final_point = pointAt(f); - arc->m_start_angle = arc->m_end_angle = m_start_angle; - arc->m_rot_angle = m_rot_angle; - arc->m_sweep = m_sweep; - arc->m_large_arc = m_large_arc; - } - EllipticalArc* arc = new EllipticalArc( *this ); - arc->m_initial_point = pointAt(f); - arc->m_final_point = pointAt(t); - double sa = sweep_flag() ? sweep_angle() : -sweep_angle(); - arc->m_start_angle = m_start_angle + sa * f; - if ( !(arc->m_start_angle < 2*M_PI) ) - arc->m_start_angle -= 2*M_PI; - if ( arc->m_start_angle < 0 ) - arc->m_start_angle += 2*M_PI; - arc->m_end_angle = m_start_angle + sa * t; - if ( !(arc->m_end_angle < 2*M_PI) ) - arc->m_end_angle -= 2*M_PI; - if ( arc->m_end_angle < 0 ) - arc->m_end_angle += 2*M_PI; - if ( f > t ) arc->m_sweep = !sweep_flag(); - if ( large_arc_flag() && (arc->sweep_angle() < M_PI) ) - arc->m_large_arc = false; + // fix input arguments + if (f < 0) f = 0; + if (f > 1) f = 1; + if (t < 0) t = 0; + if (t > 1) t = 1; + + if ( are_near(f, t) ) + { + EllipticalArc *arc = static_cast(duplicate()); + arc->_center = arc->_initial_point = arc->_final_point = pointAt(f); + arc->_start_angle = arc->_end_angle = _start_angle; + arc->_rot_angle = _rot_angle; + arc->_sweep = _sweep; + arc->_large_arc = _large_arc; + return arc; + } + + EllipticalArc *arc = static_cast(duplicate()); + arc->_initial_point = pointAt(f); + arc->_final_point = pointAt(t); + if ( f > t ) arc->_sweep = !_sweep; + if ( _large_arc && fabs(sweepAngle() * (t-f)) < M_PI) + arc->_large_arc = false; + arc->_updateCenterAndAngles(arc->isSVGCompliant()); //TODO: be more clever return arc; } -// NOTE: doesn't work with 360 deg arcs -void EllipticalArc::calculate_center_and_extreme_angles() +// the arc is the same but traversed in the opposite direction +Curve *EllipticalArc::reverse() const { + EllipticalArc *rarc = static_cast(duplicate()); + rarc->_sweep = !_sweep; + rarc->_initial_point = _final_point; + rarc->_final_point = _initial_point; + rarc->_start_angle = _end_angle; + rarc->_end_angle = _start_angle; + rarc->_updateCenterAndAngles(rarc->isSVGCompliant()); + return rarc; +} + +#ifdef HAVE_GSL // GSL is required for function "solve_reals" +std::vector EllipticalArc::allNearestPoints( Point const& p, double from, double to ) const { - // as stated in the svg standard the rotation angle parameter - // value must be modulo 2*PI - m_rot_angle = std::fmod(m_rot_angle, 2*M_PI); - if (m_rot_angle < 0) m_rot_angle += 2*M_PI; + std::vector result; + + if ( from > to ) std::swap(from, to); + if ( from < 0 || to > 1 ) + { + THROW_RANGEERROR("[from,to] interval out of range"); + } - if ( are_near(initialPoint(), finalPoint()) ) + if ( ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) || are_near(from, to) ) { - if ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) - { - m_start_angle = m_end_angle = 0; - m_center = initialPoint(); - return; - } - else - { - THROW_RANGEERROR("initial and final point are the same"); - } - } - if ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) - { // but initialPoint != finalPoint - THROW_RANGEERROR( - "there is no ellipse that satisfies the given constraints: " - "ray(X) == 0 && ray(Y) == 0 but initialPoint != finalPoint" - ); - } - if ( are_near(ray(Y), 0) ) - { - Point v = initialPoint() - finalPoint(); - if ( are_near(L2sq(v), 4*ray(X)*ray(X)) ) - { - double angle = std::atan2(v[Y], v[X]); - if (angle < 0) angle += 2*M_PI; - if ( are_near( angle, rotation_angle() ) ) - { - m_start_angle = 0; - m_end_angle = M_PI; - m_center = v/2 + finalPoint(); - return; - } - angle -= M_PI; - if ( angle < 0 ) angle += 2*M_PI; - if ( are_near( angle, rotation_angle() ) ) - { - m_start_angle = M_PI; - m_end_angle = 0; - m_center = v/2 + finalPoint(); - return; - } - THROW_RANGEERROR( - "there is no ellipse that satisfies the given constraints: " - "ray(Y) == 0 " - "and slope(initialPoint - finalPoint) != rotation_angle " - "and != rotation_angle + PI" - ); - } - if ( L2sq(v) > 4*ray(X)*ray(X) ) - { - THROW_RANGEERROR( - "there is no ellipse that satisfies the given constraints: " - "ray(Y) == 0 and distance(initialPoint, finalPoint) > 2*ray(X)" - ); - } - else - { - THROW_RANGEERROR( - "there is infinite ellipses that satisfy the given constraints: " - "ray(Y) == 0 and distance(initialPoint, finalPoint) < 2*ray(X)" - ); - } - - } - - if ( are_near(ray(X), 0) ) - { - Point v = initialPoint() - finalPoint(); - if ( are_near(L2sq(v), 4*ray(Y)*ray(Y)) ) - { - double angle = std::atan2(v[Y], v[X]); - if (angle < 0) angle += 2*M_PI; - double rot_angle = rotation_angle() + M_PI/2; - if ( !(rot_angle < 2*M_PI) ) rot_angle -= 2*M_PI; - if ( are_near( angle, rot_angle ) ) - { - m_start_angle = M_PI/2; - m_end_angle = 3*M_PI/2; - m_center = v/2 + finalPoint(); - return; - } - angle -= M_PI; - if ( angle < 0 ) angle += 2*M_PI; - if ( are_near( angle, rot_angle ) ) - { - m_start_angle = 3*M_PI/2; - m_end_angle = M_PI/2; - m_center = v/2 + finalPoint(); - return; - } - THROW_RANGEERROR( - "there is no ellipse that satisfies the given constraints: " - "ray(X) == 0 " - "and slope(initialPoint - finalPoint) != rotation_angle + PI/2 " - "and != rotation_angle + (3/2)*PI" - ); - } - if ( L2sq(v) > 4*ray(Y)*ray(Y) ) - { - THROW_RANGEERROR( - "there is no ellipse that satisfies the given constraints: " - "ray(X) == 0 and distance(initialPoint, finalPoint) > 2*ray(Y)" - ); - } - else - { - THROW_RANGEERROR( - "there is infinite ellipses that satisfy the given constraints: " - "ray(X) == 0 and distance(initialPoint, finalPoint) < 2*ray(Y)" - ); - } - - } - - double sin_rot_angle = std::sin(rotation_angle()); - double cos_rot_angle = std::cos(rotation_angle()); - - Point sp = sweep_flag() ? initialPoint() : finalPoint(); - Point ep = sweep_flag() ? finalPoint() : initialPoint(); - - Matrix m( ray(X) * cos_rot_angle, ray(X) * sin_rot_angle, - -ray(Y) * sin_rot_angle, ray(Y) * cos_rot_angle, - 0, 0 ); - Matrix im = m.inverse(); - Point sol = (ep - sp) * im; - double half_sum_angle = std::atan2(-sol[X], sol[Y]); - double half_diff_angle; - if ( are_near(std::fabs(half_sum_angle), M_PI/2) ) + result.push_back(from); + return result; + } + else if ( are_near(ray(X), 0) || are_near(ray(Y), 0) ) { - double anti_sgn_hsa = (half_sum_angle > 0) ? -1 : 1; - double arg = anti_sgn_hsa * sol[X] / 2; - // if |arg| is a little bit > 1 acos returns nan - if ( are_near(arg, 1) ) - half_diff_angle = 0; - else if ( are_near(arg, -1) ) - half_diff_angle = M_PI; + LineSegment seg(pointAt(from), pointAt(to)); + Point np = seg.pointAt( seg.nearestPoint(p) ); + if ( are_near(ray(Y), 0) ) + { + if ( are_near(_rot_angle, M_PI/2) + || are_near(_rot_angle, 3*M_PI/2) ) + { + result = roots(np[Y], Y); + } + else + { + result = roots(np[X], X); + } + } else { - if ( !(-1 < arg && arg < 1) ) - THROW_RANGEERROR( - "there is no ellipse that satisfies the given constraints" - ); - // assert( -1 < arg && arg < 1 ); - // if it fails - // => there is no ellipse that satisfies the given constraints - half_diff_angle = std::acos( arg ); + if ( are_near(_rot_angle, M_PI/2) + || are_near(_rot_angle, 3*M_PI/2) ) + { + result = roots(np[X], X); + } + else + { + result = roots(np[Y], Y); + } } + return result; + } + else if ( are_near(ray(X), ray(Y)) ) + { + Point r = p - center(); + if ( are_near(r, Point(0,0)) ) + { + THROW_INFINITESOLUTIONS(0); + } + // TODO: implement case r != 0 +// Point np = ray(X) * unit_vector(r); +// std::vector solX = roots(np[X],X); +// std::vector solY = roots(np[Y],Y); +// double t; +// if ( are_near(solX[0], solY[0]) || are_near(solX[0], solY[1])) +// { +// t = solX[0]; +// } +// else +// { +// t = solX[1]; +// } +// if ( !(t < from || t > to) ) +// { +// result.push_back(t); +// } +// else +// { +// +// } + } - half_diff_angle = M_PI/2 - half_diff_angle; + // solve the equation == 0 + // that provides min and max distance points + // on the ellipse E wrt the point p + // after the substitutions: + // cos(t) = (1 - s^2) / (1 + s^2) + // sin(t) = 2t / (1 + s^2) + // where s = tan(t/2) + // we get a 4th degree equation in s + /* + * ry s^4 ((-cy + py) Cos[Phi] + (cx - px) Sin[Phi]) + + * ry ((cy - py) Cos[Phi] + (-cx + px) Sin[Phi]) + + * 2 s^3 (rx^2 - ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi]) + + * 2 s (-rx^2 + ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi]) + */ + + Point p_c = p - center(); + double rx2_ry2 = (ray(X) - ray(Y)) * (ray(X) + ray(Y)); + double sinrot, cosrot; + sincos(_rot_angle, sinrot, cosrot); + double expr1 = ray(X) * (p_c[X] * cosrot + p_c[Y] * sinrot); + Poly coeff; + coeff.resize(5); + coeff[4] = ray(Y) * ( p_c[Y] * cosrot - p_c[X] * sinrot ); + coeff[3] = 2 * ( rx2_ry2 + expr1 ); + coeff[2] = 0; + coeff[1] = 2 * ( -rx2_ry2 + expr1 ); + coeff[0] = -coeff[4]; + +// for ( unsigned int i = 0; i < 5; ++i ) +// std::cerr << "c[" << i << "] = " << coeff[i] << std::endl; + + std::vector real_sol; + // gsl_poly_complex_solve raises an error + // if the leading coefficient is zero + if ( are_near(coeff[4], 0) ) + { + real_sol.push_back(0); + if ( !are_near(coeff[3], 0) ) + { + double sq = -coeff[1] / coeff[3]; + if ( sq > 0 ) + { + double s = std::sqrt(sq); + real_sol.push_back(s); + real_sol.push_back(-s); + } + } } else { - double arg = sol[Y] / ( 2 * std::cos(half_sum_angle) ); - // if |arg| is a little bit > 1 asin returns nan - if ( are_near(arg, 1) ) - half_diff_angle = M_PI/2; - else if ( are_near(arg, -1) ) - half_diff_angle = -M_PI/2; - else + real_sol = solve_reals(coeff); + } + + for ( unsigned int i = 0; i < real_sol.size(); ++i ) + { + real_sol[i] = 2 * std::atan(real_sol[i]); + if ( real_sol[i] < 0 ) real_sol[i] += 2*M_PI; + } + // when s -> Infinity then -> 0 iff coeff[4] == 0 + // so we add M_PI to the solutions being lim arctan(s) = PI when s->Infinity + if ( (real_sol.size() % 2) != 0 ) + { + real_sol.push_back(M_PI); + } + + double mindistsq1 = std::numeric_limits::max(); + double mindistsq2 = std::numeric_limits::max(); + double dsq; + unsigned int mi1, mi2; + for ( unsigned int i = 0; i < real_sol.size(); ++i ) + { + dsq = distanceSq(p, pointAtAngle(real_sol[i])); + if ( mindistsq1 > dsq ) { - if ( !(-1 < arg && arg < 1) ) - THROW_RANGEERROR( - "there is no ellipse that satisfies the given constraints" - ); - // assert( -1 < arg && arg < 1 ); - // if it fails - // => there is no ellipse that satisfies the given constraints - half_diff_angle = std::asin( arg ); + mindistsq2 = mindistsq1; + mi2 = mi1; + mindistsq1 = dsq; + mi1 = i; + } + else if ( mindistsq2 > dsq ) + { + mindistsq2 = dsq; + mi2 = i; } } - if ( ( m_large_arc && half_diff_angle > 0 ) - || (!m_large_arc && half_diff_angle < 0 ) ) + double t = map_to_01( real_sol[mi1] ); + if ( !(t < from || t > to) ) { - half_diff_angle = -half_diff_angle; - } - if ( half_sum_angle < 0 ) half_sum_angle += 2*M_PI; - if ( half_diff_angle < 0 ) half_diff_angle += M_PI; - - m_start_angle = half_sum_angle - half_diff_angle; - m_end_angle = half_sum_angle + half_diff_angle; - // 0 <= m_start_angle, m_end_angle < 2PI - if ( m_start_angle < 0 ) m_start_angle += 2*M_PI; - if( !(m_end_angle < 2*M_PI) ) m_end_angle -= 2*M_PI; - sol[0] = std::cos(m_start_angle); - sol[1] = std::sin(m_start_angle); - m_center = sp - sol * m; - if ( !sweep_flag() ) + result.push_back(t); + } + + bool second_sol = false; + t = map_to_01( real_sol[mi2] ); + if ( real_sol.size() == 4 && !(t < from || t > to) ) { - double angle = m_start_angle; - m_start_angle = m_end_angle; - m_end_angle = angle; + if ( result.empty() || are_near(mindistsq1, mindistsq2) ) + { + result.push_back(t); + second_sol = true; + } } + + // we need to test extreme points too + double dsq1 = distanceSq(p, pointAt(from)); + double dsq2 = distanceSq(p, pointAt(to)); + if ( second_sol ) + { + if ( mindistsq2 > dsq1 ) + { + result.clear(); + result.push_back(from); + mindistsq2 = dsq1; + } + else if ( are_near(mindistsq2, dsq) ) + { + result.push_back(from); + } + if ( mindistsq2 > dsq2 ) + { + result.clear(); + result.push_back(to); + } + else if ( are_near(mindistsq2, dsq2) ) + { + result.push_back(to); + } + + } + else + { + if ( result.empty() ) + { + if ( are_near(dsq1, dsq2) ) + { + result.push_back(from); + result.push_back(to); + } + else if ( dsq2 > dsq1 ) + { + result.push_back(from); + } + else + { + result.push_back(to); + } + } + } + + return result; } +#endif -Coord EllipticalArc::map_to_02PI(Coord t) const +/* + * NOTE: this implementation follows Standard SVG 1.1 implementation guidelines + * for elliptical arc curves. See Appendix F.6. + */ +void EllipticalArc::_updateCenterAndAngles(bool svg) { - if ( sweep_flag() ) + Point d = initialPoint() - finalPoint(); + + // TODO move this to SVGElipticalArc? + if (svg) { - Coord angle = start_angle() + sweep_angle() * t; - if ( !(angle < 2*M_PI) ) - angle -= 2*M_PI; - return angle; + if ( initialPoint() == finalPoint() ) + { + _rot_angle = _start_angle = _end_angle = 0; + _center = initialPoint(); + _rays = Geom::Point(0,0); + _large_arc = _sweep = false; + return; + } + + _rays[X] = std::fabs(_rays[X]); + _rays[Y] = std::fabs(_rays[Y]); + + if ( are_near(ray(X), 0) || are_near(ray(Y), 0) ) + { + _rays[X] = L2(d) / 2; + _rays[Y] = 0; + _rot_angle = std::atan2(d[Y], d[X]); + _start_angle = 0; + _end_angle = M_PI; + _center = middle_point(initialPoint(), finalPoint()); + _large_arc = false; + _sweep = false; + return; + } } else { - Coord angle = start_angle() - sweep_angle() * t; - if ( angle < 0 ) angle += 2*M_PI; - return angle; + if ( are_near(initialPoint(), finalPoint()) ) + { + if ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) + { + _start_angle = _end_angle = 0; + _center = initialPoint(); + return; + } + else + { + THROW_RANGEERROR("initial and final point are the same"); + } + } + if ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) + { // but initialPoint != finalPoint + THROW_RANGEERROR( + "there is no ellipse that satisfies the given constraints: " + "ray(X) == 0 && ray(Y) == 0 but initialPoint != finalPoint" + ); + } + if ( are_near(ray(Y), 0) ) + { + Point v = initialPoint() - finalPoint(); + if ( are_near(L2sq(v), 4*ray(X)*ray(X)) ) + { + Angle angle(v); + if ( are_near( angle, _rot_angle ) ) + { + _start_angle = 0; + _end_angle = M_PI; + _center = v/2 + finalPoint(); + return; + } + angle -= M_PI; + if ( are_near( angle, _rot_angle ) ) + { + _start_angle = M_PI; + _end_angle = 0; + _center = v/2 + finalPoint(); + return; + } + THROW_RANGEERROR( + "there is no ellipse that satisfies the given constraints: " + "ray(Y) == 0 " + "and slope(initialPoint - finalPoint) != rotation_angle " + "and != rotation_angle + PI" + ); + } + if ( L2sq(v) > 4*ray(X)*ray(X) ) + { + THROW_RANGEERROR( + "there is no ellipse that satisfies the given constraints: " + "ray(Y) == 0 and distance(initialPoint, finalPoint) > 2*ray(X)" + ); + } + else + { + THROW_RANGEERROR( + "there is infinite ellipses that satisfy the given constraints: " + "ray(Y) == 0 and distance(initialPoint, finalPoint) < 2*ray(X)" + ); + } + + } + + if ( are_near(ray(X), 0) ) + { + Point v = initialPoint() - finalPoint(); + if ( are_near(L2sq(v), 4*ray(Y)*ray(Y)) ) + { + double angle = std::atan2(v[Y], v[X]); + if (angle < 0) angle += 2*M_PI; + double rot_angle = _rot_angle.radians() + M_PI/2; + if ( !(rot_angle < 2*M_PI) ) rot_angle -= 2*M_PI; + if ( are_near( angle, rot_angle ) ) + { + _start_angle = M_PI/2; + _end_angle = 3*M_PI/2; + _center = v/2 + finalPoint(); + return; + } + angle -= M_PI; + if ( angle < 0 ) angle += 2*M_PI; + if ( are_near( angle, rot_angle ) ) + { + _start_angle = 3*M_PI/2; + _end_angle = M_PI/2; + _center = v/2 + finalPoint(); + return; + } + THROW_RANGEERROR( + "there is no ellipse that satisfies the given constraints: " + "ray(X) == 0 " + "and slope(initialPoint - finalPoint) != rotation_angle + PI/2 " + "and != rotation_angle + (3/2)*PI" + ); + } + if ( L2sq(v) > 4*ray(Y)*ray(Y) ) + { + THROW_RANGEERROR( + "there is no ellipse that satisfies the given constraints: " + "ray(X) == 0 and distance(initialPoint, finalPoint) > 2*ray(Y)" + ); + } + else + { + THROW_RANGEERROR( + "there is infinite ellipses that satisfy the given constraints: " + "ray(X) == 0 and distance(initialPoint, finalPoint) < 2*ray(Y)" + ); + } + + } + } + + Rotate rm(_rot_angle); + Affine m(rm); + m[1] = -m[1]; + m[2] = -m[2]; + + Point p = (d / 2) * m; + double rx2 = _rays[X] * _rays[X]; + double ry2 = _rays[Y] * _rays[Y]; + double rxpy = _rays[X] * p[Y]; + double rypx = _rays[Y] * p[X]; + double rx2py2 = rxpy * rxpy; + double ry2px2 = rypx * rypx; + double num = rx2 * ry2; + double den = rx2py2 + ry2px2; + assert(den != 0); + double rad = num / den; + Point c(0,0); + if (rad > 1) + { + rad -= 1; + rad = std::sqrt(rad); + + if (_large_arc == _sweep) rad = -rad; + c = rad * Point(rxpy / ray(Y), -rypx / ray(X)); + + _center = c * rm + middle_point(initialPoint(), finalPoint()); + } + else if (rad == 1 || svg) + { + double lamda = std::sqrt(1 / rad); + _rays[X] *= lamda; + _rays[Y] *= lamda; + _center = middle_point(initialPoint(), finalPoint()); + } + else + { + THROW_RANGEERROR( + "there is no ellipse that satisfies the given constraints" + ); + } + + Point sp((p[X] - c[X]) / ray(X), (p[Y] - c[Y]) / ray(Y)); + Point ep((-p[X] - c[X]) / ray(X), (-p[Y] - c[Y]) / ray(Y)); + Point v(1, 0); + _start_angle = angle_between(v, sp); + double sweep_angle = angle_between(sp, ep); + if (!_sweep && sweep_angle > 0) sweep_angle -= 2*M_PI; + if (_sweep && sweep_angle < 0) sweep_angle += 2*M_PI; + + _end_angle = _start_angle; + _end_angle += sweep_angle; } -Coord EllipticalArc::map_to_01(Coord angle) const +D2 EllipticalArc::toSBasis() const { - return map_circular_arc_on_unit_interval(angle, start_angle(), - end_angle(), sweep_flag()); + D2 arc; + // the interval of parametrization has to be [0,1] + Coord et = initialAngle().radians() + ( _sweep ? sweepAngle() : -sweepAngle() ); + Linear param(initialAngle(), et); + Coord cos_rot_angle, sin_rot_angle; + sincos(_rot_angle, sin_rot_angle, cos_rot_angle); + + // order = 4 seems to be enough to get a perfect looking elliptical arc + SBasis arc_x = ray(X) * cos(param,4); + SBasis arc_y = ray(Y) * sin(param,4); + arc[0] = arc_x * cos_rot_angle - arc_y * sin_rot_angle + Linear(center(X),center(X)); + arc[1] = arc_x * sin_rot_angle + arc_y * cos_rot_angle + Linear(center(Y),center(Y)); + + // ensure that endpoints remain exact + for ( int d = 0 ; d < 2 ; d++ ) { + arc[d][0][0] = initialPoint()[d]; + arc[d][0][1] = finalPoint()[d]; + } + + return arc; } -std::vector EllipticalArc:: -allNearestPoints( Point const& p, double from, double to ) const +Curve *EllipticalArc::transformed(Affine const& m) const { - if ( from > to ) std::swap(from, to); - if ( from < 0 || to > 1 ) - { - THROW_RANGEERROR("[from,to] interval out of range"); - } - std::vector result; - if ( ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) || are_near(from, to) ) - { - result.push_back(from); - return result; - } - else if ( are_near(ray(X), 0) || are_near(ray(Y), 0) ) - { - LineSegment seg(pointAt(from), pointAt(to)); - Point np = seg.pointAt( seg.nearestPoint(p) ); - if ( are_near(ray(Y), 0) ) - { - if ( are_near(rotation_angle(), M_PI/2) - || are_near(rotation_angle(), 3*M_PI/2) ) - { - result = roots(np[Y], Y); - } - else - { - result = roots(np[X], X); - } - } - else - { - if ( are_near(rotation_angle(), M_PI/2) - || are_near(rotation_angle(), 3*M_PI/2) ) - { - result = roots(np[X], X); - } - else - { - result = roots(np[Y], Y); - } - } - return result; - } - else if ( are_near(ray(X), ray(Y)) ) - { - Point r = p - center(); - if ( are_near(r, Point(0,0)) ) - { - THROW_INFINITESOLUTIONS(0); - } - // TODO: implement case r != 0 -// Point np = ray(X) * unit_vector(r); -// std::vector solX = roots(np[X],X); -// std::vector solY = roots(np[Y],Y); -// double t; -// if ( are_near(solX[0], solY[0]) || are_near(solX[0], solY[1])) -// { -// t = solX[0]; -// } -// else -// { -// t = solX[1]; -// } -// if ( !(t < from || t > to) ) -// { -// result.push_back(t); -// } -// else -// { -// -// } - } - - // solve the equation == 0 - // that provides min and max distance points - // on the ellipse E wrt the point p - // after the substitutions: - // cos(t) = (1 - s^2) / (1 + s^2) - // sin(t) = 2t / (1 + s^2) - // where s = tan(t/2) - // we get a 4th degree equation in s - /* - * ry s^4 ((-cy + py) Cos[Phi] + (cx - px) Sin[Phi]) + - * ry ((cy - py) Cos[Phi] + (-cx + px) Sin[Phi]) + - * 2 s^3 (rx^2 - ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi]) + - * 2 s (-rx^2 + ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi]) - */ - - Point p_c = p - center(); - double rx2_ry2 = (ray(X) - ray(Y)) * (ray(X) + ray(Y)); - double cosrot = std::cos( rotation_angle() ); - double sinrot = std::sin( rotation_angle() ); - double expr1 = ray(X) * (p_c[X] * cosrot + p_c[Y] * sinrot); - Poly coeff; - coeff.resize(5); - coeff[4] = ray(Y) * ( p_c[Y] * cosrot - p_c[X] * sinrot ); - coeff[3] = 2 * ( rx2_ry2 + expr1 ); - coeff[2] = 0; - coeff[1] = 2 * ( -rx2_ry2 + expr1 ); - coeff[0] = -coeff[4]; - -// for ( unsigned int i = 0; i < 5; ++i ) -// std::cerr << "c[" << i << "] = " << coeff[i] << std::endl; - - std::vector real_sol; - // gsl_poly_complex_solve raises an error - // if the leading coefficient is zero - if ( are_near(coeff[4], 0) ) - { - real_sol.push_back(0); - if ( !are_near(coeff[3], 0) ) - { - double sq = -coeff[1] / coeff[3]; - if ( sq > 0 ) - { - double s = std::sqrt(sq); - real_sol.push_back(s); - real_sol.push_back(-s); - } - } - } - else - { - real_sol = solve_reals(coeff); - } -// else -// { -// double sol[8]; -// gsl_poly_complex_workspace * w = gsl_poly_complex_workspace_alloc(5); -// gsl_poly_complex_solve(coeff, 5, w, sol ); -// gsl_poly_complex_workspace_free(w); -// -// for ( unsigned int i = 0; i < 4; ++i ) -// { -// if ( sol[2*i+1] == 0 ) real_sol.push_back(sol[2*i]); -// } -// } - - for ( unsigned int i = 0; i < real_sol.size(); ++i ) - { - real_sol[i] = 2 * std::atan(real_sol[i]); - if ( real_sol[i] < 0 ) real_sol[i] += 2*M_PI; - } - // when s -> Infinity then -> 0 iff coeff[4] == 0 - // so we add M_PI to the solutions being lim arctan(s) = PI when s->Infinity - if ( (real_sol.size() % 2) != 0 ) - { - real_sol.push_back(M_PI); - } - - double mindistsq1 = std::numeric_limits::max(); - double mindistsq2 = std::numeric_limits::max(); - double dsq; - unsigned int mi1, mi2; - for ( unsigned int i = 0; i < real_sol.size(); ++i ) - { - dsq = distanceSq(p, pointAtAngle(real_sol[i])); - if ( mindistsq1 > dsq ) - { - mindistsq2 = mindistsq1; - mi2 = mi1; - mindistsq1 = dsq; - mi1 = i; - } - else if ( mindistsq2 > dsq ) - { - mindistsq2 = dsq; - mi2 = i; - } - } - - double t = map_to_01( real_sol[mi1] ); - if ( !(t < from || t > to) ) - { - result.push_back(t); - } - - bool second_sol = false; - t = map_to_01( real_sol[mi2] ); - if ( real_sol.size() == 4 && !(t < from || t > to) ) - { - if ( result.empty() || are_near(mindistsq1, mindistsq2) ) - { - result.push_back(t); - second_sol = true; - } - } - - // we need to test extreme points too - double dsq1 = distanceSq(p, pointAt(from)); - double dsq2 = distanceSq(p, pointAt(to)); - if ( second_sol ) - { - if ( mindistsq2 > dsq1 ) - { - result.clear(); - result.push_back(from); - mindistsq2 = dsq1; - } - else if ( are_near(mindistsq2, dsq) ) - { - result.push_back(from); - } - if ( mindistsq2 > dsq2 ) - { - result.clear(); - result.push_back(to); - } - else if ( are_near(mindistsq2, dsq2) ) - { - result.push_back(to); - } - - } - else - { - if ( result.empty() ) - { - if ( are_near(dsq1, dsq2) ) - { - result.push_back(from); - result.push_back(to); - } - else if ( dsq2 > dsq1 ) - { - result.push_back(from); - } - else - { - result.push_back(to); - } - } - } - - return result; + Ellipse e(center(X), center(Y), ray(X), ray(Y), _rot_angle); + Ellipse et = e.transformed(m); + Point inner_point = pointAt(0.5); + return et.arc( initialPoint() * m, + inner_point * m, + finalPoint() * m, + isSVGCompliant() ); } +Coord EllipticalArc::map_to_01(Coord angle) const +{ + return map_circular_arc_on_unit_interval(angle, initialAngle(), + finalAngle(), _sweep); +} } // end namespace Geom - /* Local Variables: mode:c++ @@ -928,4 +916,3 @@ allNearestPoints( Point const& p, double from, double to ) const */ // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 : - diff --git a/src/2geom/elliptical-arc.h b/src/2geom/elliptical-arc.h index 002735944..e1e757207 100644 --- a/src/2geom/elliptical-arc.h +++ b/src/2geom/elliptical-arc.h @@ -1,12 +1,14 @@ /** * \file - * \brief Elliptical Arc - implementation of the svg elliptical arc path element + * \brief Elliptical arc curve * + *//* * Authors: - * MenTaLguY - * Marco Cecchetti + * MenTaLguY + * Marco Cecchetti + * Krzysztof Kosiński * - * Copyright 2007-2008 authors + * 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 @@ -32,272 +34,234 @@ * the specific language governing rights and limitations. */ - - - #ifndef _2GEOM_ELLIPTICAL_ARC_H_ #define _2GEOM_ELLIPTICAL_ARC_H_ - -#include <2geom/curve.h> +#include #include <2geom/angle.h> -#include <2geom/utils.h> +#include <2geom/bezier-curve.h> +#include <2geom/curve.h> +#include <2geom/affine.h> #include <2geom/sbasis-curve.h> // for non-native methods - -#include - +#include <2geom/utils.h> namespace Geom { -class EllipticalArc : public Curve +class EllipticalArc : public Curve, public AngleInterval { - public: - EllipticalArc() - : m_initial_point(Point(0,0)), m_final_point(Point(0,0)), - m_rx(0), m_ry(0), m_rot_angle(0), - m_large_arc(true), m_sweep(true) - { - m_start_angle = m_end_angle = 0; - m_center = Point(0,0); - } - - EllipticalArc( Point _initial_point, double _rx, double _ry, - double _rot_angle, bool _large_arc, bool _sweep, - Point _final_point - ) - : m_initial_point(_initial_point), m_final_point(_final_point), - m_rx(_rx), m_ry(_ry), m_rot_angle(_rot_angle), - m_large_arc(_large_arc), m_sweep(_sweep) - { - calculate_center_and_extreme_angles(); - } - - void set( Point _initial_point, double _rx, double _ry, - double _rot_angle, bool _large_arc, bool _sweep, - Point _final_point - ) +public: + /** @brief Creates an arc with all variables set to zero, and both flags to true. */ + EllipticalArc() + : AngleInterval(0, 0, true) + , _initial_point(0,0) + , _final_point(0,0) + , _rays(0,0) + , _center(0,0) + , _rot_angle(0) + , _large_arc(true) + {} + /** @brief Create a new elliptical arc. + * @param ip Initial point of the arc + * @param rx First ray of the ellipse + * @param ry Second ray of the ellipse + * @param rot Angle of rotation of the X axis of the ellipse in radians + * @param large If true, the large arc is chosen (always >= 180 degrees), otherwise + * the smaller arc is chosen + * @param sweep If true, the clockwise arc is chosen, otherwise the counter-clockwise + * arc is chosen + * @param fp Final point of the arc */ + EllipticalArc( Point ip, Coord rx, Coord ry, + Coord rot_angle, bool large_arc, bool sweep, + Point fp + ) + : AngleInterval(0,0,sweep) + , _initial_point(ip) + , _final_point(fp) + , _rays(rx, ry) + , _rot_angle(rot_angle) + , _large_arc(large_arc) { - m_initial_point = _initial_point; - m_final_point = _final_point; - m_rx = _rx; - m_ry = _ry; - m_rot_angle = _rot_angle; - m_large_arc = _large_arc; - m_sweep = _sweep; - calculate_center_and_extreme_angles(); + _updateCenterAndAngles(false); } - Curve* duplicate() const - { - return new EllipticalArc(*this); - } - - double center(unsigned int i) const - { - return m_center[i]; + // methods new to EllipticalArc go here + + /// @name Retrieve and modify parameters + /// @{ + /** @brief Get the interval of angles the arc contains + * @return The interval between the final and initial angles of the arc */ + Interval angleInterval() const { return Interval(initialAngle(), finalAngle()); } + /** @brief Get a coordinate of the elliptical arc's center. + * @param d The dimension to retrieve + * @return The selected coordinate of the center */ + /** @brief Get the defining ellipse's rotation + * @return Angle between the +X ray of the ellipse and the +X axis */ + Angle rotationAngle() const { + return _rot_angle; } - - Point center() const + /** @brief Get one of the ellipse's rays + * @param d Dimension to retrieve + * @return The selected ray of the ellipse */ + Coord ray(Dim2 d) const { return _rays[d]; } + /** @brief Get both rays as a point + * @return Point with X equal to the X ray and Y to Y ray */ + Point rays() const { return _rays; } + /** @brief Whether the arc is larger than half an ellipse. + * @return True if the arc is larger than \f$\pi\f$, false otherwise */ + bool largeArc() const { return _large_arc; } + /** @brief Whether the arc turns clockwise + * @return True if the arc makes a clockwise turn when going from initial to final + * point, false otherwise */ + bool sweep() const { return _sweep; } + /** @brief Get the line segment connecting the arc's endpoints. + * @return A linear segment with initial and final point correspoding to those of the arc. */ + LineSegment chord() const { return LineSegment(_initial_point, _final_point); } + /** @brief Change the arc's parameters. */ + void set( Point const &ip, double rx, double ry, + double rot_angle, bool large_arc, bool sweep, + Point const &fp + ) { - return m_center; + _initial_point = ip; + _final_point = fp; + _rays[X] = rx; + _rays[Y] = ry; + _rot_angle = Angle(rot_angle); + _large_arc = large_arc; + _sweep = sweep; + _updateCenterAndAngles(isSVGCompliant()); } - - Point initialPoint() const - { - return m_initial_point; + /** @brief Change the initial and final point in one operation. + * This method exists because modifying any of the endpoints causes rather costly + * recalculations of the center and extreme angles. + * @param ip New initial point + * @param fp New final point */ + void setExtremes(Point const &ip, Point const &fp) { + _initial_point = ip; + _final_point = fp; + _updateCenterAndAngles(isSVGCompliant()); } - - Point finalPoint() const - { - return m_final_point; + /// @} + + /// @name Access computed parameters of the arc + /// @{ + Coord center(Dim2 d) const { return _center[d]; } + /** @brief Get the arc's center + * @return The arc's center, situated on the intersection of the ellipse's rays */ + Point center() const { return _center; } + /** @brief Get the extent of the arc + * @return The angle between the initial and final point, in arc's angular coordinates */ + Coord sweepAngle() const { + return extent(); } - - double start_angle() const - { - return m_start_angle; - } - - double end_angle() const - { - return m_end_angle; - } - - double ray(unsigned int i) const - { - return (i == 0) ? m_rx : m_ry; - } - - bool large_arc_flag() const - { - return m_large_arc; - } - - bool sweep_flag() const - { - return m_sweep; - } - - double rotation_angle() const - { - return m_rot_angle; - } - - void setInitial( const Point _point) - { - m_initial_point = _point; - calculate_center_and_extreme_angles(); + /// @} + + /// @name Angular evaluation + /// @{ + /** Check whether the arc contains the given angle + * @param t The angle to check + * @return True if the arc contains the angle, false otherwise */ + bool containsAngle(Coord angle) const; + /** @brief Evaluate the arc at the specified angular coordinate + * @param t Angle + * @return Point corresponding to the given angle */ + Point pointAtAngle(Coord t) const; + /** @brief Evaluate one of the arc's coordinates at the specified angle + * @param t Angle + * @param d The dimension to retrieve + * @return Selected coordinate of the arc at the specified angle */ + Coord valueAtAngle(Coord t, Dim2 d) const; + /** @brief Retrieve the unit circle transform. + * Each ellipse can be interpreted as a translated, scaled and rotate unit circle. + * This function returns the transform that maps the unit circle to the arc's ellipse. + * @return Transform from unit circle to the arc's ellipse */ + Affine unitCircleTransform() const; + /// @} + + /** @brief Check whether the arc adheres to SVG 1.1 implementation guidelines */ + virtual bool isSVGCompliant() const { return false; } + + std::pair subdivide(Coord t) const { + EllipticalArc* arc1 = static_cast(portion(0, t)); + EllipticalArc* arc2 = static_cast(portion(t, 1)); + assert( arc1 != NULL && arc2 != NULL); + std::pair arc_pair(*arc1, *arc2); + delete arc1; + delete arc2; + return arc_pair; } - void setFinal( const Point _point) - { - m_final_point = _point; - calculate_center_and_extreme_angles(); + // implementation of overloads goes here +#ifndef DOXYGEN_SHOULD_SKIP_THIS + virtual Point initialPoint() const { return _initial_point; } + virtual Point finalPoint() const { return _final_point; } + virtual Curve* duplicate() const { return new EllipticalArc(*this); } + virtual void setInitial(Point const &p) { + _initial_point = p; + _updateCenterAndAngles(isSVGCompliant()); } - - void setExtremes( const Point& _initial_point, const Point& _final_point ) - { - m_initial_point = _initial_point; - m_final_point = _final_point; - calculate_center_and_extreme_angles(); + virtual void setFinal(Point const &p) { + _final_point = p; + _updateCenterAndAngles(isSVGCompliant()); } - - bool isDegenerate() const - { + virtual bool isDegenerate() const { return ( are_near(ray(X), 0) || are_near(ray(Y), 0) ); } - - - virtual OptRect boundsFast() const - { + virtual Rect boundsFast() const { return boundsExact(); } - - virtual OptRect boundsExact() const; - + virtual Rect boundsExact() const; // TODO: native implementation of the following methods - virtual OptRect boundsLocal(OptInterval i, unsigned int deg) const - { + virtual OptRect boundsLocal(OptInterval const &i, unsigned int deg) const { return SBasisCurve(toSBasis()).boundsLocal(i, deg); } - - std::vector roots(double v, Dim2 d) const; - - std::vector - allNearestPoints( Point const& p, double from = 0, double to = 1 ) const; - - double nearestPoint( Point const& p, double from = 0, double to = 1 ) const - { - if ( are_near(ray(X), ray(Y)) && are_near(center(), p) ) - { - return from; - } - return allNearestPoints(p, from, to).front(); - } - - // TODO: native implementation of the following methods - int winding(Point p) const - { - return SBasisCurve(toSBasis()).winding(p); - } - - int degreesOfFreedom() const { return 7;} - - Curve *derivative() const; - - // TODO: native implementation of the following methods - Curve *transformed(Matrix const &m) const - { - return SBasisCurve(toSBasis()).transformed(m); - } - - std::vector pointAndDerivatives(Coord t, unsigned int n) const; - - D2 toSBasis() const; - - bool containsAngle(Coord angle) const; - - double valueAtAngle(Coord t, Dim2 d) const; - - Point pointAtAngle(Coord t) const - { - double sin_rot_angle = std::sin(rotation_angle()); - double cos_rot_angle = std::cos(rotation_angle()); - Matrix m( ray(X) * cos_rot_angle, ray(X) * sin_rot_angle, - -ray(Y) * sin_rot_angle, ray(Y) * cos_rot_angle, - center(X), center(Y) ); - Point p( std::cos(t), std::sin(t) ); - return p * m; + virtual std::vector roots(double v, Dim2 d) const; +#ifdef HAVE_GSL + virtual std::vector allNearestPoints( Point const& p, double from = 0, double to = 1 ) const; +#endif + virtual double nearestPoint( Point const& p, double from = 0, double to = 1 ) const { + if ( are_near(ray(X), ray(Y)) && are_near(center(), p) ) { + return from; + } + return allNearestPoints(p, from, to).front(); } - - double valueAt(Coord t, Dim2 d) const - { - Coord tt = map_to_02PI(t); - return valueAtAngle(tt, d); + virtual int degreesOfFreedom() const { return 7; } + virtual Curve *derivative() const; + virtual Curve *transformed(Affine const &m) const; + + /** + * The size of the returned vector equals n+1. + */ + virtual std::vector pointAndDerivatives(Coord t, unsigned int n) const; + + virtual D2 toSBasis() const; + virtual double valueAt(Coord t, Dim2 d) const { + return valueAtAngle(angleAt(t), d); } - - Point pointAt(Coord t) const - { - Coord tt = map_to_02PI(t); - return pointAtAngle(tt); + virtual Point pointAt(Coord t) const { + return pointAtAngle(angleAt(t)); } + virtual Curve* portion(double f, double t) const; + virtual Curve* reverse() const; +#endif - std::pair - subdivide(Coord t) const - { - EllipticalArc* arc1 = static_cast(portion(0, t)); - EllipticalArc* arc2 = static_cast(portion(t, 1)); - assert( arc1 != NULL && arc2 != NULL); - std::pair arc_pair(*arc1, *arc2); - delete arc1; - delete arc2; - return arc_pair; - } +protected: + void _updateCenterAndAngles(bool svg); - Curve* portion(double f, double t) const; - - // the arc is the same but traversed in the opposite direction - Curve* reverse() const - { - EllipticalArc* rarc = new EllipticalArc( *this ); - rarc->m_sweep = !m_sweep; - rarc->m_initial_point = m_final_point; - rarc->m_final_point = m_initial_point; - rarc->m_start_angle = m_end_angle; - rarc->m_end_angle = m_start_angle; - return rarc; - } + Point _initial_point, _final_point; + Point _rays, _center; + Angle _rot_angle; + bool _large_arc; - double sweep_angle() const - { - Coord d = end_angle() - start_angle(); - if ( !sweep_flag() ) d = -d; - if ( d < 0 ) - d += 2*M_PI; - return d; - } - - private: - Coord map_to_02PI(Coord t) const; +private: Coord map_to_01(Coord angle) const; - void calculate_center_and_extreme_angles(); - private: - Point m_initial_point, m_final_point; - double m_rx, m_ry, m_rot_angle; - bool m_large_arc, m_sweep; - double m_start_angle, m_end_angle; - Point m_center; - }; // end class EllipticalArc - } // end namespace Geom #endif // _2GEOM_ELLIPTICAL_ARC_H_ - - - /* Local Variables: mode:c++ diff --git a/src/2geom/exception.h b/src/2geom/exception.h index fd92ca5e1..12736d639 100644 --- a/src/2geom/exception.h +++ b/src/2geom/exception.h @@ -1,11 +1,17 @@ -#ifndef LIB2GEOM_EXCEPTION_HEADER -#define LIB2GEOM_EXCEPTION_HEADER - /** * \file * \brief Defines the different types of exceptions that 2geom can throw. * - * Copyright 2007 Johan Engelen + * There are two main exception classes: LogicalError and RangeError. + * Logical errors are 2geom faults/bugs; RangeErrors are 'user' faults, + * e.g. invalid arguments to lib2geom methods. + * This way, the 'user' can distinguish between groups of exceptions + * ('user' is the coder that uses lib2geom) + * + * Several macro's are defined for easily throwing exceptions + * (e.g. THROW_CONTINUITYERROR). + */ +/* Copyright 2007 Johan Engelen * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -32,13 +38,18 @@ * */ +#ifndef LIB2GEOM_EXCEPTION_HEADER +#define LIB2GEOM_EXCEPTION_HEADER + #include #include #include namespace Geom { -// Base exception class, all 2geom exceptions should be derived from this one. +/** + * Base exception class, all 2geom exceptions should be derived from this one. + */ class Exception : public std::exception { public: Exception(const char * message, const char *file, const int line) { @@ -58,10 +69,7 @@ protected: #define THROW_EXCEPTION(message) throw(Geom::Exception(message, __FILE__, __LINE__)) //----------------------------------------------------------------------- -// Two main exception classes: LogicalError and RangeError. -// Logical errors are 2geom faults/bugs, RangeErrors are 'user' faults. -// This way, the 'user' can distinguish between groups of exceptions -// ('user' is the coder that uses lib2geom) + class LogicalError : public Exception { public: LogicalError(const char * message, const char *file, const int line) diff --git a/src/2geom/forward.h b/src/2geom/forward.h index adc099379..93a762022 100644 --- a/src/2geom/forward.h +++ b/src/2geom/forward.h @@ -1,11 +1,12 @@ /** * \file * \brief Contains forward declarations of 2geom types - * + *//* * Authors: * Johan Engelen + * Krzysztof Kosiński * - * Copyright 2008 authors + * Copyright (C) 2008-2010 Authors * * This library is free software; you can redistribute it and/or * modify it either under the terms of the GNU Lesser General Public @@ -38,21 +39,34 @@ namespace Geom { +// basic types +typedef double Coord; +class Point; +class Interval; +class OptInterval; +class Line; +class Ray; + +// fragments +class Linear; class Bezier; -template class BezierCurve; -template<> class BezierCurve<0>; -typedef BezierCurve<2> QuadraticBezier; -typedef BezierCurve<1> LineSegment; -typedef BezierCurve<3> CubicBezier; -class EllipticalArc; -class SVGEllipticalArc; +class SBasis; +// curves +class Curve; +class SBasisCurve; +class BezierCurve; class HLineSegment; class VLineSegment; +class LineSegment; +class EllipticalArc; +class SVGEllipticalArc; -typedef double Coord; -class Point; +// paths and path sequences +class Path; +typedef std::vector PathVector; +// errors class Exception; class LogicalError; class RangeError; @@ -61,32 +75,27 @@ class InvariantsViolation; class NotInvertible; class ContinuityError; -class Interval; -class OptInterval; -class Linear; -class Hat; -class Tri; - -class Matrix; +// transforms +class Affine; class Translate; class Rotate; class Scale; +class HShear; +class VShear; -class Curve; -class Path; -typedef std::vector PathVector; - -template class D2; +// templates +template class D2; template class Piecewise; -class SBasis; -class SBasisCurve; typedef D2 Rect; class OptRect; class Shape; class Region; +class Hat; +class Tri; +// misc class SVGPathSink; template class SVGPathGenerator; diff --git a/src/2geom/hvlinesegment.h b/src/2geom/hvlinesegment.h index 6a9edbcea..9419be8f6 100644 --- a/src/2geom/hvlinesegment.h +++ b/src/2geom/hvlinesegment.h @@ -39,127 +39,37 @@ namespace Geom { -class HLineSegment : public Curve +template +class AxisLineSegment : public LineSegment { - public: - HLineSegment() - {} - - HLineSegment(Coord _x0, Coord _x1, Coord _y) - : m_line_seg(Point(_x0, _y), Point(_x1, _y)) - { - } - - HLineSegment(Point const& _p, double _length) - : m_line_seg(_p, Point(_p[X] + _length, _p[Y])) - { - } - - HLineSegment(Point const& _p0, Point const& _p1) - : m_line_seg(_p0, _p1) - { - if ( _p0[Y] != _p1[Y] ) - { - THROW_RANGEERROR("HLineSegment::HLineSegment passed points should " - "have the same Y value"); - } - } - - Curve* duplicate() const - { - return new HLineSegment(*this); - } - - bool isDegenerate() const - { - return m_line_seg.isDegenerate(); - } - - Point initialPoint() const - { - return m_line_seg.initialPoint(); - } - - Point finalPoint() const - { - return m_line_seg.finalPoint(); - } - - Coord getY() - { - return initialPoint()[Y]; - } - - void setInitial(Point _p) - { - m_line_seg.setInitial( Point(_p[X], initialPoint()[Y]) ); - } - - void setFinal(Point _p) - { - m_line_seg.setFinal( Point(_p[X], finalPoint()[Y]) ); - } - - void setX0(Coord _x) - { - m_line_seg.setInitial( Point(_x, initialPoint()[Y]) ); - } - - void setX1(Coord _x) - { - m_line_seg.setFinal( Point(_x, finalPoint()[Y]) ); - } - - void setY(Coord _y) - { - m_line_seg.setInitial( Point(initialPoint()[X], _y) ); - m_line_seg.setFinal( Point(finalPoint()[X], _y) ); - } - - virtual OptRect boundsFast() const - { - return boundsExact(); - } - - virtual OptRect boundsExact() const - { - return Rect( initialPoint(), finalPoint() ); - } - - virtual OptRect boundsLocal(OptInterval i, unsigned deg) const - { - return m_line_seg.boundsLocal(i, deg); - } - - int winding(Point p) const - { - return m_line_seg.winding(p); - } - - int degreesOfFreedom() const { return 3;} - - std::vector - roots(double v, Dim2 d) const - { - if (d < 0 || d > 1) - { - THROW_RANGEERROR("dimension argument out of range"); - } - std::vector result; - if (d == X) - { - if ( v >= initialPoint()[X] && v <= finalPoint()[X] ) - { - double t = 0; +public: + static const Dim2 other_axis = static_cast((axis + 1) % 2); + virtual void setInitial(Point const &p) { + Point f = finalPoint(); + f[axis] = p[axis]; + LineSegment::setInitial(p); + LineSegment::setFinal(f); + } + virtual void setFinal(Point const &p) { + Point i = initialPoint(); + i[axis] = p[axis]; + LineSegment::setFinal(p); + LineSegment::setInitial(i); + } + virtual Rect boundsFast() const { return boundsExact(); } + virtual Rect boundsExact() const { Rect r(initialPoint(), finalPoint()); return r; } + virtual int degreesOfFreedom() const { return 3; } + virtual std::vector roots(Coord v, Dim2 d) const { + std::vector result; + if (d == axis) { + if ( v >= initialPoint()[axis] && v <= finalPoint()[axis] ) { + Coord t = 0; if (!isDegenerate()) - t = (v - initialPoint()[X]) / (finalPoint()[X] - initialPoint()[X]); + t = (v - initialPoint()[axis]) / (finalPoint()[axis] - initialPoint()[axis]); result.push_back(t); } - } - else - { - if (v == initialPoint()[Y]) - { + } else { + if (v == initialPoint()[other_axis]) { if (!isDegenerate()) THROW_INFINITESOLUTIONS(0); result.push_back(0); @@ -167,270 +77,161 @@ class HLineSegment : public Curve } return result; } - - double nearestPoint( Point const& p, double from = 0, double to = 1 ) const - { + virtual Coord nearestPoint( Point const &p, Coord from = 0, Coord to = 1 ) const { if ( from > to ) std::swap(from, to); - double xfrom = pointAt(from)[X]; - double xto = pointAt(to)[X]; - if ( xfrom > xto ) - { + Coord xfrom = valueAt(from, axis); + Coord xto = valueAt(to, axis); + if ( xfrom > xto ) { std::swap(xfrom, xto); std::swap(from, to); } - if ( p[X] > xfrom && p[X] < xto ) - { - return (p[X] - initialPoint()[X]) / (finalPoint()[X] - initialPoint()[X]); + if ( p[axis] > xfrom && p[axis] < xto ) { + return (p[axis] - initialPoint()[axis]) / (finalPoint()[axis] - initialPoint()[axis]); } else if ( p[X] <= xfrom ) return from; else return to; } - - std::pair subdivide(Coord t) const - { - std::pair result; - Point p = pointAt(t); - result.first.setInitial(initialPoint()); - result.first.setFinal(p); - result.second.setInitial(p); - result.second.setFinal(finalPoint()); - return result; - } - - Curve* portion(double f, double t) const - { - Point ip = pointAt(f); - Point ep = pointAt(t); - return new HLineSegment(ip[X], ep[X], ip[Y]); - } - - Curve* reverse() const - { - return - new HLineSegment(finalPoint()[X], initialPoint()[X], initialPoint()[Y]); - } - - Curve* transformed(Matrix const & m) const - { - Point ip = initialPoint() * m; - Point ep = finalPoint() * m; - if (ip[Y] == ep[Y]) { - return new HLineSegment(ip[X], ep[X], ip[Y]); - } else { - return new LineSegment(ip, ep); - } - } - - Curve* derivative() const - { - double x = finalPoint()[X] - initialPoint()[X]; - return new HLineSegment(x, x, 0); - } - - Point pointAt(double t) const - { + virtual Point pointAt(Coord t) const { if ( t < 0 || t > 1 ) - THROW_RANGEERROR("domain parameter out of range"); - double x = initialPoint()[X] + t * (finalPoint()[X] - initialPoint()[X]); - return Point(x, initialPoint()[Y]); + THROW_RANGEERROR("HLineSegment: Time value out of range"); + Coord x = initialPoint()[axis] + t * (finalPoint()[axis] - initialPoint()[axis]); + Point ret(x, initialPoint()[other_axis]); + return ret; } - - double valueAt(double t, Dim2 d) const - { - if (d < 0 || d > 1) - { - THROW_RANGEERROR("dimension argument out of range"); - } + virtual Coord valueAt(Coord t, Dim2 d) const { if ( t < 0 || t > 1 ) - THROW_RANGEERROR("domain parameter out of range"); - - if (d == Y) return initialPoint()[Y]; - - return initialPoint()[X] + t * (finalPoint()[X] - initialPoint()[X]); + THROW_RANGEERROR("HLineSegment: Time value out of range"); + if (d != axis) return initialPoint()[other_axis]; + return initialPoint()[axis] + t * (finalPoint()[axis] - initialPoint()[axis]); } - std::vector pointAndDerivatives(Coord t, unsigned n) const - { + /** + * The size of the returned vector equals n+1. + */ + virtual std::vector pointAndDerivatives(Coord t, unsigned n) const { std::vector result; result.push_back(pointAt(t)); - if (n > 0) - { - double x = finalPoint()[X] - initialPoint()[X]; + if (n > 0) { + Coord x = finalPoint()[axis] - initialPoint()[axis]; result.push_back( Point(x, 0) ); } - if (n > 1) - { + if (n > 1) { /* higher order derivatives are zero, * so the other n-1 vector elements are (0,0) */ result.insert( result.end(), n-1, Point(0, 0) ); } return result; } +protected: + AxisLineSegment(Point const &p0, Point const &p1) : LineSegment(p0, p1) {} + AxisLineSegment() {} +}; - D2 toSBasis() const - { - return m_line_seg.toSBasis(); - } - - private: - LineSegment m_line_seg; - -}; // end class HLineSegment - - -class VLineSegment : public Curve +class HLineSegment : public AxisLineSegment { - public: - VLineSegment() +public: + HLineSegment() {} + HLineSegment(Coord x0, Coord x1, Coord y) + : AxisLineSegment(Point(x0, y), Point(x1, y)) {} - VLineSegment(Coord _x, Coord _y0, Coord _y1) - : m_line_seg(Point(_x, _y0), Point(_x, _y1)) - { - } - - VLineSegment(Point const& _p, double _length) - : m_line_seg(_p, Point(_p[X], _p[Y] + _length)) - { - } + HLineSegment(Point const& p, Coord len) + : AxisLineSegment(p, Point(p[X] + len, p[Y])) + {} - VLineSegment(Point const& _p0, Point const& _p1) - : m_line_seg(_p0, _p1) + HLineSegment(Point const& p0, Point const& p1) + : AxisLineSegment(p0, p1) { - if ( _p0[X] != _p1[X] ) - { - THROW_RANGEERROR("VLineSegment::VLineSegment passed points should " - "have the same X value"); + if ( p0[Y] != p1[Y] ) { + THROW_RANGEERROR("HLineSegment::HLineSegment passed points should " + "have the same Y value"); } } - Curve* duplicate() const - { - return new VLineSegment(*this); + Coord getY() { return initialPoint()[Y]; } + void setInitialX(Coord x) { + LineSegment::setInitial(Point(x, initialPoint()[Y])); } - - bool isDegenerate() const - { - return m_line_seg.isDegenerate(); + void setFinalX(Coord x) { + LineSegment::setFinal(Point(x, initialPoint()[Y])); } - - Point initialPoint() const - { - return m_line_seg.initialPoint(); - } - - Point finalPoint() const - { - return m_line_seg.finalPoint(); + void setY(Coord y) { + LineSegment::setInitial( Point(initialPoint()[X], y) ); + LineSegment::setFinal( Point(finalPoint()[X], y) ); } - - Coord getX() - { - return initialPoint()[X]; + std::pair subdivide(Coord t) const { + std::pair result; + Point p = pointAt(t); + result.first.setInitial(initialPoint()); + result.first.setFinal(p); + result.second.setInitial(p); + result.second.setFinal(finalPoint()); + return result; } - void setInitial(Point _p) - { - m_line_seg.setInitial( Point(initialPoint()[X], _p[Y]) ); + virtual Curve* duplicate() const { return new HLineSegment(*this); } + virtual Curve *portion(Coord f, Coord t) const { + Point ip = pointAt(f); + Point ep = pointAt(t); + return new HLineSegment(ip[X], ep[X], ip[Y]); } - - void setFinal(Point _p) - { - m_line_seg.setFinal( Point(finalPoint()[X], _p[Y]) ); + virtual Curve *reverse() const { + Point ip = initialPoint(); + return new HLineSegment(finalPoint()[X], ip[X], ip[Y]); } - - void setY0(Coord _y) - { - m_line_seg.setInitial( Point(initialPoint()[X], _y) ); + virtual Curve *transformed(Affine const & m) const { + Point ip = initialPoint() * m; + Point ep = finalPoint() * m; + // cannot afford to lose precision here since it can lead to discontinuous paths + if (m.isZoom(0)) { + return new HLineSegment(ip[X], ep[X], ip[Y]); + } else { + return new LineSegment(ip, ep); + } } - - void setY1(Coord _y) - { - m_line_seg.setFinal( Point(finalPoint()[Y], _y) ); + virtual Curve *derivative() const { + Coord x = finalPoint()[X] - initialPoint()[X]; + return new HLineSegment(x, x, 0); } +}; // end class HLineSegment - void setX(Coord _x) - { - m_line_seg.setInitial( Point(_x, initialPoint()[Y]) ); - m_line_seg.setFinal( Point(_x, finalPoint()[Y]) ); - } - virtual OptRect boundsFast() const - { - return boundsExact(); - } +class VLineSegment : public AxisLineSegment +{ +public: + VLineSegment() {} - virtual OptRect boundsExact() const - { - return Rect( initialPoint(), finalPoint() ); - } + VLineSegment(Coord x, Coord y0, Coord y1) + : AxisLineSegment(Point(x, y0), Point(x, y1)) + {} - virtual OptRect boundsLocal(OptInterval i, unsigned deg) const - { - return m_line_seg.boundsLocal(i, deg); - } + VLineSegment(Point const& _p, Coord _length) + : AxisLineSegment(_p, Point(_p[X], _p[Y] + _length)) + {} - int winding(Point p) const + VLineSegment(Point const& _p0, Point const& _p1) + : AxisLineSegment(_p0, _p1) { - return m_line_seg.winding(p); + if ( _p0[X] != _p1[X] ) { + THROW_RANGEERROR("VLineSegment::VLineSegment passed points should " + "have the same X value"); + } } - - int degreesOfFreedom() const { return 3;} - std::vector - roots(double v, Dim2 d) const - { - if (d < 0 || d > 1) - { - THROW_RANGEERROR("dimension argument out of range"); - } - std::vector result; - if (d == Y) - { - if ( v >= initialPoint()[Y] && v <= finalPoint()[Y] ) - { - double t = 0; - if (!isDegenerate()) - t = (v - initialPoint()[Y]) / (finalPoint()[Y] - initialPoint()[Y]); - result.push_back(t); - } - } - else - { - if (v == initialPoint()[X]) - { - if (!isDegenerate()) - THROW_INFINITESOLUTIONS(0); - result.push_back(0); - } - } - return result; + Coord getX() { return initialPoint()[X]; } + void setInitialY(Coord _y) { + LineSegment::setInitial( Point(initialPoint()[X], _y) ); } - - double nearestPoint( Point const& p, double from = 0, double to = 1 ) const - { - if ( from > to ) std::swap(from, to); - double yfrom = pointAt(from)[Y]; - double yto = pointAt(to)[Y]; - if (yfrom > yto) - { - std::swap(yfrom, yto); - std::swap(from, to); - } - if ( p[Y] > yfrom && p[Y] < yto ) - { - return (p[Y] - initialPoint()[Y]) / (finalPoint()[Y] - initialPoint()[Y]); - } - else if ( p[Y] <= yfrom ) - return from; - else - return to; + void setFinalY(Coord _y) { + LineSegment::setFinal( Point(finalPoint()[Y], _y) ); } - - std::pair subdivide(Coord t) const - { + void setX(Coord _x) { + LineSegment::setInitial( Point(_x, initialPoint()[Y]) ); + LineSegment::setFinal( Point(_x, finalPoint()[Y]) ); + } + std::pair subdivide(Coord t) const { std::pair result; Point p = pointAt(t); result.first.setInitial(initialPoint()); @@ -440,88 +241,31 @@ class VLineSegment : public Curve return result; } - Curve* portion(double f, double t) const - { + virtual Curve *duplicate() const { return new VLineSegment(*this); } + virtual Curve *portion(Coord f, Coord t) const { Point ip = pointAt(f); - Point ep = pointAt(t); - return new VLineSegment(ip[X], ip[Y], ep[Y]); + Coord epy = valueAt(t, Y); + return new VLineSegment(ip[X], ip[Y], epy); } - - Curve* reverse() const - { - return - new VLineSegment(initialPoint()[X], finalPoint()[Y], initialPoint()[Y]); + virtual Curve *reverse() const { + Point ip = initialPoint(); + return new VLineSegment(ip[X], finalPoint()[Y], ip[Y]); } - - Curve* transformed(Matrix const & m) const - { + virtual Curve *transformed(Affine const & m) const { Point ip = initialPoint() * m; Point ep = finalPoint() * m; - if (ip[X] == ep[X]) { + if (m.isZoom()) { return new VLineSegment(ip[X], ip[Y], ep[Y]); } else { return new LineSegment(ip, ep); } } - - Curve* derivative() const - { - double y = finalPoint()[Y] - initialPoint()[Y]; + virtual Curve* derivative() const { + Coord y = finalPoint()[Y] - initialPoint()[Y]; return new VLineSegment(0, y, y); } - - Point pointAt(double t) const - { - if ( t < 0 || t > 1 ) - THROW_RANGEERROR("domain parameter out of range"); - double y = initialPoint()[Y] + t * (finalPoint()[Y] - initialPoint()[Y]); - return Point(initialPoint()[X], y); - } - - double valueAt(double t, Dim2 d) const - { - if (d < 0 || d > 1) - { - THROW_RANGEERROR("dimension argument out of range"); - } - if ( t < 0 || t > 1 ) - THROW_RANGEERROR("domain parameter out of range"); - - if (d == X) return initialPoint()[X]; - - return initialPoint()[Y] + t * (finalPoint()[Y] - initialPoint()[Y]); - } - - std::vector pointAndDerivatives(Coord t, unsigned n) const - { - std::vector result; - result.push_back(pointAt(t)); - if (n > 0) - { - double y = finalPoint()[Y] - initialPoint()[Y]; - result.push_back( Point(0, y) ); - } - if (n > 1) - { - /* higher order derivatives are zero, - * so the other n-1 vector elements are (0,0) */ - result.insert( result.end(), n-1, Point(0, 0) ); - } - return result; - } - - D2 toSBasis() const - { - return m_line_seg.toSBasis(); - } - - private: - LineSegment m_line_seg; - }; // end class VLineSegment - - } // end namespace Geom diff --git a/src/2geom/interval.h b/src/2geom/interval.h index 68a406318..a790a6c3b 100644 --- a/src/2geom/interval.h +++ b/src/2geom/interval.h @@ -1,7 +1,7 @@ /** * \file * \brief Simple closed interval class - * + *//* * Copyright 2007 Michael Sloan * * Original Rect/Range code by: @@ -34,216 +34,295 @@ * the specific language governing rights and limitations. * */ -#ifndef SEEN_INTERVAL_H -#define SEEN_INTERVAL_H +#ifndef LIB2GEOM_SEEN_INTERVAL_H +#define LIB2GEOM_SEEN_INTERVAL_H #include +#include +#include +#include #include <2geom/coord.h> - -#include +#include <2geom/isnan.h> namespace Geom { -class Interval; +class OptInterval; /** - * \brief This class represents a range of numbers that is never empty. + * @brief Range of 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. * - * The endpoints are included in the range. + * @ingroup Primitives */ -class Interval { +class Interval + : boost::equality_comparable< Interval + , boost::additive< Interval + , boost::multipliable< Interval + , boost::arithmetic< Interval, Coord + , boost::orable< Interval + > > > > > +{ private: + /// @invariant _b[0] <= _b[1] Coord _b[2]; public: - /// The default constructor creates an interval [0,0] DO NOT RELY ON THIS, BEST NOT TO USE THIS CONSTRUCTOR + /// @name Create intervals. + /// @{ + /** @brief Create an interval that contains only zero. */ explicit Interval() { _b[0] = 0; _b[1] = 0; } + /** @brief Create an interval that contains a single point. */ explicit Interval(Coord u) { _b[0] = _b[1] = u; } - /* When creating an Interval using the constructor specifying the exact range, the created interval - * will be [u,v] when u<=v ; and will be [v,u] when v < u !!! - */ + /** @brief Create an interval that contains all points between @c u and @c v. */ Interval(Coord u, Coord v) { - if(u < v) { + if (u <= v) { _b[0] = u; _b[1] = v; } else { _b[0] = v; _b[1] = u; } } - - double operator[](unsigned i) const { - assert(i < 2); - return _b[i]; - } - inline double& operator[](unsigned i) { return _b[i]; } //Trust the user... - - inline Coord min() const { return _b[0]; } - inline Coord max() const { return _b[1]; } - inline Coord extent() const { return _b[1] - _b[0]; } - inline Coord middle() const { return (_b[1] + _b[0]) * 0.5; } - -// inline bool isEmpty() const { return _b[0] > _b[1]; } - inline bool isSingular() const { return _b[0] == _b[1]; } - inline bool contains(Coord val) const { return _b[0] <= val && val <= _b[1]; } - bool contains(const Interval & val) const { return _b[0] <= val._b[0] && val._b[1] <= _b[1]; } - bool intersects(const Interval & val) const { - return contains(val._b[0]) || contains(val._b[1]) || val.contains(*this); - } - - inline bool operator==(Interval other) const { return _b[0] == other._b[0] && _b[1] == other._b[1]; } - inline bool operator!=(Interval 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; - inline Interval operator+(Coord amnt) { - return Interval(_b[0] + amnt, _b[1] + amnt); - } - inline Interval operator-(Coord amnt) { - return Interval(_b[0] - amnt, _b[1] - amnt); + + /** @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 Coord. The given range + * must not be empty. For potentially empty ranges, see OptInterval. + * @param start Beginning of the range + * @param end End of the range + * @return Interval that contains all values from [start, end). */ + template + static Interval from_range(InputIterator start, InputIterator end) { + assert(start != end); + Interval result(*start++); + for (; start != end; ++start) result.expandTo(*start); + return result; } - inline Interval operator+=(Coord amnt) { - _b[0] += amnt; _b[1] += amnt; - return *this; + /** @brief Create an interval from a C-style array of values it should contain. */ + static Interval from_array(Coord const *c, unsigned n) { + Interval result = from_range(c, c+n); + return result; } - inline Interval operator-=(Coord amnt) { - _b[0] -= amnt; _b[1] -= amnt; - return *this; + /// @} + + /// @name Inspect endpoints. + /// @{ + Coord operator[](unsigned i) const { return _b[i]; } + 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]); } - - //IMPL: ScalableConcept - inline Interval operator-() const { return Interval(*this); } - inline Interval operator*(Coord s) const { return Interval(_b[0]*s, _b[1]*s); } - inline Interval operator/(Coord s) const { return Interval(_b[0]/s, _b[1]/s); } - Interval operator*=(Coord s) { - if(s < 0) { - Coord temp = _b[0]; - _b[0] = _b[1]*s; - _b[1] = temp*s; - } else { - _b[0] *= s; - _b[1] *= s; - } - return *this; + /// @} + + /// @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]; } + /** @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); } - Interval operator/=(Coord s) { - //TODO: what about s=0? - if(s < 0) { - Coord temp = _b[0]; - _b[0] = _b[1]/s; - _b[1] = temp/s; - } else { - _b[0] /= s; - _b[1] /= s; - } - return *this; + /** @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? - //TODO: Evaluate if wrap behaviour is proper. - //If val > max, then rather than becoming a min==max range, it 'wraps' over + /** @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]; - _b[1] = val; + _b[0] = _b[1] = val; } else { _b[0] = val; } } - //If val < min, then rather than becoming a min==max range, it 'wraps' over + /** @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]; - _b[0] = val; + _b[1] = _b[0] = val; } else { _b[1] = val; } } - - inline void extendTo(Coord 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 } - - static Interval fromArray(const Coord* c, int n) { - assert(n > 0); - Interval result(c[0]); - for(int i = 1; i < n; i++) result.extendTo(c[i]); - return result; - } - - /** When this would create an empty interval, the interval will be the centerpoint of the old range only. - */ - inline void expandBy(double amnt) { - _b[0] -= amnt; - _b[1] += amnt; + /** @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 + * amount * 2. 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; } } - - inline void unionWith(const Interval & a) { + /** @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]; } -}; - -//IMPL: AddableConcept -inline Interval operator+(const Interval & a, const Interval & b) { - return Interval(a.min() + b.min(), a.max() + b.max()); -} -inline Interval operator-(const Interval & a, const Interval & b) { - return Interval(a.min() - b.max(), a.max() - b.min()); -} -inline Interval operator+=(Interval & a, const Interval & b) { a = a + b; return a; } -inline Interval operator-=(Interval & a, const Interval & b) { a = a - b; return a; } - -//There might be impls of this based off sign checks -inline Interval operator*(const Interval & a, const Interval & b) { - Interval res(a.min() * b.min()); - res.extendTo(a.min() * b.max()); - res.extendTo(a.max() * b.min()); - res.extendTo(a.max() * b.max()); - return res; -} -inline Interval operator*=(Interval & a, const Interval & b) { a = a * b; return a; } + /// @} -/* reinstate if useful (doesn't do the proper thing for 0 inclusion) -inline Interval operator/(const Interval & a, const Interval & b) { - Interval res(a.min() / b.min()); - res.extendTo(a.min() / b.max()); - res.extendTo(a.max() / b.min()); - res.extendTo(a.max() / b.max()); - return res; -} -inline Interval operator/=(Interval & a, const Interval & b) { a = a / b; return a; } -*/ + /// @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; + } + + // 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; + _b[1] *= s; + if(s < 0) std::swap(_b[0], _b[1]); + return *this; + } + /** @brief Scale an interval by the inverse of the specified value */ + Interval &operator/=(Coord s) { + _b[0] /= s; + _b[1] /= s; + 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: + * \f$S = \{x \in A, y \in B: x * y\}\f$ */ + Interval &operator*=(Interval const &o) { + // TODO implement properly + Coord mn = min(), mx = max(); + expandTo(mn * o.min()); + expandTo(mn * o.max()); + expandTo(mx * o.min()); + 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; + } + /// @} +}; -// 'union' conflicts with C keyword -inline Interval unify(const Interval & a, const Interval & b) { - return Interval(std::min(a.min(), b.min()), - std::max(a.max(), b.max())); +/** @brief Union two intervals + * @relates Interval */ +inline Interval unify(Interval const &a, Interval const &b) { + return a | b; } /** - * \brief OptInterval is an Interval that can be empty. + * @brief A range of numbers that can be empty. + * @ingroup Primitives */ -class OptInterval : public boost::optional { +class OptInterval + : public boost::optional + , boost::orable< OptInterval + , boost::andable< OptInterval + > > +{ public: + /// @name Create optionally empty intervals. + /// @{ + /** @brief Create an empty interval. */ OptInterval() : boost::optional() {}; + /** @brief Wrap an existing interval. */ OptInterval(Interval const &a) : boost::optional(a) {}; + /** @brief Create an interval containing a single point. */ OptInterval(Coord u) : boost::optional(Interval(u)) {}; + /** @brief Create an interval containing a range of numbers. */ OptInterval(Coord u, Coord v) : boost::optional(Interval(u,v)) {}; - /** - * Check whether this OptInterval is empty or not. - */ - inline bool isEmpty() { return (*this == false); }; - - /** - * If \c this is empty, copy argument \c a. Otherwise, union with it (and do nothing when \c a is empty) - */ - inline void unionWith(const OptInterval & a) { + /** @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 + static OptInterval from_range(InputIterator start, InputIterator end) { + if (start == end) { + OptInterval ret; + return ret; + } + OptInterval ret(Interval::from_range(start, end)); + 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); @@ -252,14 +331,41 @@ public: } } } + 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*>(this)) = boost::none; + } + OptInterval &operator|=(OptInterval const &o) { + unionWith(o); + return *this; + } + OptInterval &operator&=(OptInterval const &o) { + intersectWith(o); + return *this; + } }; -inline OptInterval intersect(const Interval & a, const Interval & b) { - Coord u = std::max(a.min(), b.min()), - v = std::min(a.max(), b.max()); - //technically >= might be incorrect, but singulars suck - return u > v ? OptInterval() - : OptInterval(Interval(u, v)); +/** @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 diff --git a/src/2geom/line.cpp b/src/2geom/line.cpp index a91ff03a3..5ef8dfddc 100644 --- a/src/2geom/line.cpp +++ b/src/2geom/line.cpp @@ -37,6 +37,90 @@ namespace Geom { +/** + * @class Line + * @brief Infinite line on a plane. + * + * Every line in 2Geom has a special point on it, called the origin. The direction of the line + * is stored as a unit vector (versor). This way a line can be interpreted as a function + * \f$ f: (-\infty, \infty) \to \mathbb{R}^2\f$. Zero corresponds to the origin point, + * positive values to the points in the direction of the unit vector, and negative values + * to points in the opposite direction. + * + * @ingroup Primitives + */ + +/** @brief Set the line by solving the line equation. + * A line is a set of points that satisfies the line equation + * \f$Ax + By + C = 0\f$. This function changes the line so that its points + * satisfy the line equation with the given coefficients. */ +void Line::setCoefficients (double a, double b, double c) { + if (a == 0 && b == 0) { + if (c != 0) { + THROW_LOGICALERROR("the passed coefficients gives the empty set"); + } + m_versor = Point(0,0); + m_origin = Point(0,0); + } else { + double l = hypot(a,b); + a /= l; + b /= l; + c /= l; + Point N(a, b); + m_versor = N.ccw(); + m_origin = -c * N; + } +} + +/** @brief Get the line equation coefficients of this line. + * @return Vector with three values corresponding to the A, B and C + * coefficients of the line equation for this line. */ +std::vector Line::coefficients() const { + std::vector coeff; + coeff.reserve(3); + Point N = versor().cw(); + coeff.push_back (N[X]); + coeff.push_back (N[Y]); + double d = - dot (N, origin()); + coeff.push_back (d); + return coeff; +} + +/** @brief Find intersection with an axis-aligned line. + * @param v Coordinate of the axis-aligned line + * @param d Which axis the coordinate is on. X means a vertical line, Y means a horizontal line. + * @return Time values at which this line intersects the query line. */ +std::vector Line::roots(Coord v, Dim2 d) const { + if (d < 0 || d > 1) + THROW_RANGEERROR("Line::roots, dimension argument out of range"); + std::vector result; + if ( m_versor[d] != 0 ) + { + result.push_back( (v - m_origin[d]) / m_versor[d] ); + } + // TODO: else ? + return result; +} + +/** @brief Get a time value corresponding to a point. + * @param p Point on the line. If the point is not on the line, + * the returned value will be meaningless. + * @return Time value t such that \f$f(t) = p\f$. + * @see timeAtProjection */ +Coord Line::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; +} + namespace detail { @@ -55,18 +139,18 @@ OptCrossing intersection_impl(Point const& V1, Point const O1, Crossing c; c.ta = detBV2 * inv_detV1V2; c.tb = detV1B * inv_detV1V2; -// std::cerr << "ta = " << solution.ta << std::endl; -// std::cerr << "tb = " << solution.tb << std::endl; +// std::cerr << "ta = " << c.ta << std::endl; +// std::cerr << "tb = " << c.tb << std::endl; return OptCrossing(c); } OptCrossing intersection_impl(Ray const& r1, Line const& l2, unsigned int i) { - OptCrossing crossing = + OptCrossing crossing = intersection_impl(r1.versor(), r1.origin(), l2.versor(), l2.origin() ); - + if (crossing) { if (crossing->ta < 0) @@ -97,7 +181,7 @@ OptCrossing intersection_impl( LineSegment const& ls1, Line const& l2, unsigned int i ) { - OptCrossing crossing = + OptCrossing crossing = intersection_impl(ls1.finalPoint() - ls1.initialPoint(), ls1.initialPoint(), l2.versor(), @@ -135,7 +219,7 @@ OptCrossing intersection_impl( LineSegment const& ls1, unsigned int i ) { Point direction = ls1.finalPoint() - ls1.initialPoint(); - OptCrossing crossing = + OptCrossing crossing = intersection_impl( direction, ls1.initialPoint(), r2.versor(), @@ -143,9 +227,9 @@ OptCrossing intersection_impl( LineSegment const& ls1, if (crossing) { - if ( crossing->getTime(0) < 0 - || crossing->getTime(0) > 1 - || crossing->getTime(1) < 0 ) + if ( (crossing->getTime(0) < 0) + || (crossing->getTime(0) > 1) + || (crossing->getTime(1) < 0) ) { return OptCrossing(); } @@ -203,7 +287,7 @@ OptCrossing intersection_impl( LineSegment const& ls1, OptCrossing intersection(Line const& l1, Line const& l2) { - OptCrossing crossing = + OptCrossing crossing = detail::intersection_impl( l1.versor(), l1.origin(), l2.versor(), l2.origin() ); if (crossing) @@ -223,7 +307,7 @@ OptCrossing intersection(Line const& l1, Line const& l2) OptCrossing intersection(Ray const& r1, Ray const& r2) { - OptCrossing crossing = + OptCrossing crossing = detail::intersection_impl( r1.versor(), r1.origin(), r2.versor(), r2.origin() ); @@ -333,6 +417,62 @@ OptCrossing intersection( LineSegment const& ls1, LineSegment const& ls2 ) } +boost::optional clip (Line const& l, Rect const& r) +{ + typedef boost::optional opt_linesegment; + LineSegment result; + //size_t index = 0; + std::vector points; + LineSegment ls (r.corner(0), r.corner(1)); + try + { + OptCrossing oc = intersection (ls, l); + if (oc) + { + points.push_back (l.pointAt (oc->tb)); + } + } + catch (InfiniteSolutions e) + { + return opt_linesegment(ls); + } + + for (size_t i = 2; i < 5; ++i) + { + ls.setInitial (ls[1]); + ls.setFinal (r.corner(i)); + try + { + OptCrossing oc = intersection (ls, l); + if (oc) + { + points.push_back (l.pointAt (oc->tb)); + if (points.size() > 1) + { + size_t sz = points.size(); + if (!are_near (points[sz - 2], points[sz - 1], 1e-10)) + { + result.setInitial (points[sz - 2]); + result.setFinal (points[sz - 1]); + return opt_linesegment(result); + } + } + } + } + catch (InfiniteSolutions e) + { + return opt_linesegment(ls); + } + } + if (points.size() != 0) + { + result.setInitial (points[0]); + result.setFinal (points[0]); + return opt_linesegment(result); + } + return opt_linesegment(); +} + Line make_angle_bisector_line(Line const& l1, Line const& l2) { @@ -359,6 +499,8 @@ Line make_angle_bisector_line(Line const& l1, Line const& l2) } + + } // end namespace Geom diff --git a/src/2geom/line.h b/src/2geom/line.h index a7e6a54bb..ccb0ae6c5 100644 --- a/src/2geom/line.h +++ b/src/2geom/line.h @@ -35,265 +35,278 @@ #include #include <2geom/bezier-curve.h> // for LineSegment +#include <2geom/rect.h> #include <2geom/crossing.h> #include <2geom/exception.h> #include <2geom/ray.h> +#include + namespace Geom { -class Line -{ - public: - Line() - : m_origin(0,0), m_versor(1,0) - { - } - - Line(Point const& _origin, Coord angle ) - : m_origin(_origin), m_versor(std::cos(angle), std::sin(angle)) - { - } - - Line(Point const& A, Point const& B) - { - setBy2Points(A, B); - } - - explicit - Line(LineSegment const& _segment) - { - setBy2Points(_segment.initialPoint(), _segment.finalPoint()); - } - - explicit - Line(Ray const& _ray) - : m_origin(_ray.origin()), m_versor(_ray.versor()) - { - } - - static Line fromNormalDistance(Point n, double c) { - Point P = n*c/(dot(n,n)); - - return Line(P, P+rot90(n)); +class Line { +private: + Point m_origin; + Point m_versor; +public: + /// @name Creating lines. + /// @{ + /** @brief Create a default horizontal line. */ + Line() + : m_origin(0,0), m_versor(1,0) + {} + /** @brief Create a line with the specified inclination. + * @param _origin One of the points on the line + * @param angle Angle of the line in mathematical convention */ + Line(Point const& _origin, Coord angle ) + : m_origin(_origin) + { + sincos(angle, m_versor[Y], m_versor[X]); + } + + /** @brief Create a line going through two points. + * @param A First point + * @param B Second point */ + Line(Point const& A, Point const& B) { + setPoints(A, B); } - static Line fromPointDirection(Point o, Point v) { + + /** @brief Create a line based on the coefficients of its equation. + @see Line::setCoefficients() */ + Line(double a, double b, double c) { + setCoefficients(a, b, c); + } + + /** @brief Create a line by extending a line segment. */ + explicit Line(LineSegment const& _segment) { + setPoints(_segment.initialPoint(), _segment.finalPoint()); + } + + /** @brief Create a line by extending a ray. */ + explicit Line(Ray const& _ray) + : m_origin(_ray.origin()), m_versor(_ray.versor()) + {} + + // huh? + static Line from_normal_distance(Point n, double c) { + Point P = n * c / dot(n,n); + Line l(P, P+rot90(n)); + return l; + } + /** @brief Create a line from origin and unit vector. + * Note that each line direction has two possible unit vectors. + * @param o Point through which the line will pass + * @param v Unit vector of the line's direction */ + static Line from_origin_and_versor(Point o, Point v) { Line l; l.m_origin = o; l.m_versor = v; return l; } - Line* duplicate() const - { - return new Line(*this); - } - - 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; - } - - // return the angle described by rotating the X-axis in cw direction - // until it overlaps the line - // the returned value is in the interval [0, PI[ - Coord angle() const - { - double a = std::atan2(m_versor[Y], m_versor[X]); - if (a < 0) a += M_PI; - if (a == M_PI) a = 0; - 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 - { - return m_origin + m_versor * t; - } - - Coord valueAt(Coord t, Dim2 d) const - { - if (d < 0 || d > 1) - THROW_RANGEERROR("Ray::valueAt, dimension argument out of range"); - return m_origin[d] + m_versor[d] * t; - } - - std::vector roots(Coord v, Dim2 d) const - { - if (d < 0 || d > 1) - THROW_RANGEERROR("Ray::roots, dimension argument out of range"); - std::vector result; - if ( m_versor[d] != 0 ) - { - result.push_back( (v - m_origin[d]) / m_versor[d] ); - } - // 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 timeAtProjection(Point const& _point) const - { - if ( isDegenerate() ) return 0; - return dot( _point - m_origin, m_versor ); - } - - Coord nearestPoint(Point const& _point) const - { - return timeAtProjection(_point); - } - - Line reverse() const - { - Line 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 ray(Coord t) - { - Ray result; - result.origin(pointAt(t)); - result.versor(m_versor); - return result; - } - - Line derivative() const - { - Line result; - result.origin(m_versor); - result.versor(Point(0,0)); - return result; - } - - Line transformed(Matrix const& m) const - { - return Line(m_origin * m, (m_origin + m_versor) * m); - } - - static Line from_normal_and_dist(Point const &n, double d) { - return Line(n*d, n*d + rot90(n)); + Line* duplicate() const { + return new Line(*this); + } + /// @} + + /// @name Retrieve and set the line's parameters. + /// @{ + /** @brief Get the line's origin point. */ + Point origin() const { return m_origin; } + /** @brief Get the line's direction unit vector. */ + Point versor() const { return m_versor; } + // return the angle described by rotating the X-axis in cw direction + // until it overlaps the line + // the returned value is in the interval [0, PI[ + Coord angle() const { + double a = std::atan2(m_versor[Y], m_versor[X]); + if (a < 0) a += M_PI; + if (a == M_PI) a = 0; + return a; } - private: - Point m_origin; - Point m_versor; + void setOrigin(Point const& _point) { + m_origin = _point; + } + void setVersor(Point const& _versor) { + m_versor = _versor; + } + + void setAngle(Coord _angle) { + sincos(_angle, m_versor[Y], m_versor[X]); + } + + /** @brief Set a line based on two points it should pass through. */ + void setPoints(Point const& A, Point const& B) { + m_origin = A; + if ( are_near(A, B) ) + m_versor = Point(0,0); + else + m_versor = B - A; + m_versor.normalize(); + } + void setCoefficients (double a, double b, double c); + std::vector coefficients() const; + + /** @brief Check if the line has any points. + * A degenerate line can be created if the line is created from a line equation + * that has no solutions. + * @return True if the line has no points */ + bool isDegenerate() const { + return ( m_versor[X] == 0 && m_versor[Y] == 0 ); + } + /// @} + + /// @name Evaluate the line as a function. + ///@{ + Point pointAt(Coord t) const { + return m_origin + m_versor * t; + } + + Coord valueAt(Coord t, Dim2 d) const { + if (d < 0 || d > 1) + THROW_RANGEERROR("Line::valueAt, dimension argument out of range"); + return m_origin[d] + m_versor[d] * t; + } + + Coord timeAt(Point const &p) const; + + /** @brief Get a time value corresponding to a projection of a point on the line. + * @param p Arbitrary point. + * @return Time value corresponding to a point closest to @c p. */ + Coord timeAtProjection(Point const& p) const { + if ( isDegenerate() ) return 0; + return dot( p - m_origin, m_versor ); + } + + /** @brief Find a point on the line closest to the query point. + * This is an alias for timeAtProjection(). */ + Coord nearestPoint(Point const& _point) const { + return timeAtProjection(_point); + } + + std::vector roots(Coord v, Dim2 d) const; + /// @} + + /// @name Create other objects based on this line. + /// @{ + /** @brief Create a line containing the same points, but with negated time values. + * @return Line \f$g\f$ such that \f$g(t) = f(-t)\f$ */ + Line reverse() const + { + Line result; + result.setOrigin(m_origin); + result.setVersor(-m_versor); + return result; + } + + /** @brief Same as segment(), but allocate the line segment dynamically. */ + // TODO remove this? + Curve* portion(Coord f, Coord t) const { + LineSegment* seg = new LineSegment(pointAt(f), pointAt(t)); + return seg; + } + + /** @brief Create a segment of this line. + * @param f Time value for the initial point of the segment + * @param t Time value for the final point of the segment + * @return Created line segment */ + LineSegment segment(Coord f, Coord t) const { + return LineSegment(pointAt(f), pointAt(t)); + } + + /** @brief Create a ray starting at the specified time value. + * The created ray will go in the direction of the line's versor (in the direction + * of increasing time values). + * @param t Time value where the ray should start + * @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); + return result; + } + + /** @brief Create a derivative of the line. + * The new line will always be degenerate. Its origin will be equal to this + * line's versor. */ + Line derivative() const { + Line result; + result.setOrigin(m_versor); + result.setVersor(Point(0,0)); + return result; + } + + /** @brief Create a line transformed by an affine transformation. */ + Line transformed(Affine const& m) const { + return Line(m_origin * m, (m_origin + m_versor) * m); + } + + /** @brief Get a vector normal to the line. + * If Y grows upwards, then this is the left normal. If Y grows downwards, + * then this is the right normal. */ + Point normal() const { + return rot90(m_versor); + } + + // what does this do? + Point normalAndDist(double & dist) const { + Point n = normal(); + dist = -dot(n, m_origin); + return n; + } + /// @} }; // end class Line inline double distance(Point const& _point, Line const& _line) { - if ( _line.isDegenerate() ) - { - return distance( _point, _line.origin() ); - } - else - { - return fabs( dot(_point - _line.origin(), _line.versor().ccw()) ); - } + if ( _line.isDegenerate() ) + { + return ::Geom::distance( _point, _line.origin() ); + } + else + { + return fabs( dot(_point - _line.origin(), _line.versor().ccw()) ); + } } inline bool are_near(Point const& _point, Line const& _line, double eps = EPSILON) { - return are_near(distance(_point, _line), 0, eps); + return are_near(distance(_point, _line), 0, eps); } inline bool are_parallel(Line const& l1, Line const& l2, double eps = EPSILON) { - return ( are_near(l1.versor(), l2.versor(), eps) - || are_near(l1.versor(), -l2.versor(), eps) ); + return ( are_near(l1.versor(), l2.versor(), eps) + || are_near(l1.versor(), -l2.versor(), eps) ); } inline bool are_same(Line const& l1, Line const& l2, double eps = EPSILON) { - return are_parallel(l1, l2, eps) && are_near(l1.origin(), l2, eps); + return are_parallel(l1, l2, eps) && are_near(l1.origin(), l2, eps); } inline bool are_orthogonal(Line const& l1, Line const& l2, double eps = EPSILON) { - return ( are_near(l1.versor(), l2.versor().cw(), eps) - || are_near(l1.versor(), l2.versor().ccw(), eps) ); + return ( are_near(l1.versor(), l2.versor().cw(), eps) + || are_near(l1.versor(), l2.versor().ccw(), eps) ); } inline bool are_collinear(Point const& p1, Point const& p2, Point const& p3, - double eps = EPSILON) + double eps = EPSILON) { - return are_near( cross(p3, p2) - cross(p3, p1) + cross(p2, p1), 0, eps); + return are_near( cross(p3, p2) - cross(p3, p1) + cross(p2, p1), 0, eps); } // evaluate the angle between l1 and l2 rotating l1 in cw direction @@ -302,10 +315,10 @@ bool are_collinear(Point const& p1, Point const& p2, Point const& p3, inline double angle_between(Line const& l1, Line const& l2) { - double angle = angle_between(l1.versor(), l2.versor()); - if (angle < 0) angle += M_PI; - if (angle == M_PI) angle = 0; - return angle; + double angle = angle_between(l1.versor(), l2.versor()); + if (angle < 0) angle += M_PI; + if (angle == M_PI) angle = 0; + return angle; } inline @@ -317,60 +330,60 @@ double distance(Point const& _point, LineSegment const& _segment) inline bool are_near(Point const& _point, LineSegment const& _segment, - double eps = EPSILON) + double eps = EPSILON) { - return are_near(distance(_point, _segment), 0, eps); + return are_near(distance(_point, _segment), 0, eps); } // build a line passing by _point and orthogonal to _line inline Line make_orthogonal_line(Point const& _point, Line const& _line) { - Line l; - l.origin(_point); - l.versor(_line.versor().cw()); - return l; + Line l; + l.setOrigin(_point); + l.setVersor(_line.versor().cw()); + return l; } // build a line passing by _point and parallel to _line inline Line make_parallel_line(Point const& _point, Line const& _line) { - Line l(_line); - l.origin(_point); - return l; + Line l(_line); + l.setOrigin(_point); + return l; } // build a line passing by the middle point of _segment and orthogonal to it. inline Line make_bisector_line(LineSegment const& _segment) { - return make_orthogonal_line( middle_point(_segment), Line(_segment) ); + return make_orthogonal_line( middle_point(_segment), Line(_segment) ); } // build the bisector line of the angle between ray(O,A) and ray(O,B) inline Line make_angle_bisector_line(Point const& A, Point const& O, Point const& B) { - Point M = middle_point(A,B); - return Line(O,M); + Point M = middle_point(A,B); + return Line(O,M); } // prj(P) = rot(v, Point( rot(-v, P-O)[X], 0 )) + O inline Point projection(Point const& _point, Line const& _line) { - return _line.pointAt( _line.nearestPoint(_point) ); + return _line.pointAt( _line.nearestPoint(_point) ); } inline LineSegment projection(LineSegment const& _segment, Line const& _line) { - return _line.segment( _line.nearestPoint(_segment.initialPoint()), - _line.nearestPoint(_segment.finalPoint()) ); + return _line.segment( _line.nearestPoint(_segment.initialPoint()), + _line.nearestPoint(_segment.finalPoint()) ); } - +boost::optional clip (Line const& l, Rect const& r); namespace detail diff --git a/src/2geom/matrix.cpp b/src/2geom/matrix.cpp deleted file mode 100644 index e130d2027..000000000 --- a/src/2geom/matrix.cpp +++ /dev/null @@ -1,258 +0,0 @@ -#define __Geom_MATRIX_C__ - -/** \file - * Various matrix routines. Currently includes some Geom::Rotate etc. routines too. - */ - -/* - * Authors: - * Lauris Kaplinski - * Michael G. Sloan - * - * This code is in public domain - */ - -#include <2geom/utils.h> -#include <2geom/matrix.h> -#include <2geom/point.h> - -namespace Geom { - -/** Creates a Matrix given an axis and origin point. - * The axis is represented as two vectors, which represent skew, rotation, and scaling in two dimensions. - * from_basis(Point(1, 0), Point(0, 1), Point(0, 0)) would return the identity matrix. - - \param x_basis the vector for the x-axis. - \param y_basis the vector for the y-axis. - \param offset the translation applied by the matrix. - \return The new Matrix. - */ -//NOTE: Inkscape's version is broken, so when including this version, you'll have to search for code with this func -//TODO: move to Matrix::from_basis -Matrix from_basis(Point const x_basis, Point const y_basis, Point const offset) { - return Matrix(x_basis[X], x_basis[Y], - y_basis[X], y_basis[Y], - offset [X], offset [Y]); -} - -Point Matrix::xAxis() const { - return Point(_c[0], _c[1]); -} - -Point Matrix::yAxis() const { - return Point(_c[2], _c[3]); -} - -/** Gets the translation imparted by the Matrix. - */ -Point Matrix::translation() const { - return Point(_c[4], _c[5]); -} - -void Matrix::setXAxis(Point const &vec) { - for(int i = 0; i < 2; i++) - _c[i] = vec[i]; -} - -void Matrix::setYAxis(Point const &vec) { - for(int i = 0; i < 2; i++) - _c[i + 2] = vec[i]; -} - -/** Sets the translation imparted by the Matrix. - */ -void Matrix::setTranslation(Point const &loc) { - for(int i = 0; i < 2; i++) - _c[i + 4] = loc[i]; -} - -/** Calculates the amount of x-scaling imparted by the Matrix. This is the scaling applied to - * the original x-axis region. It is \emph{not} the overall x-scaling of the transformation. - * Equivalent to L2(m.xAxis()) - */ -double Matrix::expansionX() const { - return sqrt(_c[0] * _c[0] + _c[1] * _c[1]); -} - -/** Calculates the amount of y-scaling imparted by the Matrix. This is the scaling applied before - * the other transformations. It is \emph{not} the overall y-scaling of the transformation. - * Equivalent to L2(m.yAxis()) - */ -double Matrix::expansionY() const { - return sqrt(_c[2] * _c[2] + _c[3] * _c[3]); -} - -void Matrix::setExpansionX(double val) { - double exp_x = expansionX(); - if(!are_near(exp_x, 0.0)) { //TODO: best way to deal with it is to skip op? - double coef = val / expansionX(); - for(unsigned i=0;i<2;i++) _c[i] *= coef; - } -} - -void Matrix::setExpansionY(double val) { - double exp_y = expansionY(); - if(!are_near(exp_y, 0.0)) { //TODO: best way to deal with it is to skip op? - double coef = val / expansionY(); - for(unsigned i=2; i<4; i++) _c[i] *= coef; - } -} - -/** Sets this matrix to be the Identity Matrix. */ -void Matrix::setIdentity() { - _c[0] = 1.0; _c[1] = 0.0; - _c[2] = 0.0; _c[3] = 1.0; - _c[4] = 0.0; _c[5] = 0.0; -} - -//TODO: use eps - -bool Matrix::isIdentity(Coord const eps) const { - return are_near(_c[0], 1.0, eps) && are_near(_c[1], 0.0, eps) && - are_near(_c[2], 0.0, eps) && are_near(_c[3], 1.0, eps) && - are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps); -} - -/** Answers the question "Does this matrix perform a translation, and \em{only} a translation?" - \param eps an epsilon value defaulting to EPSILON - \return A bool representing yes/no. - */ -bool Matrix::isTranslation(Coord const eps) const { - return are_near(_c[0], 1.0, eps) && are_near(_c[1], 0.0, eps) && - are_near(_c[2], 0.0, eps) && are_near(_c[3], 1.0, eps) && - (!are_near(_c[4], 0.0, eps) || !are_near(_c[5], 0.0, eps)); -} - -/** Answers the question "Does this matrix perform a scale, and \em{only} a Scale?" - \param eps an epsilon value defaulting to EPSILON - \return A bool representing yes/no. - */ -bool Matrix::isScale(Coord const eps) const { - return (!are_near(_c[0], 1.0, eps) || !are_near(_c[3], 1.0, eps)) && //NOTE: these are the diags, and the next line opposite diags - are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) && - are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps); -} - -/** Answers the question "Does this matrix perform a uniform scale, and \em{only} a uniform scale?" - \param eps an epsilon value defaulting to EPSILON - \return A bool representing yes/no. - */ -bool Matrix::isUniformScale(Coord const eps) const { - return !are_near(_c[0], 1.0, eps) && are_near(_c[0], _c[3], eps) && - are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) && - are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps); -} - -/** Answers the question "Does this matrix perform a rotation, and \em{only} a rotation?" - \param eps an epsilon value defaulting to EPSILON - \return A bool representing yes/no. - */ -bool Matrix::isRotation(Coord const eps) const { - return are_near(_c[0], _c[3], eps) && are_near(_c[1], -_c[2], eps) && - are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps) && - are_near(_c[0]*_c[0] + _c[1]*_c[1], 1.0, eps); -} - -bool Matrix::onlyScaleAndTranslation(Coord const eps) const { - return are_near(_c[0], _c[3], eps) && are_near(_c[1], 0, eps) && are_near(_c[2], 0, eps); -} - -bool Matrix::isSingular(Coord const eps) const { - return are_near(det(), 0.0, eps); -} - -bool Matrix::flips() const { - return cross(xAxis(), yAxis()) > 0; -} - -/** Returns the Scale/Rotate/skew part of the matrix without the translation part. */ -Matrix Matrix::without_translation() const { - return Matrix(_c[0], _c[1], _c[2], _c[3], 0, 0); -} - -/** Attempts to calculate the inverse of a matrix. - * This is a Matrix such that m * m.inverse() is very near (hopefully < epsilon difference) the identity Matrix. - * \textbf{The Identity Matrix is returned if the matrix has no inverse.} - \return The inverse of the Matrix if defined, otherwise the Identity Matrix. - */ -Matrix Matrix::inverse() const { - Matrix d; - - Geom::Coord const determ = det(); - // the numerical precision of the determinant must be significant - if (fabs(determ) > 1e-18) { - Geom::Coord const ideterm = 1.0 / determ; - - d._c[0] = _c[3] * ideterm; - d._c[1] = -_c[1] * ideterm; - d._c[2] = -_c[2] * ideterm; - d._c[3] = _c[0] * ideterm; - d._c[4] = -_c[4] * d._c[0] - _c[5] * d._c[2]; - d._c[5] = -_c[4] * d._c[1] - _c[5] * d._c[3]; - } else { - d.setIdentity(); - } - - return d; -} - -/** Calculates the determinant of a Matrix. */ -Geom::Coord Matrix::det() const { - return _c[0] * _c[3] - _c[1] * _c[2]; -} - -/** Calculates the scalar of the descriminant of the Matrix. - * This is simply the absolute value of the determinant. - */ -Geom::Coord Matrix::descrim2() const { - return fabs(det()); -} - -/** Calculates the descriminant of the Matrix. */ -Geom::Coord Matrix::descrim() const { - return sqrt(descrim2()); -} - -Matrix operator*(Matrix const &m0, Matrix const &m1) { - Matrix ret; - for(int a = 0; a < 5; a += 2) { - for(int b = 0; b < 2; b++) { - ret[a + b] = m0[a] * m1[b] + m0[a + 1] * m1[b + 2]; - } - } - ret[4] += m1[4]; - ret[5] += m1[5]; - return ret; -} - -//TODO: What's this!?! -Matrix elliptic_quadratic_form(Matrix const &m) { - double const od = m[0] * m[1] + m[2] * m[3]; - return Matrix(m[0]*m[0] + m[1]*m[1], od, - od, m[2]*m[2] + m[3]*m[3], - 0, 0); -} - -Eigen::Eigen(Matrix const &m) { - double const B = -m[0] - m[3]; - double const C = m[0]*m[3] - m[1]*m[2]; - double const center = -B/2.0; - double const delta = sqrt(B*B-4*C)/2.0; - values[0] = center + delta; values[1] = center - delta; - for (int i = 0; i < 2; i++) { - vectors[i] = unit_vector(rot90(Point(m[0]-values[i], m[1]))); - } -} - -} //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:fileencoding=utf-8:textwidth=99 : diff --git a/src/2geom/matrix.h b/src/2geom/matrix.h deleted file mode 100644 index 6a378dbf1..000000000 --- a/src/2geom/matrix.h +++ /dev/null @@ -1,165 +0,0 @@ -#ifndef __Geom_MATRIX_H__ -#define __Geom_MATRIX_H__ - -/** \file - * \brief Definition of Geom::Matrix types. - * - * Main authors: - * Lauris Kaplinski : - * Original NRMatrix definition and related macros. - * - * Nathan Hurst : - * Geom::Matrix class version of the above. - * - * Michael G. Sloan : - * Reorganization and additions. - * - * This code is in public domain. - */ - -//#include - -#include <2geom/point.h> - -namespace Geom { - -/** - * The Matrix class. - * - * For purposes of multiplication, points should be thought of as row vectors - * - * \f$(p_X p_Y 1)\f$ - * - * to be right-multiplied by transformation matrices of the form - * \f[ - \left[ - \begin{array}{ccc} - c_0&c_1&0 \\ - c_2&c_3&0 \\ - c_4&c_5&1 - \end{array} - \right] - \f] - * (so the columns of the matrix correspond to the columns (elements) of the result, - * and the rows of the matrix correspond to columns (elements) of the "input"). - */ -class Matrix { - private: - Coord _c[6]; - public: - Matrix() {} - - Matrix(Matrix const &m) { - for(int i = 0; i < 6; i++) { - _c[i] = m[i]; - } - } - - Matrix(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5) { - _c[0] = c0; _c[1] = c1; - _c[2] = c2; _c[3] = c3; - _c[4] = c4; _c[5] = c5; - } - - Matrix &operator=(Matrix const &m) { - for(int i = 0; i < 6; i++) - _c[i] = m._c[i]; - return *this; - } - - inline Coord operator[](unsigned const i) const { return _c[i]; } - inline Coord &operator[](unsigned const i) { return _c[i]; } - - - Point xAxis() const; - Point yAxis() const; - void setXAxis(Point const &vec); - void setYAxis(Point const &vec); - - Point translation() const; - void setTranslation(Point const &loc); - - double expansionX() const; - double expansionY() const; - inline Point expansion() const { return Point(expansionX(), expansionY()); } - void setExpansionX(double val); - void setExpansionY(double val); - - void setIdentity(); - - bool isIdentity(Coord eps = EPSILON) const; - bool isTranslation(Coord eps = EPSILON) const; - bool isRotation(double eps = EPSILON) const; - bool isScale(double eps = EPSILON) const; - bool isUniformScale(double eps = EPSILON) const; - bool onlyScaleAndTranslation(double eps = EPSILON) const; - bool isSingular(double eps = EPSILON) const; - - bool flips() const; - - Matrix without_translation() const; - - Matrix inverse() const; - - Coord det() const; - Coord descrim2() const; - Coord descrim() const; -}; - -Matrix operator*(Matrix const &a, Matrix const &b); -inline Matrix &operator*=(Matrix &a, Matrix const &b) { a = a * b; return a; } - -/** A function to print out the Matrix (for debugging) */ -inline std::ostream &operator<< (std::ostream &out_file, const Geom::Matrix &m) { - out_file << "A: " << m[0] << " C: " << m[2] << " E: " << m[4] << "\n"; - out_file << "B: " << m[1] << " D: " << m[3] << " F: " << m[5] << "\n"; - return out_file; -} - -/** Given a matrix m such that unit_circle = m*x, this returns the - * quadratic form x*A*x = 1. */ -Matrix elliptic_quadratic_form(Matrix const &m); - -/** Given a matrix (ignoring the translation) this returns the eigen - * values and vectors. */ -class Eigen{ -public: - Point vectors[2]; - double values[2]; - Eigen(Matrix const &m); -}; - -// Matrix factories -Matrix from_basis(const Point x_basis, const Point y_basis, const Point offset=Point(0,0)); - -/** Returns the Identity Matrix. */ -inline Matrix identity() { - return Matrix(1.0, 0.0, - 0.0, 1.0, - 0.0, 0.0); -} - -inline bool operator==(Matrix const &a, Matrix const &b) { - for(unsigned i = 0; i < 6; ++i) { - if ( a[i] != b[i] ) return false; - } - return true; -} -inline bool operator!=(Matrix const &a, Matrix const &b) { return !( a == b ); } - - - -} /* namespace Geom */ - -#endif /* !__Geom_MATRIX_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/numeric/fitting-model.h b/src/2geom/numeric/fitting-model.h index dcf0e8e1d..b1ecbe92c 100644 --- a/src/2geom/numeric/fitting-model.h +++ b/src/2geom/numeric/fitting-model.h @@ -43,6 +43,7 @@ #include <2geom/ellipse.h> #include <2geom/circle.h> #include <2geom/utils.h> +#include <2geom/conicsec.h> namespace Geom { namespace NL { @@ -83,6 +84,10 @@ namespace Geom { namespace NL { * instance type: the type of the objects produced by using * the fitting raw data solution */ + + + + template< typename ParameterType, typename ValueType, typename InstanceType > class LinearFittingModel { @@ -230,8 +235,32 @@ class LFMNormalizedPowerBasis // incomplete model, it can be inherited to make up different kinds of // instance type; the raw data is a vector of coefficients of the equation // of an ellipse curve +//template< typename InstanceType > +//class LFMEllipseEquation +// : public LinearFittingModelWithFixedTerms +//{ +// public: +// void feed( VectorView & coeff, double & fixed_term, Point const& p ) const +// { +// coeff[0] = p[X] * p[Y]; +// coeff[1] = p[Y] * p[Y]; +// coeff[2] = p[X]; +// coeff[3] = p[Y]; +// coeff[4] = 1; +// fixed_term = p[X] * p[X]; +// } +// +// size_t size() const +// { +// return 5; +// } +//}; + +// incomplete model, it can be inherited to make up different kinds of +// instance type; the raw data is a vector of coefficients of the equation +// of a conic section template< typename InstanceType > -class LFMEllipseEquation +class LFMConicEquation : public LinearFittingModelWithFixedTerms { public: @@ -251,10 +280,20 @@ class LFMEllipseEquation } }; +// this model generates Ellipse curves +class LFMConicSection + : public LFMConicEquation +{ + public: + void instance(xAx & c, ConstVectorView const& coeff) const + { + c.set(1, coeff[0], coeff[1], coeff[2], coeff[3], coeff[4]); + } +}; // this model generates Ellipse curves class LFMEllipse - : public LFMEllipseEquation + : public LFMConicEquation { public: void instance(Ellipse & e, ConstVectorView const& coeff) const @@ -431,9 +470,8 @@ class LFMBezier // this model generates Bezier curves -template< unsigned int N > class LFMBezierCurve - : public LinearFittingModel< double, Point, BezierCurve > + : public LinearFittingModel< double, Point, BezierCurve > { public: LFMBezierCurve( size_t _order ) @@ -451,13 +489,13 @@ class LFMBezierCurve return mob.size(); } - void instance(BezierCurve & bc, ConstMatrixView const& raw_data) const + void instance(BezierCurve & bc, ConstMatrixView const& raw_data) const { Bezier bx(size()-1); Bezier by(size()-1); mob.instance(bx, raw_data.column_const_view(X)); mob.instance(by, raw_data.column_const_view(Y)); - bc = BezierCurve(bx, by); + bc = BezierCurve(bx, by); } private: diff --git a/src/2geom/numeric/matrix.cpp b/src/2geom/numeric/matrix.cpp index 94a345fd5..98ff3b6ca 100644 --- a/src/2geom/numeric/matrix.cpp +++ b/src/2geom/numeric/matrix.cpp @@ -37,10 +37,8 @@ #include <2geom/numeric/vector.h> - namespace Geom { namespace NL { - Vector operator*( detail::BaseMatrixImpl const& A, detail::BaseVectorImpl const& v ) { @@ -101,6 +99,47 @@ Matrix pseudo_inverse(detail::BaseMatrixImpl const& A) return P; } + +double trace (detail::BaseMatrixImpl const& A) +{ + if (A.rows() != A.columns()) + { + THROW_RANGEERROR ("NL::Matrix: computing trace: " + "rows() != columns()"); + } + double t = 0; + for (size_t i = 0; i < A.rows(); ++i) + { + t += A(i,i); + } + return t; +} + + +double det (detail::BaseMatrixImpl const& A) +{ + if (A.rows() != A.columns()) + { + THROW_RANGEERROR ("NL::Matrix: computing determinant: " + "rows() != columns()"); + } + + Matrix LU(A); + int s; + gsl_permutation * p = gsl_permutation_alloc(LU.rows()); + gsl_linalg_LU_decomp (LU.get_gsl_matrix(), p, &s); + + double t = 1; + for (size_t i = 0; i < LU.rows(); ++i) + { + t *= LU(i,i); + } + + gsl_permutation_free(p); + return t; +} + + } } // end namespaces /* diff --git a/src/2geom/numeric/matrix.h b/src/2geom/numeric/matrix.h index f2a934235..a130bd748 100644 --- a/src/2geom/numeric/matrix.h +++ b/src/2geom/numeric/matrix.h @@ -38,6 +38,7 @@ #ifndef _NL_MATRIX_H_ #define _NL_MATRIX_H_ +#include <2geom/exception.h> #include <2geom/numeric/vector.h> #include @@ -45,7 +46,6 @@ #include // for std::swap #include #include - #include #include @@ -232,13 +232,13 @@ class MatrixImpl : public BaseMatrixImpl gsl_matrix_set_identity(m_matrix); } - using base_type::operator(); // VSC legacy support - const double & operator() (size_t i, size_t j) const - { - return base_type::operator ()(i, j); - } + using base_type::operator(); // VSC legacy support + const double & operator() (size_t i, size_t j) const + { + return base_type::operator ()(i, j); + } - double & operator() (size_t i, size_t j) + double & operator() (size_t i, size_t j) { return *gsl_matrix_ptr(m_matrix, i, j); } @@ -310,6 +310,8 @@ using detail::operator==; using detail::operator<<; +template +class ConstBaseSymmetricMatrix; class Matrix: public detail::MatrixImpl @@ -352,6 +354,18 @@ class Matrix: public detail::MatrixImpl gsl_matrix_memcpy(m_matrix, _matrix.get_gsl_matrix()); } + template + explicit + Matrix(ConstBaseSymmetricMatrix const& _smatrix) + { + m_rows = N; + m_columns = N; + m_matrix = gsl_matrix_alloc(N, N); + for (size_t i = 0; i < N; ++i) + for (size_t j = 0; j < N ; ++j) + (*gsl_matrix_ptr(m_matrix, i, j)) = _smatrix(i,j); + } + Matrix & operator=(Matrix const& _matrix) { assert( rows() == _matrix.rows() && columns() == _matrix.columns() ); @@ -366,6 +380,16 @@ class Matrix: public detail::MatrixImpl return *this; } + template + Matrix & operator=(ConstBaseSymmetricMatrix const& _smatrix) + { + assert (rows() == N && columns() == N); + for (size_t i = 0; i < N; ++i) + for (size_t j = 0; j < N ; ++j) + (*this)(i,j) = _smatrix(i,j); + return *this; + } + virtual ~Matrix() { gsl_matrix_free(m_matrix); @@ -557,6 +581,10 @@ Matrix operator*( detail::BaseMatrixImpl const& A, Matrix pseudo_inverse(detail::BaseMatrixImpl const& A); +double trace (detail::BaseMatrixImpl const& A); + +double det (detail::BaseMatrixImpl const& A); + } } // end namespaces #endif /*_NL_MATRIX_H_*/ diff --git a/src/2geom/numeric/vector.h b/src/2geom/numeric/vector.h index 46701645a..6ab898f29 100644 --- a/src/2geom/numeric/vector.h +++ b/src/2geom/numeric/vector.h @@ -555,6 +555,24 @@ void swap_view(VectorView & v1, VectorView & v2) std::swap(v1.m_vector_view, v2.m_vector_view); // not swap m_vector too } +inline +const VectorView & const_vector_view_cast (const ConstVectorView & view) +{ + const detail::BaseVectorImpl & bvi + = static_cast(view); + const VectorView & vv = reinterpret_cast(bvi); + return vv; +} + +inline +VectorView & const_vector_view_cast (ConstVectorView & view) +{ + detail::BaseVectorImpl & bvi + = static_cast(view); + VectorView & vv = reinterpret_cast(bvi); + return vv; +} + } } // end namespaces diff --git a/src/2geom/path-intersection.cpp b/src/2geom/path-intersection.cpp index 5e58525c7..58ee6232b 100644 --- a/src/2geom/path-intersection.cpp +++ b/src/2geom/path-intersection.cpp @@ -28,7 +28,7 @@ int winding(Path const &path, Point p) { if(iter == path.end_closed()) { return 0; } if(iter->initialPoint()[Y]!=p[Y]) { start = iter; break; } if(iter->finalPoint()[Y]!=p[Y]) { start = iter; break; } - if(iter->boundsFast()->height()!=0.){ start = iter; break; } + if(iter->boundsFast().height()!=0.){ start = iter; break; } } int wind = 0; unsigned cnt = 0; @@ -39,18 +39,18 @@ int winding(Path const &path, Point p) { cnt++; if(cnt > path.size()) return wind; //some bug makes this required starting = false; - Rect bounds = *(iter->boundsFast()); + Rect bounds = (iter->boundsFast()); Coord x = p[X], y = p[Y]; - + if(x > bounds.right() || !bounds[Y].contains(y)) continue; //ray doesn't intersect box - + Point final = iter->finalPoint(); Point initial = iter->initialPoint(); Cmp final_to_ray = cmp(final[Y], y); Cmp initial_to_ray = cmp(initial[Y], y); - + // if y is included, these will have opposite values, giving order. - Cmp c = cmp(final_to_ray, initial_to_ray); + Cmp c = cmp(final_to_ray, initial_to_ray); if(x < bounds.left()) { // ray goes through bbox // winding delta determined by position of endpoints @@ -73,7 +73,7 @@ int winding(Path const &path, Point p) { next++; for(; ; next++) { if(next == path.end_closed()) next = path.begin(); - Rect bnds = *(next->boundsFast()); + Rect bnds = (next->boundsFast()); //TODO: X considerations if(bnds.height() > 0) { //It has diverged @@ -100,7 +100,7 @@ int winding(Path const &path, Point p) { //Looks like it looped, which means everything's flat return 0; } - + cont:(void)0; } return wind; @@ -135,10 +135,10 @@ bool path_direction(Path const &p) { } else if(final_to_ray == EQUAL_TO) goto doh; } return res < 0; - + doh: //Otherwise fallback on area - + Piecewise > pw = p.toPwSb(); double area; Point centre; @@ -214,39 +214,41 @@ intersect_polish_f (const gsl_vector * x, void *params, { const double x0 = gsl_vector_get (x, 0); const double x1 = gsl_vector_get (x, 1); - - Geom::Point dx = ((struct rparams *) params)->A(x0) - + + Geom::Point dx = ((struct rparams *) params)->A(x0) - ((struct rparams *) params)->B(x1); - + gsl_vector_set (f, 0, dx[0]); gsl_vector_set (f, 1, dx[1]); - + return GSL_SUCCESS; } #endif -static void +static void intersect_polish_root (Curve const &A, double &s, Curve const &B, double &t) { + int status; + size_t iter = 0; std::vector as, bs; as = A.pointAndDerivatives(s, 2); bs = B.pointAndDerivatives(t, 2); Point F = as[0] - bs[0]; double best = dot(F, F); - + for(int i = 0; i < 4; i++) { - + /** we want to solve J*(x1 - x0) = f(x0) - + |dA(s)[0] -dB(t)[0]| (X1 - X0) = A(s) - B(t) - |dA(s)[1] -dB(t)[1]| + |dA(s)[1] -dB(t)[1]| **/ // We're using the standard transformation matricies, which is numerically rather poor. Much better to solve the equation using elimination. - Matrix jack(as[1][0], as[1][1], + Affine jack(as[1][0], as[1][1], -bs[1][0], -bs[1][1], 0, 0); Point soln = (F)*jack.inverse(); @@ -257,7 +259,7 @@ intersect_polish_root (Curve const &A, double &s, else if (ns>1) ns=1; if (nt<0) nt=0; else if (nt>1) nt=1; - + as = A.pointAndDerivatives(ns, 2); bs = B.pointAndDerivatives(nt, 2); F = as[0] - bs[0]; @@ -275,35 +277,33 @@ intersect_polish_root (Curve const &A, double &s, const size_t n = 2; struct rparams p = {A, B}; gsl_multiroot_function f = {&intersect_polish_f, n, &p}; - + double x_init[2] = {s, t}; gsl_vector *x = gsl_vector_alloc (n); - + gsl_vector_set (x, 0, x_init[0]); gsl_vector_set (x, 1, x_init[1]); - + const gsl_multiroot_fsolver_type *T = gsl_multiroot_fsolver_hybrids; gsl_multiroot_fsolver *sol = gsl_multiroot_fsolver_alloc (T, 2); gsl_multiroot_fsolver_set (sol, &f, x); - - int status = 0; - size_t iter = 0; + do { iter++; status = gsl_multiroot_fsolver_iterate (sol); - + if (status) /* check if solver is stuck */ break; - + status = gsl_multiroot_test_residual (sol->f, 1e-12); } while (status == GSL_CONTINUE && iter < 1000); - + s = gsl_vector_get (sol->x, 0); t = gsl_vector_get (sol->x, 1); - + gsl_multiroot_fsolver_free (sol); gsl_vector_free (x); } @@ -315,7 +315,7 @@ intersect_polish_root (Curve const &A, double &s, * It passes in the curves, time intervals, and keeps track of depth, while * returning the results through the Crossings parameter. */ -void pair_intersect(Curve const & A, double Al, double Ah, +void pair_intersect(Curve const & A, double Al, double Ah, Curve const & B, double Bl, double Bh, Crossings &ret, unsigned depth = 0) { // std::cout << depth << "(" << Al << ", " << Ah << ")\n"; @@ -324,15 +324,15 @@ void pair_intersect(Curve const & A, double Al, double Ah, OptRect Br = B.boundsLocal(Interval(Bl, Bh)); if (!Br) return; - + if(! Ar->intersects(*Br)) return; - + //Checks the general linearity of the function - if((depth > 12)) { // || (A.boundsLocal(Interval(Al, Ah), 1).maxExtent() < 0.1 + if((depth > 12)) { // || (A.boundsLocal(Interval(Al, Ah), 1).maxExtent() < 0.1 //&& B.boundsLocal(Interval(Bl, Bh), 1).maxExtent() < 0.1)) { double tA, tB, c; - if(linear_intersect(A.pointAt(Al), A.pointAt(Ah), - B.pointAt(Bl), B.pointAt(Bh), + if(linear_intersect(A.pointAt(Al), A.pointAt(Ah), + B.pointAt(Bl), B.pointAt(Bh), tA, tB, c)) { tA = tA * (Ah - Al) + Al; tB = tB * (Bh - Bl) + Bl; @@ -385,8 +385,8 @@ void mono_intersect(Curve const &A, double Al, double Ah, if(depth > 12 || (Ar.maxExtent() < tol && Ar.maxExtent() < tol)) { double tA, tB, c; - if(linear_intersect(A.pointAt(Al), A.pointAt(Ah), - B.pointAt(Bl), B.pointAt(Bh), + if(linear_intersect(A.pointAt(Al), A.pointAt(Ah), + B.pointAt(Bl), B.pointAt(Bh), tA, tB, c)) { tA = tA * (Ah - Al) + Al; tB = tB * (Bh - Bl) + Bl; @@ -483,7 +483,7 @@ std::vector offset_doubles(std::vector const &x, double offs) { std::vector path_mono_splits(Path const &p) { std::vector ret; if(p.empty()) return ret; - + bool pdx=2, pdy=2; //Previous derivative direction for(unsigned i = 0; i < p.size(); i++) { std::vector spl = offset_doubles(curve_mono_splits(p[i]), i); @@ -502,7 +502,7 @@ std::vector path_mono_splits(Path const &p) { } /** - * Applies path_mono_splits to multiple paths, and returns the results such that + * Applies path_mono_splits to multiple paths, and returns the results such that * time-set i corresponds to Path i. */ std::vector > paths_mono_splits(std::vector const &ps) { @@ -541,14 +541,14 @@ CrossingSet MonoCrosser::crossings(std::vector const &a, std::vector if(b.empty()) return CrossingSet(a.size(), Crossings()); CrossingSet results(a.size() + b.size(), Crossings()); if(a.empty()) return results; - + std::vector > splits_a = paths_mono_splits(a), splits_b = paths_mono_splits(b); std::vector > bounds_a = split_bounds(a, splits_a), bounds_b = split_bounds(b, splits_b); - - std::vector bounds_a_union, bounds_b_union; + + std::vector bounds_a_union, bounds_b_union; for(unsigned i = 0; i < bounds_a.size(); i++) bounds_a_union.push_back(union_list(bounds_a[i])); for(unsigned i = 0; i < bounds_b.size(); i++) bounds_b_union.push_back(union_list(bounds_b[i])); - + std::vector > cull = sweep_bounds(bounds_a_union, bounds_b_union); Crossings n; for(unsigned i = 0; i < cull.size(); i++) { @@ -556,7 +556,7 @@ CrossingSet MonoCrosser::crossings(std::vector const &a, std::vector unsigned j = cull[i][jx]; unsigned jc = j + a.size(); Crossings res; - + //Sweep of the monotonic portions std::vector > cull2 = sweep_bounds(bounds_a[i], bounds_b[j]); for(unsigned k = 0; k < cull2.size(); k++) { @@ -567,9 +567,9 @@ CrossingSet MonoCrosser::crossings(std::vector const &a, std::vector res, .1); } } - + for(unsigned k = 0; k < res.size(); k++) { res[k].a = i; res[k].b = jc; } - + merge_crossings(results[i], res, i); merge_crossings(results[i], res, jc); } @@ -583,22 +583,22 @@ CrossingSet MonoCrosser::crossings(std::vector const &a, std::vector CrossingSet crossings_among(std::vector const &p) { CrossingSet results(p.size(), Crossings()); if(p.empty()) return results; - + std::vector > splits = paths_mono_splits(p); std::vector > prs = split_bounds(p, splits); std::vector rs; for(unsigned i = 0; i < prs.size(); i++) rs.push_back(union_list(prs[i])); - + std::vector > cull = sweep_bounds(rs); - + //we actually want to do the self-intersections, so add em in: for(unsigned i = 0; i < cull.size(); i++) cull[i].push_back(i); - + for(unsigned i = 0; i < cull.size(); i++) { for(unsigned jx = 0; jx < cull[i].size(); jx++) { unsigned j = cull[i][jx]; Crossings res; - + //Sweep of the monotonic portions std::vector > cull2 = sweep_bounds(prs[i], prs[j]); for(unsigned k = 0; k < cull2.size(); k++) { @@ -609,14 +609,14 @@ CrossingSet crossings_among(std::vector const &p) { res, .1); } } - + for(unsigned k = 0; k < res.size(); k++) { res[k].a = i; res[k].b = j; } - + merge_crossings(results[i], res, i); merge_crossings(results[j], res, j); } } - + return results; } */ @@ -635,7 +635,7 @@ Crossings curve_self_crossings(Curve const &a) { } /* -void mono_curve_intersect(Curve const & A, double Al, double Ah, +void mono_curve_intersect(Curve const & A, double Al, double Ah, Curve const & B, double Bl, double Bh, Crossings &ret, unsigned depth=0) { // std::cout << depth << "(" << Al << ", " << Ah << ")\n"; @@ -643,9 +643,9 @@ void mono_curve_intersect(Curve const & A, double Al, double Ah, B0 = B.pointAt(Bl), B1 = B.pointAt(Bh); //inline code that this implies? (without rect/interval construction) if(!Rect(A0, A1).intersects(Rect(B0, B1)) || A0 == A1 || B0 == B1) return; - + //Checks the general linearity of the function - if((depth > 12) || (A.boundsLocal(Interval(Al, Ah), 1).maxExtent() < 0.1 + if((depth > 12) || (A.boundsLocal(Interval(Al, Ah), 1).maxExtent() < 0.1 && B.boundsLocal(Interval(Bl, Bh), 1).maxExtent() < 0.1)) { double tA, tB, c; if(linear_intersect(A0, A1, B0, B1, tA, tB, c)) { @@ -705,7 +705,7 @@ Crossings path_self_crossings(Path const &p) { for(unsigned jx = 0; jx < cull[i].size(); jx++) { unsigned j = cull[i][jx]; res.clear(); - + std::vector > cull2 = sweep_bounds(bnds[i], bnds[j]); for(unsigned k = 0; k < cull2.size(); k++) { for(unsigned lx = 0; lx < cull2[k].size(); lx++) { @@ -713,7 +713,7 @@ Crossings path_self_crossings(Path const &p) { mono_curve_intersect(p[i], spl[i][k-1], spl[i][k], p[j], spl[j][l-1], spl[j][l], res); } } - + //if(fabs(int(i)-j) == 1 || fabs(int(i)-j) == p.size()-1) { Crossings res2; for(unsigned k = 0; k < res.size(); k++) { @@ -742,7 +742,7 @@ Crossings self_crossings(Path const &p) { unsigned j = cull[i][jx]; res.clear(); pair_intersect(p[i], 0, 1, p[j], 0, 1, res); - + //if(fabs(int(i)-j) == 1 || fabs(int(i)-j) == p.size()-1) { Crossings res2; for(unsigned k = 0; k < res.size(); k++) { @@ -767,9 +767,9 @@ void flip_crossings(Crossings &crs) { CrossingSet crossings_among(std::vector const &p) { CrossingSet results(p.size(), Crossings()); if(p.empty()) return results; - + SimpleCrosser cc; - + std::vector > cull = sweep_bounds(bounds(p)); for(unsigned i = 0; i < cull.size(); i++) { Crossings res = self_crossings(p[i]); @@ -779,7 +779,7 @@ CrossingSet crossings_among(std::vector const &p) { merge_crossings(results[i], res, i); for(unsigned jx = 0; jx < cull[i].size(); jx++) { unsigned j = cull[i][jx]; - + Crossings res = cc.crossings(p[i], p[j]); for(unsigned k = 0; k < res.size(); k++) { res[k].a = i; res[k].b = j; } merge_crossings(results[i], res, i); diff --git a/src/2geom/path.cpp b/src/2geom/path.cpp index c47902649..58d6b9b5e 100644 --- a/src/2geom/path.cpp +++ b/src/2geom/path.cpp @@ -46,8 +46,9 @@ namespace Geom OptRect Path::boundsFast() const { OptRect bounds; if (empty()) return bounds; - bounds=front().boundsFast(); + bounds = front().boundsFast(); const_iterator iter = begin(); + // the closing path segment can be ignored, because it will always lie within the bbox of the rest of the path if ( iter != end() ) { for ( ++iter; iter != end() ; ++iter ) { bounds.unionWith(iter->boundsFast()); @@ -59,8 +60,9 @@ OptRect Path::boundsFast() const { OptRect Path::boundsExact() const { OptRect bounds; if (empty()) return bounds; - bounds=front().boundsExact(); + bounds = front().boundsExact(); const_iterator iter = begin(); + // the closing path segment can be ignored, because it will always lie within the bbox of the rest of the path if ( iter != end() ) { for ( ++iter; iter != end() ; ++iter ) { bounds.unionWith(iter->boundsExact()); @@ -77,7 +79,7 @@ iter inc(iter const &x, unsigned n) { return ret; } -Path &Path::operator*=(Matrix const &m) { +Path &Path::operator*=(Affine const &m) { unshare(); Sequence::iterator last = get_curves().end() - 1; Sequence::iterator it; @@ -146,7 +148,7 @@ Path::allNearestPoints(Point const& _point, double from, double to) const Rect bb(Geom::Point(0,0),Geom::Point(0,0)); for ( unsigned int i = si + 1; i < ei; ++i ) { - bb = *(_path[i].boundsFast()); + bb = (_path[i].boundsFast()); dsq = distanceSq(_point, bb); if ( mindistsq < dsq ) continue; all_t = _path[i].allNearestPoints(_point); @@ -165,7 +167,7 @@ Path::allNearestPoints(Point const& _point, double from, double to) const ni.push_back(i); } } - bb = *(_path[ei].boundsFast()); + bb = (_path[ei].boundsFast()); dsq = distanceSq(_point, bb); if ( mindistsq >= dsq ) { @@ -203,7 +205,7 @@ Path::nearestPointPerCurve(Point const& _point) const { //return a single nearest point for each curve in this path std::vector np; - for (const_iterator it = begin() ; it != end_default(); ++it) + for (const_iterator it = begin() ; it != end_default() ; ++it) //for (std::vector::const_iterator it = _path.begin(); it != _path.end(), ++it){ { np.push_back(it->nearestPoint(_point)); @@ -256,7 +258,7 @@ double Path::nearestPoint(Point const &_point, double from, double to, double *d Rect bb(Geom::Point(0,0),Geom::Point(0,0)); for ( unsigned int i = si + 1; i < ei; ++i ) { - bb = *(_path[i].boundsFast()); + bb = (_path[i].boundsFast()); dsq = distanceSq(_point, bb); if ( mindistsq <= dsq ) continue; t = _path[i].nearestPoint(_point); @@ -268,7 +270,7 @@ double Path::nearestPoint(Point const &_point, double from, double to, double *d mindistsq = dsq; } } - bb = *(_path[ei].boundsFast()); + bb = (_path[ei].boundsFast()); dsq = distanceSq(_point, bb); if ( mindistsq > dsq ) { diff --git a/src/2geom/path.h b/src/2geom/path.h index 3167bb09e..cbd449248 100644 --- a/src/2geom/path.h +++ b/src/2geom/path.h @@ -291,13 +291,13 @@ public: return !( *this == other ); } - Path operator*(Matrix const &m) const { + Path operator*(Affine const &m) const { Path ret(*this); ret *= m; return ret; } - Path &operator*=(Matrix const &m); + Path &operator*=(Affine const &m); Point pointAt(double t) const { diff --git a/src/2geom/pathvector.cpp b/src/2geom/pathvector.cpp index 3d11dd48b..fc0ad75c4 100644 --- a/src/2geom/pathvector.cpp +++ b/src/2geom/pathvector.cpp @@ -38,7 +38,7 @@ #include <2geom/pathvector.h> #include <2geom/path.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> namespace Geom { diff --git a/src/2geom/pathvector.h b/src/2geom/pathvector.h index a531cc955..2f45b9d86 100644 --- a/src/2geom/pathvector.h +++ b/src/2geom/pathvector.h @@ -3,7 +3,8 @@ * \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 * @@ -46,13 +47,13 @@ typedef std::vector PathVector; /* general path transformation: */ inline -void operator*= (PathVector & path_in, Matrix const &m) { +void operator*= (PathVector & path_in, Affine const &m) { for(PathVector::iterator it = path_in.begin(); it != path_in.end(); ++it) { (*it) *= m; } } inline -PathVector operator*(PathVector const & path_in, Matrix const &m) { +PathVector operator*(PathVector const & path_in, Affine const &m) { PathVector ret(path_in); ret *= m; return ret; diff --git a/src/2geom/piecewise.cpp b/src/2geom/piecewise.cpp index fcecc13c1..ba1e60ea3 100644 --- a/src/2geom/piecewise.cpp +++ b/src/2geom/piecewise.cpp @@ -154,6 +154,54 @@ int compose_findSegIdx(std::map::iterator const &cut, return idx; } + +Piecewise pw_compose_inverse(SBasis const &f, SBasis const &g, unsigned order, double zero){ + Piecewise result; + + assert( f.size()>0 && g.size()>0); + SBasis g01 = g; + bool flip = ( g01.at0() > g01.at1() ); + + //OptInterval g_range = bounds_exact(g); + OptInterval g_range( Interval( g.at0(), g.at1() )); + + g01 -= g_range->min(); + g01 /= g_range->extent(); + if ( flip ){ + g01 *= -1.; + g01 += 1.; + } +#if 1 + assert( std::abs( g01.at0() - 0. ) < zero ); + assert( std::abs( g01.at1() - 1. ) < zero ); + //g[0][0] = 0.; + //g[0][1] = 1.; +#endif + + SBasis foginv = compose_inverse( f, g01, order, zero ); + SBasis err = compose( foginv, g01) - f; + + if ( err.tailError(0) < zero ){ + result = Piecewise (foginv); + }else{ + SBasis g_portion = portion( g01, Interval(0.,.5) ); + SBasis f_portion = portion( f, Interval(0.,.5) ); + result = pw_compose_inverse(f_portion, g_portion, order, zero); + + g_portion = portion( g01, Interval(.5, 1.) ); + f_portion = portion( f, Interval(.5, 1.) ); + Piecewise result_next; + result_next = pw_compose_inverse(f_portion, g_portion, order, zero); + result.concat( result_next ); + } + if (flip) { + result = reverse(result); + } + result.setDomain(*g_range); + return result; +} + + std::vector roots(Piecewise const &f){ std::vector result; for (unsigned i=0; i > multi_roots(Piecewise const &f, std::v return result; } + +std::vector level_set(Piecewise const &f, Interval const &level, double tol){ + std::vector result; + for (unsigned i=0; i resulti = level_set( f[i], level, 0., 1., tol); + for (unsigned j=0; j 0 && result.back().intersects(domj) ){ + result.back().unionWith(domj); + }else{ + result.push_back(domj); + } + } + } + return result; +} +std::vector level_set(Piecewise const &f, double v, double vtol, double tol){ + Interval level ( v-vtol, v+vtol ); + return level_set( f, level, tol); +} + + } /* Local Variables: diff --git a/src/2geom/piecewise.h b/src/2geom/piecewise.h index 62185b472..19c66d8f0 100644 --- a/src/2geom/piecewise.h +++ b/src/2geom/piecewise.h @@ -265,6 +265,11 @@ class Piecewise { }; +/** + * ... + * \return ... + * \relates Piecewise + */ template inline typename FragmentConcept::BoundsType bounds_fast(const Piecewise &f) { boost::function_requires >(); @@ -276,6 +281,11 @@ inline typename FragmentConcept::BoundsType bounds_fast(const Piecewise &f return ret; } +/** + * ... + * \return ... + * \relates Piecewise + */ template inline typename FragmentConcept::BoundsType bounds_exact(const Piecewise &f) { boost::function_requires >(); @@ -287,6 +297,11 @@ inline typename FragmentConcept::BoundsType bounds_exact(const Piecewise & return ret; } +/** + * ... + * \return ... + * \relates Piecewise + */ template inline typename FragmentConcept::BoundsType bounds_local(const Piecewise &f, const OptInterval &_m) { boost::function_requires >(); @@ -308,7 +323,10 @@ inline typename FragmentConcept::BoundsType bounds_local(const Piecewise & return ret; } -//returns a portion of a piece of a Piecewise, given the piece's index and a to/from time. +/** + * Returns a portion of a piece of a Piecewise, given the piece's index and a to/from time. + * \relates Piecewise + */ template T elem_portion(const Piecewise &a, unsigned i, double from, double to) { assert(i < a.size()); @@ -324,6 +342,8 @@ T elem_portion(const Piecewise &a, unsigned i, double from, double to) { * Piecewise ac = a.partition(b.cuts); * Piecewise bc = b.partition(a.cuts); * //ac.cuts should be equivalent to bc.cuts + * + * \relates Piecewise */ template Piecewise partition(const Piecewise &pw, std::vector const &c) { @@ -389,8 +409,9 @@ Piecewise partition(const Piecewise &pw, std::vector const &c) { return ret; } -/**Piecewise portion(const Piecewise &pw, double from, double to); - * Returns a Piecewise with a defined domain of [min(from, to), max(from, to)]. +/** + * Returns a Piecewise with a defined domain of [min(from, to), max(from, to)]. + * \relates Piecewise */ template Piecewise portion(const Piecewise &pw, double from, double to) { @@ -424,6 +445,11 @@ Piecewise portion(const Piecewise &pw, double from, double to) { } //TODO: seems like these should be mutating +/** + * ... + * \return ... + * \relates Piecewise + */ template Piecewise remove_short_cuts(Piecewise const &f, double tol) { if(f.empty()) return f; @@ -439,6 +465,11 @@ Piecewise remove_short_cuts(Piecewise const &f, double tol) { } //TODO: seems like these should be mutating +/** + * ... + * \return ... + * \relates Piecewise + */ template Piecewise remove_short_cuts_extending(Piecewise const &f, double tol) { if(f.empty()) return f; @@ -455,6 +486,11 @@ Piecewise remove_short_cuts_extending(Piecewise const &f, double tol) { return ret; } +/** + * ... + * \return ... + * \relates Piecewise + */ template std::vector roots(const Piecewise &pw) { std::vector ret; @@ -467,6 +503,11 @@ std::vector roots(const Piecewise &pw) { } //IMPL: OffsetableConcept +/** + * ... + * \return \f$ a + b = \f$ + * \relates Piecewise + */ template Piecewise operator+(Piecewise const &a, typename T::output_type b) { boost::function_requires >(); @@ -511,6 +552,11 @@ Piecewise& operator-=(Piecewise& a, typename T::output_type b) { } //IMPL: ScalableConcept +/** + * ... + * \return \f$ -a = \f$ + * \relates Piecewise + */ template Piecewise operator-(Piecewise const &a) { boost::function_requires >(); @@ -522,6 +568,11 @@ Piecewise operator-(Piecewise const &a) { ret.push_seg(- a[i]); return ret; } +/** + * ... + * \return \f$ a * b = \f$ + * \relates Piecewise + */ template Piecewise operator*(Piecewise const &a, double b) { boost::function_requires >(); @@ -535,6 +586,11 @@ Piecewise operator*(Piecewise const &a, double b) { ret.push_seg(a[i] * b); return ret; } +/** + * ... + * \return \f$ a * b = \f$ + * \relates Piecewise + */ template Piecewise operator*(Piecewise const &a, T b) { boost::function_requires >(); @@ -548,6 +604,11 @@ Piecewise operator*(Piecewise const &a, T b) { ret.push_seg(a[i] * b); return ret; } +/** + * ... + * \return \f$ a / b = \f$ + * \relates Piecewise + */ template Piecewise operator/(Piecewise const &a, double b) { boost::function_requires >(); @@ -582,6 +643,11 @@ Piecewise& operator/=(Piecewise& a, double b) { } //IMPL: AddableConcept +/** + * ... + * \return \f$ a + b = \f$ + * \relates Piecewise + */ template Piecewise operator+(Piecewise const &a, Piecewise const &b) { boost::function_requires >(); @@ -595,6 +661,11 @@ Piecewise operator+(Piecewise const &a, Piecewise const &b) { ret.push_seg(pa[i] + pb[i]); return ret; } +/** + * ... + * \return \f$ a - b = \f$ + * \relates Piecewise + */ template Piecewise operator-(Piecewise const &a, Piecewise const &b) { boost::function_requires >(); @@ -619,6 +690,11 @@ inline Piecewise& operator-=(Piecewise &a, Piecewise const &b) { return a; } +/** + * ... + * \return \f$ a \cdot b = \f$ + * \relates Piecewise + */ template Piecewise operator*(Piecewise const &a, Piecewise const &b) { //function_requires >(); @@ -635,6 +711,11 @@ Piecewise operator*(Piecewise const &a, Piecewise const &b) { return ret; } +/** + * ... + * \return \f$ a \cdot b \f$ + * \relates Piecewise + */ template inline Piecewise& operator*=(Piecewise &a, Piecewise const &b) { a = a * b; @@ -661,9 +742,14 @@ int compose_findSegIdx(std::map::iterator const &cut, std::vector const &levels, SBasis const &g); -//TODO: add concept check +/** + * ... + * \return ... + * \relates Piecewise + */ template Piecewise compose(Piecewise const &f, SBasis const &g){ + /// \todo add concept check Piecewise result; if (f.empty()) return result; if (g.isZero()) return Piecewise(f(0)); @@ -707,9 +793,14 @@ Piecewise compose(Piecewise const &f, SBasis const &g){ return(result); } -//TODO: add concept check for following composition functions +/** + * ... + * \return ... + * \relates Piecewise + */ template Piecewise compose(Piecewise const &f, Piecewise const &g){ +/// \todo add concept check Piecewise result; for(unsigned i = 0; i < g.segs.size(); i++){ Piecewise fgi=compose(f, g.segs[i]); @@ -721,6 +812,7 @@ Piecewise compose(Piecewise const &f, Piecewise const &g){ /* Piecewise > compose(D2 const &sb2d, Piecewise > const &pwd2sb){ +/// \todo add concept check Piecewise > result; result.push_cut(0.); for(unsigned i = 0; i < pwd2sb.size(); i++){ @@ -729,11 +821,26 @@ Piecewise > compose(D2 const &sb2d, Piecewise > return result; }*/ +/** Compose an SBasis with the inverse of another. + * WARNING: It's up to the user to check that the second SBasis is indeed + * invertible (i.e. strictly increasing or decreasing). + * \return \f$ f \cdot g^{-1} \f$ + * \relates Piecewise + */ +Piecewise pw_compose_inverse(SBasis const &f, SBasis const &g, unsigned order, double zero); + + + template Piecewise Piecewise::operator()(SBasis f){return compose((*this),f);} template Piecewise Piecewise::operator()(Piecewisef){return compose((*this),f);} +/** + * ... + * \return ... + * \relates Piecewise + */ template Piecewise integral(Piecewise const &a) { Piecewise result; @@ -748,6 +855,11 @@ Piecewise integral(Piecewise const &a) { return result; } +/** + * ... + * \return ... + * \relates Piecewise + */ template Piecewise derivative(Piecewise const &a) { Piecewise result; @@ -763,6 +875,19 @@ std::vector roots(Piecewise const &f); std::vector >multi_roots(Piecewise const &f, std::vector const &values); +//TODO: implement level_sets directly for pwsb instead of sb (and derive it fo sb). +//It should be faster than the reverse as the algorithm may jump over full cut intervals. +std::vector level_set(Piecewise const &f, Interval const &level, double tol=1e-5); +std::vector level_set(Piecewise const &f, double v, double vtol, double tol=1e-5); +//std::vector level_sets(Piecewise const &f, std::vector const &levels, double tol=1e-5); +//std::vector level_sets(Piecewise const &f, std::vector &v, double vtol, double tol=1e-5); + + +/** + * ... + * \return ... + * \relates Piecewise + */ template Piecewise reverse(Piecewise const &f) { Piecewise ret = Piecewise(); diff --git a/src/2geom/point.cpp b/src/2geom/point.cpp index 45e035d4a..9df88df92 100644 --- a/src/2geom/point.cpp +++ b/src/2geom/point.cpp @@ -1,25 +1,46 @@ -#include <2geom/point.h> #include -#include <2geom/coord.h> -#include <2geom/isnan.h> //temporary fix for isnan() +#include +#include <2geom/point.h> #include <2geom/transforms.h> namespace Geom { -/** \brief Scales this vector to make it a unit vector (within rounding error). +/** + * @class Point + * @brief Two-dimensional point that doubles as a vector. + * + * Points in 2Geom are represented in Cartesian coordinates, e.g. as a pair of numbers + * that store the X and Y coordinates. Each point is also a vector in \f$\mathbb{R}^2\f$ + * from the origin (point at 0,0) to the stored coordinates, + * and has methods implementing several vector operations (like length()). * - * The current version tries to handle infinite coordinates gracefully, - * but it's not clear that any callers need that. + * \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: + * @code + p += q; p -= q; r = p + q; r = p - q; + p *= s; p /= s; q = p * s; q = s * p; q = p / s; + p *= m; p /= m; q = p * m; q = m * p; q = p / m; + @endcode + * It is possible to left-multiply a point by a matrix, even though mathematically speaking + * this is undefined. The result is a point identical to that obtained by right-multiplying. + * Division of points by matrices is defined as multiplication by their inverses. * - * \pre \f$this \neq (0, 0)\f$ - * \pre Neither component is NaN. - * \post \f$-\epsilon<\left|this\right|-1<\epsilon\f$ - */ + * @ingroup Primitives */ + +/** @brief Normalize the vector representing the point. + * After this method returns, the length of the vector will be 1 (unless both coordinates are + * zero - the zero point will be returned then). The function tries to handle infinite + * coordinates gracefully. If any of the coordinates are NaN, the function will do nothing. + * @post \f$-\epsilon < \left|this\right| - 1 < \epsilon\f$ + * @see unit_vector(Geom::Point const &) */ void Point::normalize() { double len = hypot(_pt[0], _pt[1]); if(len == 0) return; if(IS_NAN(len)) return; - static double const inf = 1e400; + static double const inf = HUGE_VAL; if(len != inf) { *this /= len; } else { @@ -58,7 +79,10 @@ void Point::normalize() { } } -/** Compute the L1 norm, or manhattan distance, of \a p. */ +/** @brief Compute the first norm (Manhattan distance) of @a p. + * This is equal to the sum of absolutes values of the coordinates. + * @return \f$|p_X| + |p_Y|\f$ + * @relates Point */ Coord L1(Point const &p) { Coord d = 0; for ( int i = 0 ; i < 2 ; i++ ) { @@ -67,7 +91,9 @@ Coord L1(Point const &p) { return d; } -/** Compute the L infinity, or maximum, norm of \a p. */ +/** @brief Compute the infinity norm (maximum norm) of @a p. + * @return \f$\max(p_X, p_Y)\f$ + * @relates Point */ Coord LInfty(Point const &p) { Coord const a(fabs(p[0])); Coord const b(fabs(p[1])); @@ -76,80 +102,83 @@ Coord LInfty(Point const &p) { : a ); } -/** Returns true iff p is a zero vector, i.e.\ Point(0, 0). - * - * (NaN is considered non-zero.) - */ -bool -is_zero(Point const &p) -{ +/** @brief True if the point has both coordinates zero. + * NaNs are treated as not equal to zero. + * @relates Point */ +bool is_zero(Point const &p) { return ( p[0] == 0 && p[1] == 0 ); } -bool -is_unit_vector(Point const &p) -{ - return fabs(1.0 - L2(p)) <= 1e-4; - /* The tolerance of 1e-4 is somewhat arbitrary. 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. */ +/** @brief True if the point has a length near 1. The are_near() function is used. + * @relates Point */ +bool is_unit_vector(Point const &p) { + return are_near(L2(p), 1.0); } - -Coord atan2(Point const p) { +/** @brief Return the angle between the point and the +X axis. + * @return Angle in \f$(-\pi, \pi]\f$. + * @relates Point */ +Coord atan2(Point const &p) { return std::atan2(p[Y], p[X]); } -/** compute the angle turning from a to b. This should give \f$\pi/2\f$ for angle_between(a, rot90(a)); - * This works by projecting b onto the basis defined by a, rot90(a) - */ -Coord angle_between(Point const a, Point const b) { +/** @brief Compute the angle between a and b relative to the origin. + * The computation is done by projecting b onto the basis defined by a, rot90(a). + * @return Angle in \f$(-\pi, \pi]\f$. + * @relates Point */ +Coord angle_between(Point const &a, Point const &b) { return std::atan2(cross(b,a), dot(b,a)); } - - -/** 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. - */ +/** @brief Create a normalized version of a point. + * This is equivalent to copying the point and calling its normalize() method. + * The returned point will be (0,0) if the argument has both coordinates equal to zero. + * If any coordinate is NaN, this function will do nothing. + * @param a Input point + * @return Point on the unit circle in the same direction from origin as a, or the origin + * if a has both coordinates equal to zero + * @relates Point */ Point unit_vector(Point const &a) { Point ret(a); ret.normalize(); return ret; } - +/** @brief Return the "absolute value" of the point's vector. + * This is defined in terms of the default lexicographical ordering. If the point is "larger" + * that the origin (0, 0), its negation is returned. This corresponds to making the Y coordinate + * positive. 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. + * To check with some margin of error, use + * @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) { - Point ret; - for ( int i = 0 ; i < 2 ; i++ ) { - ret[i] = fabs(b[i]); - } + Point ret = b; + ret[Y] = fabs(ret[Y]); return ret; } -Point operator*(Point const &v, Matrix const &m) { - Point ret; +/** @brief Transform the point by the specified matrix. */ +Point &Point::operator*=(Affine const &m) { + double x = _pt[X], y = _pt[Y]; for(int i = 0; i < 2; i++) { - ret[i] = v[X] * m[i] + v[Y] * m[i + 2] + m[i + 4]; + _pt[i] = x * m[i] + y * m[i + 2] + m[i + 4]; } - return ret; -} - -Point operator/(Point const &p, Matrix const &m) { return p * m.inverse(); } - -Point &Point::operator*=(Matrix const &m) -{ - *this = *this * 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 + * is undefined. + * @return Point with the same distance from A as B, with a snapped angle. + * @post distance(A, B) == distance(A, result) + * @post angle_between(result - A, dir) == \f$2k\pi/n, k \in \mathbb{N}\f$ + * @relates Point */ Point constrain_angle(Point const &A, Point const &B, unsigned int n, Point const &dir) { // for special cases we could perhaps use explicit testing (which might be faster) diff --git a/src/2geom/point.h b/src/2geom/point.h index 562950525..97f5142e3 100644 --- a/src/2geom/point.h +++ b/src/2geom/point.h @@ -1,241 +1,367 @@ -#ifndef SEEN_Geom_POINT_H -#define SEEN_Geom_POINT_H - /** * \file - * \brief Defines a Cartesian 2D Point class. + * \brief Cartesian point / 2D vector and related operations + *//* + * Authors: + * Michael G. Sloan + * Nathan Hurst + * Krzysztof Kosiński + * + * 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 +#ifndef SEEN_Geom_POINT_H +#define SEEN_Geom_POINT_H +#include "config.h" +#include +#include +#include +#include <2geom/forward.h> #include <2geom/coord.h> -#include <2geom/isnan.h> -#include <2geom/utils.h> +#include <2geom/isnan.h> //temporary fix for isnan() +#include <2geom/math-utils.h> namespace Geom { -enum Dim2 { X=0, Y=1 }; - -class Matrix; - -/// Cartesian 2D point. -class Point { +class Point + : boost::additive< Point + , boost::totally_ordered< Point + , boost::multiplicative< Point, Coord + , boost::multiplicative< Point, Affine + , boost::multiplicative< Point, Translate + , boost::multiplicative< Point, Rotate + , boost::multiplicative< Point, Scale + , boost::multiplicative< Point, HShear + , boost::multiplicative< Point, VShear + > > > > > > > > > // this uses chaining so it looks weird, but works +{ Coord _pt[2]; - public: - /// The default constructor creates an Point(0,0) DO NOT RELY ON THIS, BEST NOT TO USE THIS CONSTRUCTOR - inline Point() +public: + /** Construct a point on the origin. */ + Point() { _pt[X] = _pt[Y] = 0; } - inline Point(Coord x, Coord y) { + /** Construct a point from its coordinates. */ + Point(Coord x, Coord y) { _pt[X] = x; _pt[Y] = y; } - - inline Point(Point const &p) { + Point(Point const &p) { for (unsigned i = 0; i < 2; ++i) _pt[i] = p._pt[i]; } - - inline Point &operator=(Point const &p) { + 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]; } + /// @name Access the coordinates of a point + /// @{ + Coord operator[](unsigned i) const { return _pt[i]; } + Coord &operator[](unsigned i) { return _pt[i]; } Coord operator[](Dim2 d) const throw() { return _pt[d]; } Coord &operator[](Dim2 d) throw() { return _pt[d]; } + /// @} - static inline Point polar(Coord angle, Coord radius) { - return Point(radius * std::cos(angle), radius * std::sin(angle)); - } - - inline Coord length() const { return hypot(_pt[0], _pt[1]); } + /// @name Vector operations + /// @{ + /** @brief Compute the distance from origin. + * @return Length of the vector from origin to this point */ + Coord length() const { return hypot(_pt[0], _pt[1]); } + void normalize(); - /** 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.) - **/ + /** @brief 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.) - **/ + /** @brief 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)(decimal_round((double)_pt[X], places)); - _pt[Y] = (Coord)(decimal_round((double)_pt[Y], places)); - return; - } - - void normalize(); - - inline bool isFinite() const { - for ( unsigned i = 0 ; i < 2 ; ++i ) { - if(!IS_FINITE(_pt[i])) return false; - } - return true; - } - - inline Point operator+(Point const &o) const { - return Point(_pt[X] + o._pt[X], _pt[Y] + o._pt[Y]); - } - inline Point operator-(Point const &o) const { - return Point(_pt[X] - o._pt[X], _pt[Y] - o._pt[Y]); + /// @name Vector-like arithmetic operations + /// @{ + Point operator-() const { + return Point(-_pt[X], -_pt[Y]); } - inline Point &operator+=(Point const &o) { + 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) { + Point &operator-=(Point const &o) { for ( unsigned i = 0 ; i < 2 ; ++i ) { _pt[i] -= o._pt[i]; } return *this; } - - inline Point operator-() const { - return Point(-_pt[X], -_pt[Y]); - } - inline Point operator*(double const s) const { - return Point(_pt[X] * s, _pt[Y] * s); - } - inline Point operator/(double const s) const { - //TODO: s == 0? - return Point(_pt[X] / s, _pt[Y] / s); - } - inline Point &operator*=(double const s) { + Point &operator*=(Coord s) { for ( unsigned i = 0 ; i < 2 ; ++i ) _pt[i] *= s; return *this; } - inline Point &operator/=(double const s) { + Point &operator/=(Coord s) { //TODO: s == 0? for ( unsigned i = 0 ; i < 2 ; ++i ) _pt[i] /= s; return *this; } + /// @} + + /// @name Affine transformations + /// @{ + Point &operator*=(Affine const &m); + // implemented in transforms.cpp + Point &operator*=(Translate const &t); + Point &operator*=(Scale const &s); + Point &operator*=(Rotate const &r); + Point &operator*=(HShear const &s); + Point &operator*=(VShear const &s); + /** @brief Transform the point by the inverse of the specified matrix. */ + template + Point &operator/=(T const &m) { + *this *= m.inverse(); + return *this; + } + /// @} + + /// @name Various utilities + /// @{ + /** @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; + } - Point &operator*=(Matrix const &m); - - inline int operator == (const Point &in_pnt) { + /** @brief Check whether both coordinates are finite. + * @return True if neither coordinate is infinite. */ + bool isFinite() const { + for ( unsigned i = 0 ; i < 2 ; ++i ) { + if(!IS_FINITE(_pt[i])) return false; + } + return true; + } + /** @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])); } + /** @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; + } + /// @} + + /** @brief Lexicographical ordering functor. */ + template struct LexOrder; + /** @brief Lexicographical ordering functor with runtime dimension. */ + class LexOrderRt { + public: + LexOrderRt(Dim2 d) : dim(d) {} + inline bool operator()(Point const &a, Point const &b); + private: + Dim2 dim; + }; friend inline std::ostream &operator<< (std::ostream &out_file, const Geom::Point &in_pnt); }; -inline Point operator*(double const s, Point const &p) { return p * s; } - -/** A function to print out the Point. It just prints out the coords - on the given output stream */ +/** @brief Output operator for points. + * Prints out the coordinates. + * @relates Point */ inline std::ostream &operator<< (std::ostream &out_file, const Geom::Point &in_pnt) { out_file << "X: " << in_pnt[X] << " Y: " << in_pnt[Y]; return out_file; } -/** 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; +template<> struct Point::LexOrder { + bool operator()(Point const &a, Point const &b) { + return a[X] < b[X] || (a[X] == b[X] && a[Y] < b[Y]); + } +}; +template<> struct Point::LexOrder { + bool operator()(Point const &a, Point const &b) { + return a[Y] < b[Y] || (a[Y] == b[Y] && a[X] < b[X]); + } +}; +inline bool Point::LexOrderRt::operator()(Point const &a, Point const &b) { + return dim ? Point::LexOrder()(a, b) : Point::LexOrder()(a, b); } -//IMPL: boost::EqualityComparableConcept -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]); +/** @brief Compute the second (Euclidean) norm of @a p. + * This corresponds to the length of @a p. The result will not overflow even if + * \f$p_X^2 + p_Y^2\f$ is larger that the maximum value that can be stored + * in a double. + * @return \f$\sqrt{p_X^2 + p_Y^2}\f$ + * @relates Point */ +inline Coord L2(Point const &p) +{ + return p.length(); } -/** This is a lexicographical ordering for points. It is remarkably useful for sweepline algorithms*/ -inline bool operator<=(Point const &a, Point const &b) { - return ( ( a[Y] < b[Y] ) || - (( a[Y] == b[Y] ) && ( a[X] < b[X] ))); +/** @brief Compute the square of the Euclidean norm of @a p. + * Warning: this can overflow where L2 won't. + * @return \f$p_X^2 + p_Y^2\f$ + * @relates Point */ +inline Coord L2sq(Point const &p) +{ + return p[0]*p[0] + p[1]*p[1]; } -Coord L1(Point const &p); - -/** Compute the L2, or euclidean, norm of \a p. */ -inline Coord L2(Point const &p) { return p.length(); } - -/** Compute the square of L2 norm of \a p. Warning: this can overflow where L2 won't.*/ -inline Coord L2sq(Point const &p) { return p[0]*p[0] + p[1]*p[1]; } - -double LInfty(Point const &p); -bool is_zero(Point const &p); -bool is_unit_vector(Point const &p); - -extern double atan2(Point const p); -/** compute the angle turning from a to b (signed). */ -extern double angle_between(Point const a, Point const b); - //IMPL: NearConcept -inline bool are_near(Point const &a, Point const &b, double const eps=EPSILON) { +/** @brief Nearness predicate for points. + * True if neither coordinate of @a a is further than @a eps from the corresponding + * coordinate of @a b. + * @relates Point */ +inline bool are_near(Point const &a, Point const &b, double const eps=EPSILON) +{ return ( are_near(a[X],b[X],eps) && are_near(a[Y],b[Y],eps) ); } -inline -Point middle_point(Point const& P1, Point const& P2) +/** @brief Return a point halfway between the specified ones. + * @relates Point */ +inline Point middle_point(Point const& P1, Point const& P2) { return (P1 + P2) / 2; } -/** Returns p * Geom::rotate_degrees(90), but more efficient. +/** @brief Returns p * Geom::rotate_degrees(90), but more efficient. * - * Angle direction in Inkscape code: If you use the traditional mathematics convention that y + * Angle direction in 2Geom: 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]); } + * There is no function to rotate by -90 degrees: use -rot90(p) instead. + * @relates Point */ +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. Akin to 1 degree bezier.*/ -inline Point lerp(double const t, Point const a, Point const b) { return (a * (1 - t) + b * t); } +/** @brief Linear interpolation between two points. + * @param t Time value + * @param a First point + * @param b Second point + * @return Point on a line between a and b. The ratio of its distance from a + * and the distance between a and b will be equal to t. + * @relates Point */ +inline Point lerp(double const t, Point const &a, Point const &b) +{ + return (a * (1 - t) + b * t); +} -Point unit_vector(Point const &a); +/** @brief Compute the dot product of a and b. + * Dot product can be interpreted as a measure of how parallel the vectors are. + * 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*/ +inline Coord dot(Point const &a, Point const &b) +{ + return a[0] * b[0] + a[1] * b[1]; +} -/** compute the dot product (inner product) between the vectors a and b. */ -inline Coord dot(Point const &a, Point const &b) { return a[0] * b[0] + a[1] * b[1]; } -/** Defined as dot(a, b.cw()). */ -inline Coord cross(Point const &a, Point const &b) { return dot(a, b.cw()); } +/** @brief Compute the 2D cross product. + * Defined as dot(a, b.cw()). This means it will be zero for parallel vectors, + * and its absolute value highest for perpendicular vectors. + * @relates Point*/ +inline Coord cross(Point const &a, Point const &b) +{ + return dot(a, b.cw()); +} -/** compute the euclidean distance between points a and b. TODO: hypot safer/faster? */ -inline Coord distance (Point const &a, Point const &b) { return L2(a - b); } +/** @brief Compute the (Euclidean) distance between points. + * @relates Point */ +inline Coord distance (Point const &a, Point const &b) +{ + return L2(a - b); +} -/** compute the square of the distance between points a and b. */ -inline Coord distanceSq (Point const &a, Point const &b) { return L2sq(a - b); } +/** @brief Compute the square of the distance between points. + * @relates Point */ +inline Coord distanceSq (Point const &a, Point const &b) +{ + return L2sq(a - b); +} +Point unit_vector(Point const &a); +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); Point abs(Point const &b); - -Point operator*(Point const &v, Matrix const &m); - -Point operator/(Point const &p, Matrix const &m); - -/** Constrains the angle (with respect to dir) of the line - * joining A and B to a multiple of pi/n. - */ Point constrain_angle(Point const &A, Point const &B, unsigned int n = 4, Geom::Point const &dir = Geom::Point(1,0)); } /* namespace Geom */ +// This is required to fix a bug in GCC 4.3.3 (and probably others) that causes the compiler +// to try to instantiate the iterator_traits template and fail. Probably it thinks that Point +// is an iterator and tries to use std::distance instead of Geom::distance. +namespace std { +template <> class iterator_traits {}; +} + #endif /* !SEEN_Geom_POINT_H */ /* diff --git a/src/2geom/poly.cpp b/src/2geom/poly.cpp index 9fa8e47db..de0229172 100644 --- a/src/2geom/poly.cpp +++ b/src/2geom/poly.cpp @@ -1,6 +1,5 @@ #include <2geom/poly.h> -#define HAVE_GSL #ifdef HAVE_GSL #include #endif diff --git a/src/2geom/poly.h b/src/2geom/poly.h index e0ba0580f..3567bda6d 100644 --- a/src/2geom/poly.h +++ b/src/2geom/poly.h @@ -34,6 +34,7 @@ #ifndef LIB2GEOM_SEEN_POLY_H #define LIB2GEOM_SEEN_POLY_H + #include #include #include @@ -205,11 +206,13 @@ Poly gcd(Poly const &a, Poly const &b, const double tol=1e-10); */ std::vector > solve(const Poly & p); +#ifdef HAVE_GSL /*** solve_reals(Poly p) * find all real solutions to Poly p. * currently we just use solve and pick out the suitably real looking values, there may be a better algorithm. */ std::vector solve_reals(const Poly & p); +#endif double polish_root(Poly const & p, double guess, double tol); inline std::ostream &operator<< (std::ostream &out_file, const Poly &in_poly) { diff --git a/src/2geom/ray.h b/src/2geom/ray.h index 3156a944d..638b86195 100644 --- a/src/2geom/ray.h +++ b/src/2geom/ray.h @@ -28,21 +28,30 @@ * the specific language governing rights and limitations. */ -#ifndef _2GEOM_RAY_H_ -#define _2GEOM_RAY_H_ +#ifndef LIB2GEOM_SEEN_RAY_H +#define LIB2GEOM_SEEN_RAY_H +#include #include <2geom/point.h> #include <2geom/bezier-curve.h> // for LineSegment #include <2geom/exception.h> -#include - - namespace Geom { -class Ray -{ +/** + * @brief Straight ray from a specific point to infinity. + * + * Rays are "half-lines" - they begin at some specific point and extend in a straight line + * to infinity. + * + * @ingroup Primitives + */ +class Ray { +private: + Point m_origin; + Point m_versor; + public: Ray() : m_origin(0,0), m_versor(1,0) @@ -183,22 +192,17 @@ public: return LineSegment(pointAt(f), pointAt(t)); } - Ray transformed(Matrix const& m) const + Ray transformed(Affine const& m) const { return Ray(m_origin * m, (m_origin + m_versor) * m); } - -private: - Point m_origin; - Point m_versor; - }; // end class ray inline double distance(Point const& _point, Ray const& _ray) { double t = _ray.nearestPoint(_point); - return distance(_point, _ray.pointAt(t)); + return ::Geom::distance(_point, _ray.pointAt(t)); } inline diff --git a/src/2geom/rect.h b/src/2geom/rect.h index cce1d64f0..65bb1bb76 100644 --- a/src/2geom/rect.h +++ b/src/2geom/rect.h @@ -1,8 +1,7 @@ /** * \file - * \brief D2 specialization to Rect - */ -/* + * \brief Axis-aligned rectangle + *//* * Copyright 2007 Michael Sloan * * This library is free software; you can redistribute it and/or @@ -28,9 +27,7 @@ * 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: + * Authors of original rect class: * Lauris Kaplinski * Nathan Hurst * bulia byak @@ -39,52 +36,81 @@ #include <2geom/d2.h> -#ifndef _2GEOM_RECT -#define _2GEOM_RECT +#ifndef LIB2GEOM_RECT_H +#define LIB2GEOM_RECT_H -#include <2geom/matrix.h> +#include <2geom/affine.h> #include namespace Geom { -/** D2 specialization to Rect */ + +/** + * @brief Axis-aligned, non-empty rectangle - convenience typedef + * @ingroup Primitives + */ typedef D2 Rect; class OptRect; -Rect unify(const Rect &, const Rect &); +inline Rect unify(Rect const &, Rect const &); + /** - * %Rect class. - * The Rect class is actually a specialisation of D2. - * + * @brief Axis aligned, non-empty rectangle. + * @ingroup Primitives */ template<> class D2 { - private: +private: Interval f[2]; - public: - /** Best not to use this constructor, do not rely on what it initializes the object to. - *The default constructor creates a rect of default intervals. - */ +public: + /// @name Create rectangles. + /// @{ + /** @brief Create a rectangle that contains only the point at (0,0). */ D2() { f[X] = f[Y] = Interval(); } - - public: + /** @brief Create a rectangle from X and Y intervals. */ D2(Interval const &a, Interval const &b) { f[X] = a; f[Y] = b; } - + /** @brief Create a rectangle from two points. */ D2(Point const & a, Point const & b) { f[X] = Interval(a[X], b[X]); f[Y] = Interval(a[Y], b[Y]); } + /** @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 + 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); + } + return result; + } + /** @brief Create a rectangle from a C-style array of points it should contain. */ + static Rect from_array(Point const *c, unsigned n) { + Rect result = Rect::from_range(c, c+n); + return result; + } + /// @} - inline Interval& operator[](unsigned i) { return f[i]; } - inline Interval const & operator[](unsigned i) const { return f[i]; } - - inline Point min() const { return Point(f[X].min(), f[Y].min()); } - inline Point max() const { return Point(f[X].max(), f[Y].max()); } + /// @name Inspect dimensions. + /// @{ + Interval& operator[](unsigned i) { return f[i]; } + Interval const & operator[](unsigned i) const { return f[i]; } - /** Returns the four corners of the rectangle in positive order - * (clockwise if +Y is up, anticlockwise if +Y is down) */ + 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()); @@ -95,17 +121,23 @@ class D2 { } //We should probably remove these - they're coord sys gnostic - inline double top() const { return f[Y].min(); } - inline double bottom() const { return f[Y].max(); } - inline double left() const { return f[X].min(); } - inline double right() const { return f[X].max(); } - - inline double width() const { return f[X].extent(); } - inline double height() const { return f[Y].extent(); } + /** @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(); } - /** Returns a vector from min to max. */ - inline Point dimensions() const { return Point(f[X].extent(), f[Y].extent()); } - inline Point midpoint() const { return Point(f[X].middle(), f[Y].middle()); } + /** @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. @@ -113,39 +145,92 @@ class D2 { * 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. */ - inline double area() const { return f[X].extent() * f[Y].extent(); } - inline bool hasZeroArea(double eps = EPSILON) const { return (area() <= eps); } + /** @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); } - inline double maxExtent() const { return std::max(f[X].extent(), f[Y].extent()); } - inline double minExtent() const { return std::min(f[X].extent(), f[Y].extent()); } + /** @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()); } + /// @} -// inline bool isEmpty() const { -// return f[X].isEmpty() || f[Y].isEmpty(); -// } - inline bool intersects(Rect const &r) const { - return f[X].intersects(r[X]) && f[Y].intersects(r[Y]); + /// @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]); } - inline bool contains(Rect const &r) const { - return f[X].contains(r[X]) && f[Y].contains(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]); } - inline bool contains(Point const &p) const { + /** @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]); } + /** @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]); + } + /// @} - inline void expandTo(Point p) { - f[X].extendTo(p[X]); f[Y].extendTo(p[Y]); + /// @name Modify the rectangle. + /// @{ + /** @brief Enlarge the rectangle to contain the given point. */ + void expandTo(Point p) { + f[X].expandTo(p[X]); f[Y].expandTo(p[Y]); } - inline void unionWith(Rect const &b) { - f[X].unionWith(b[X]); f[Y].unionWith(b[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); - - inline void expandBy(double amnt) { - f[X].expandBy(amnt); f[Y].expandBy(amnt); + + //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 -amount 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); } - inline void expandBy(Point const p) { - f[X].expandBy(p[X]); f[Y].expandBy(p[Y]); + /** @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 -p[X] 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]); } + /// @} }; inline Rect unify(Rect const & a, Rect const & b) { @@ -161,7 +246,7 @@ inline Rect union_list(std::vector const &r) { } inline -double distanceSq( Point const& p, Rect const& rect ) +Coord distanceSq( Point const& p, Rect const& rect ) { double dx = 0, dy = 0; if ( p[X] < rect.left() ) @@ -187,15 +272,14 @@ double distanceSq( Point const& p, Rect const& rect ) * Returns the smallest distance between p and rect. */ inline -double distance( Point const& p, Rect const& rect ) +Coord distance( Point const& p, Rect const& rect ) { return std::sqrt(distanceSq(p, rect)); } /** - * The OptRect class can represent and empty Rect and non-empty Rects. - * If OptRect is not empty, it means that both X and Y intervals are not empty. - * + * @brief Axis-aligned rectangle that can be empty. + * @ingroup Primitives */ class OptRect : public boost::optional { public: @@ -212,22 +296,25 @@ public: // else, stay empty. } - /** - * Check whether this OptRect is empty or not. - */ + /** @brief Check for emptiness. */ inline bool isEmpty() const { return (*this == false); }; - /** - * If \c this is empty, copy argument \c b. Otherwise, union with it (and do nothing when \c b is empty) - */ + 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 (b) { - if (*this) { // check that we are not empty - (**this)[X].unionWith((*b)[X]); - (**this)[Y].unionWith((*b)[Y]); - } else { - *this = b; - } + if (*this) { // check that we are not empty + (*this)->unionWith(b); + } else { + *this = b; } } }; @@ -256,6 +343,15 @@ inline void Rect::unionWith(OptRect const &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); +} } // end namespace Geom diff --git a/src/2geom/recursive-bezier-intersection.cpp b/src/2geom/recursive-bezier-intersection.cpp index 421f61308..b4c81e08e 100644 --- a/src/2geom/recursive-bezier-intersection.cpp +++ b/src/2geom/recursive-bezier-intersection.cpp @@ -63,7 +63,7 @@ void find_intersections_bezier_recursive( std::vector > &xs, vector const & A, vector const & B, - double precision) { + double /*precision*/) { OldBezier a, b; a.p = A; b.p = B; @@ -317,9 +317,9 @@ double Lmax(Point p) { return std::max(fabs(p[X]), fabs(p[Y])); } -unsigned wangs_theorem(OldBezier a) { +unsigned wangs_theorem(OldBezier /*a*/) { return 6; // seems a good approximation! - double la1 = Lmax( ( a.p[2] - a.p[1] ) - (a.p[1] - a.p[0]) ); + /*double la1 = Lmax( ( a.p[2] - a.p[1] ) - (a.p[1] - a.p[0]) ); double la2 = Lmax( ( a.p[3] - a.p[2] ) - (a.p[2] - a.p[1]) ); double l0 = std::max(la1, la2); unsigned ra; @@ -328,7 +328,7 @@ unsigned wangs_theorem(OldBezier a) { else ra = (unsigned)ceil( log4( M_SQRT2 * 6.0 / 8.0 * INV_EPS * l0 ) ); //std::cout << ra << std::endl; - return ra; + return ra;*/ } struct rparams @@ -337,7 +337,7 @@ struct rparams OldBezier &B; }; -static int +/*static int intersect_polish_f (const gsl_vector * x, void *params, gsl_vector * f) { @@ -351,22 +351,22 @@ intersect_polish_f (const gsl_vector * x, void *params, gsl_vector_set (f, 1, dx[1]); return GSL_SUCCESS; -} +}*/ -union dbl_64{ +/*union dbl_64{ long long i64; double d64; -}; +};*/ -static double EpsilonBy(double value, int eps) +/*static double EpsilonBy(double value, int eps) { dbl_64 s; s.d64 = value; s.i64 += eps; return s.d64; -} - +}*/ +/* static void intersect_polish_root (OldBezier &A, double &s, OldBezier &B, double &t) { const gsl_multiroot_fsolver_type *T; @@ -394,7 +394,7 @@ static void intersect_polish_root (OldBezier &A, double &s, iter++; status = gsl_multiroot_fsolver_iterate (sol); - if (status) /* check if solver is stuck */ + if (status) // check if solver is stuck break; status = @@ -439,7 +439,7 @@ static void intersect_polish_root (OldBezier &A, double &s, best_v = trial_v; } } -} +}*/ void find_intersections_bezier_recursive( std::vector > &xs, diff --git a/src/2geom/region.cpp b/src/2geom/region.cpp index 3c8c7fd1c..8cfb1c68c 100644 --- a/src/2geom/region.cpp +++ b/src/2geom/region.cpp @@ -5,9 +5,9 @@ namespace Geom { -Region Region::operator*(Matrix const &m) const { +Region Region::operator*(Affine const &m) const { Region r((m.flips() ? boundary.reverse() : boundary) * m, fill); - if(box && m.onlyScaleAndTranslation()) r.box = (*box) * m; + if(box && m.isZoom()) r.box = (*box) * m; return r; } diff --git a/src/2geom/region.h b/src/2geom/region.h index 937817595..e23d6a158 100644 --- a/src/2geom/region.h +++ b/src/2geom/region.h @@ -81,7 +81,7 @@ class Region { Region inverse() const { return Region(boundary.reverse(), box, !fill); } - Region operator*(Matrix const &m) const; + Region operator*(Affine const &m) const; bool invariants() const; }; diff --git a/src/2geom/sbasis-curve.h b/src/2geom/sbasis-curve.h index 6641c0fe1..22fe4fc1f 100644 --- a/src/2geom/sbasis-curve.h +++ b/src/2geom/sbasis-curve.h @@ -1,12 +1,13 @@ /** * \file - * \brief Symmetric Power Basis Curve - * + * \brief Symmetric power basis curve + *//* * Authors: - * MenTaLguY - * Marco Cecchetti + * MenTaLguY + * Marco Cecchetti + * Krzysztof Kosiński * - * Copyright 2007-2008 authors + * 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 @@ -32,75 +33,77 @@ * the specific language governing rights and limitations. */ - - - #ifndef _2GEOM_SBASIS_CURVE_H_ #define _2GEOM_SBASIS_CURVE_H_ - #include <2geom/curve.h> - +#include <2geom/nearest-point.h> +#include <2geom/sbasis-geometric.h> 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 + * in 2Geom. + * + * @ingroup Curves + */ class SBasisCurve : public Curve { - + private: - SBasisCurve(); - D2 inner; + SBasisCurve(); + D2 inner; public: - explicit SBasisCurve(D2 const &sb) : inner(sb) {} - explicit SBasisCurve(Curve const &other) : inner(other.toSBasis()) {} - Curve *duplicate() const { return new SBasisCurve(*this); } - - Point initialPoint() const { return inner.at0(); } - Point finalPoint() const { return inner.at1(); } - bool isDegenerate() const { return inner.isConstant(); } - Point pointAt(Coord t) const { return inner.valueAt(t); } - std::vector pointAndDerivatives(Coord t, unsigned n) const { - return inner.valueAndDerivatives(t, n); - } - double valueAt(Coord t, Dim2 d) const { return inner[d].valueAt(t); } - - void setInitial(Point v) { for(unsigned d = 0; d < 2; d++) { inner[d][0][0] = v[d]; } } - void setFinal(Point v) { for(unsigned d = 0; d < 2; d++) { inner[d][0][1] = v[d]; } } - - virtual OptRect boundsFast() const { return bounds_fast(inner); } - virtual OptRect boundsExact() const { return bounds_exact(inner); } - virtual OptRect boundsLocal(OptInterval i, unsigned deg) const { return bounds_local(inner, i, deg); } - - std::vector roots(double v, Dim2 d) const { return Geom::roots(inner[d] - v); } - - double nearestPoint( Point const& p, double from = 0, double to = 1 ) const - { - return nearest_point(p, inner, from, to); - } - - std::vector - allNearestPoints( Point const& p, double from = 0, double to = 1 ) const - { - return all_nearest_points(p, inner, from, to); - } - - Curve *portion(double f, double t) const { - return new SBasisCurve(Geom::portion(inner, f, t)); - } - - Curve *transformed(Matrix const &m) const { - return new SBasisCurve(inner * m); - } - - Curve *derivative() const { - return new SBasisCurve(Geom::derivative(inner)); - } - - D2 toSBasis() const { return inner; } - - virtual int degreesOfFreedom() const { return inner[0].degreesOfFreedom() + inner[1].degreesOfFreedom(); - } + explicit SBasisCurve(D2 const &sb) : inner(sb) {} + explicit SBasisCurve(Curve const &other) : inner(other.toSBasis()) {} + + virtual Curve *duplicate() const { return new SBasisCurve(*this); } + virtual Point initialPoint() const { return inner.at0(); } + virtual Point finalPoint() const { return inner.at1(); } + virtual bool isDegenerate() const { return inner.isConstant(); } + virtual Point pointAt(Coord t) const { return inner.valueAt(t); } + virtual std::vector pointAndDerivatives(Coord t, unsigned n) const { + return inner.valueAndDerivatives(t, n); + } + virtual Coord valueAt(Coord t, Dim2 d) const { return inner[d].valueAt(t); } + virtual void setInitial(Point const &v) { + for (unsigned d = 0; d < 2; d++) { inner[d][0][0] = v[d]; } + } + virtual void setFinal(Point const &v) { + for (unsigned d = 0; d < 2; d++) { inner[d][0][1] = v[d]; } + } + virtual Rect boundsFast() const { return *bounds_fast(inner); } + virtual Rect boundsExact() const { return *bounds_exact(inner); } + virtual OptRect boundsLocal(OptInterval const &i, unsigned deg) const { + return bounds_local(inner, i, deg); + } + virtual std::vector roots(Coord v, Dim2 d) const { return Geom::roots(inner[d] - v); } + virtual Coord nearestPoint( Point const& p, Coord from = 0, Coord to = 1 ) const { + return nearest_point(p, inner, from, to); + } + virtual std::vector allNearestPoints( Point const& p, Coord from = 0, + Coord to = 1 ) const + { + return all_nearest_points(p, inner, from, to); + } + virtual Coord length(Coord tolerance) const { return ::Geom::length(inner, tolerance); } + virtual Curve *portion(Coord f, Coord t) const { + return new SBasisCurve(Geom::portion(inner, f, t)); + } + virtual Curve *transformed(Affine const &m) const { return new SBasisCurve(inner * m); } + virtual Curve *derivative() const { + return new SBasisCurve(Geom::derivative(inner)); + } + virtual D2 toSBasis() const { return inner; } + virtual int degreesOfFreedom() const { + return inner[0].degreesOfFreedom() + inner[1].degreesOfFreedom(); + } }; diff --git a/src/2geom/sbasis-geometric.cpp b/src/2geom/sbasis-geometric.cpp index 3fd667224..f4b445faa 100644 --- a/src/2geom/sbasis-geometric.cpp +++ b/src/2geom/sbasis-geometric.cpp @@ -151,7 +151,7 @@ Geom::cutAtRoots(Piecewise > const &M, double ZERO){ \param vect a piecewise parameteric curve. \param tol the maximum error allowed. \param order the maximum degree to use for approximation - + \relates Piecewise */ Piecewise Geom::atan2(Piecewise > const &vect, double tol, unsigned order){ @@ -182,7 +182,7 @@ Geom::atan2(Piecewise > const &vect, double tol, unsigned order){ \param vect a piecewise parameteric curve. \param tol the maximum error allowed. \param order the maximum degree to use for approximation - + \relates Piecewise, D2 */ Piecewise Geom::atan2(D2 const &vect, double tol, unsigned order){ @@ -193,7 +193,7 @@ Geom::atan2(D2 const &vect, double tol, unsigned order){ \param angle a piecewise function of angle wrt t. \param tol the maximum error allowed. \param order the maximum degree to use for approximation - + \relates D2, SBasis */ D2 > Geom::tan2(SBasis const &angle, double tol, unsigned order){ @@ -204,7 +204,7 @@ Geom::tan2(SBasis const &angle, double tol, unsigned order){ \param angle a piecewise function of angle wrt t. \param tol the maximum error allowed. \param order the maximum degree to use for approximation - + \relates Piecewise, D2 */ D2 > Geom::tan2(Piecewise const &angle, double tol, unsigned order){ @@ -218,6 +218,8 @@ Geom::tan2(Piecewise const &angle, double tol, unsigned order){ unitVector(x,y) is computed as (b,-a) where a and b are solutions of: ax+by=0 (eqn1) and a^2+b^2=1 (eqn2) + + \relates Piecewise, D2 */ Piecewise > Geom::unitVector(D2 const &V_in, double tol, unsigned order){ @@ -296,6 +298,8 @@ Geom::unitVector(D2 const &V_in, double tol, unsigned order){ unitVector(x,y) is computed as (b,-a) where a and b are solutions of: ax+by=0 (eqn1) and a^2+b^2=1 (eqn2) + + \relates Piecewise */ Piecewise > Geom::unitVector(Piecewise > const &V, double tol, unsigned order){ @@ -314,7 +318,7 @@ Geom::unitVector(Piecewise > const &V, double tol, unsigned order){ /** returns a function giving the arclength at each point in M. \param M the Element. \param tol the maximum error allowed. - + \relates Piecewise */ Piecewise Geom::arcLengthSb(Piecewise > const &M, double tol){ @@ -328,7 +332,7 @@ Geom::arcLengthSb(Piecewise > const &M, double tol){ /** returns a function giving the arclength at each point in M. \param M the Element. \param tol the maximum error allowed. - + \relates Piecewise, D2 */ Piecewise Geom::arcLengthSb(D2 const &M, double tol){ @@ -353,9 +357,8 @@ Geom::length(Piecewise > const &M, /** returns a function giving the curvature at each point in M. \param M the Element. \param tol the maximum error allowed. - - Todo: - * claimed incomplete. Check. + \relates Piecewise, D2 + \todo claimed incomplete. Check. */ Piecewise Geom::curvature(D2 const &M, double tol) { @@ -371,9 +374,8 @@ Geom::curvature(D2 const &M, double tol) { /** returns a function giving the curvature at each point in M. \param M the Element. \param tol the maximum error allowed. - - Todo: - * claimed incomplete. Check. + \relates Piecewise + \todo claimed incomplete. Check. */ Piecewise Geom::curvature(Piecewise > const &V, double tol){ @@ -395,7 +397,7 @@ Geom::curvature(Piecewise > const &V, double tol){ \param M the Element. \param tol the maximum error allowed. \param order the maximum degree to use for approximation - + \relates Piecewise, D2 */ Piecewise > Geom::arc_length_parametrization(D2 const &M, @@ -424,7 +426,7 @@ Geom::arc_length_parametrization(D2 const &M, \param M the Element. \param tol the maximum error allowed. \param order the maximum degree to use for approximation - + \relates Piecewise */ Piecewise > Geom::arc_length_parametrization(Piecewise > const &M, @@ -449,7 +451,7 @@ static double sb_length_integrating(double t, void* param) { \param tol the maximum error allowed. \param result variable to be incremented with the length of the path \param abs_error variable to be incremented with the estimated error - + \relates D2 If you only want the length, this routine may be faster/more accurate. */ void Geom::length_integrating(D2 const &B, double &result, double &abs_error, double tol) { @@ -474,7 +476,7 @@ void Geom::length_integrating(D2 const &B, double &result, double &abs_e /** Calculates the length of a D2 through gsl integration. \param s the Element. \param tol the maximum error allowed. - + \relates D2 If you only want the total length, this routine faster and more accurate than constructing an arcLengthSb. */ double @@ -488,7 +490,7 @@ Geom::length(D2 const &s, /** Calculates the length of a Piecewise > through gsl integration. \param s the Element. \param tol the maximum error allowed. - + \relates Piecewise If you only want the total length, this routine faster and more accurate than constructing an arcLengthSb. */ double @@ -507,7 +509,7 @@ Geom::length(Piecewise > const &s, \param p the Element. \param centroid on return contains the centroid of the shape \param area on return contains the signed area of the shape. - + \relates Piecewise This approach uses green's theorem to compute the area and centroid using integrals. For curved shapes this is much faster than converting to polyline. Note that without an uncross operation the output is not the absolute area. * Returned values: @@ -620,6 +622,8 @@ solve_lambda0(double a0,double a1,double c0,double c1, * proportional to the given ones. * If insist_on_speed_signs == 0, allow speeds to point in the opposite direction (both at the same time) * If insist_on_speed_signs == -1, allow speeds to point in both direction independantly. +* +* \relates D2 */ std::vector > Geom::cubics_fitting_curvature(Point const &M0, Point const &M1, @@ -743,6 +747,7 @@ Geom::cubics_with_prescribed_curvature(Point const &M0, Point const &M1, /** * \brief returns all the parameter values of A whose tangent passes through P. +* \relates D2 */ std::vector find_tangents(Point P, D2 const &A) { SBasis crs (cross(A - P, derivative(A))); diff --git a/src/2geom/sbasis-roots.cpp b/src/2geom/sbasis-roots.cpp index 95fd0cf3b..1b870d88f 100644 --- a/src/2geom/sbasis-roots.cpp +++ b/src/2geom/sbasis-roots.cpp @@ -74,7 +74,7 @@ OptInterval bounds_exact(SBasis const &a) { SBasis df = derivative(a); vectorextrema = roots(df); for (unsigned i=0; i > multi_roots(SBasis const &f, return(roots); } + + +static bool compareIntervalMin( Interval I, Interval J ){ + return I.min()= x +static unsigned upper_level(vector const &levels, double x ){ + return( lower_bound( levels.begin(), levels.end(), Interval(x,x), compareIntervalMax) - levels.begin() ); +} + +static std::vector fuseContiguous(std::vector const &sets, double tol=0.){ + std::vector result; + if (sets.size() == 0 ) return result; + result.push_back( sets.front() ); + for (unsigned i=1; i < sets.size(); i++ ){ + if ( result.back().max() + tol >= sets[i].min() ){ + result.back().unionWith( sets[i] ); + }else{ + result.push_back( sets[i] ); + } + } + return result; +} + +/** level_sets internal method. +* algorithm: (~adaptation of Newton method versus 'accroissements finis') + -compute f at both ends of the given segment [a,b]. + -compute bounds m const &levels, + std::vector > &solsets, + double a, + double fa, + double b, + double fb, + double tol=1e-5){ + + if (f.size()==0){ + unsigned idx; + idx=upper_level( levels, 0. ); + if (idxtb_hi + double tb_lo; // f remains above next level for t>tb_lo + + ta_hi=ta_lo=b+1;//default values => no root there. + tb_hi=tb_lo=a-1;//default values => no root there. + + //--- if f(a) belongs to a level.------- + if ( idxa < levels.size() && levels[idxa].contains( fa ) ){ + //find the first time when we may exit this level. + ta_lo = a + ( levels[idxa].min() - fa)/bs.min(); + ta_hi = a + ( levels[idxa].max() - fa)/bs.max(); + if ( ta_lo < a || ta_lo > b ) ta_lo = b; + if ( ta_hi < a || ta_hi > b ) ta_hi = b; + //move to that time for the next iteration. + solsets[idxa].push_back( Interval( a, std::min( ta_lo, ta_hi ) ) ); + }else{ + //--- if f(b) does not belong to a level.------- + if ( idxa == 0 ){ + ta_lo = b; + }else{ + ta_lo = a + ( levels[idxa-1].max() - fa)/bs.min(); + if ( ta_lo < a ) ta_lo = b; + } + if ( idxa == levels.size() ){ + ta_hi = b; + }else{ + ta_hi = a + ( levels[idxa].min() - fa)/bs.max(); + if ( ta_hi < a ) ta_hi = b; + } + } + + //--- if f(b) belongs to a level.------- + if (idxb b || tb_lo < a ) tb_lo = a; + if ( tb_hi > b || tb_hi < a ) tb_hi = a; + //move to that time for the next iteration. + solsets[idxb].push_back( Interval( std::max( tb_lo, tb_hi ), b) ); + }else{ + //--- if f(b) does not belong to a level.------- + if ( idxb == 0 ){ + tb_lo = a; + }else{ + tb_lo = b + ( levels[idxb-1].max() - fb)/bs.max(); + if ( tb_lo > b ) tb_lo = a; + } + if ( idxb == levels.size() ){ + tb_hi = a; + }else{ + tb_hi = b + ( levels[idxb].min() - fb)/bs.min(); + if ( tb_hi > b ) tb_hi = a; + } + + + if ( bs.min() < 0 && idxb < levels.size() ) + tb_hi = b + ( levels[idxb ].min() - fb ) / bs.min(); + if ( bs.max() > 0 && idxb > 0 ) + tb_lo = b + ( levels[idxb-1].max() - fb ) / bs.max(); + } + + //let [t0,t1] be the next interval where to search. + double t0=std::min(ta_hi,ta_lo); + double t1=std::max(tb_hi,tb_lo); + + if (t0>=t1) return;//no root here. + + //if the interval is smaller than our resolution: + //pretend f simultaneously meets all the levels between f(t0) and f(t1)... + if ( t1 - t0 <= tol ){ + Interval f_t0t1 ( f(t0), f(t1) ); + unsigned idxmin = std::min(idxa, idxb); + unsigned idxmax = std::max(idxa, idxb); + //push [t0,t1] into all crossed level. Cheat to avoid overlapping intervals on different levels? + if ( idxmax > idxmin ){ + for (unsigned idx = idxmin; idx < idxmax; idx++){ + solsets[idx].push_back( Interval( t0, t1 ) ); + } + } + if ( idxmax < levels.size() && f_t0t1.intersects( levels[idxmax] ) ){ + solsets[idxmax].push_back( Interval( t0, t1 ) ); + } + return; + } + + //To make sure we finally exit the level jump at least by tol: + t0 = std::min( std::max( t0, a + tol ), b ); + t1 = std::max( std::min( t1, b - tol ), a ); + + double t =(t0+t1)/2; + double ft=f(t); + level_sets_internal( f, df, levels, solsets, t0, f(t0), t, ft ); + level_sets_internal( f, df, levels, solsets, t, ft, t1, f(t1) ); +} + +std::vector > level_sets(SBasis const &f, + std::vector const &levels, + double a, double b, double tol){ + + std::vector > solsets(levels.size(), std::vector()); + + SBasis df=derivative(f); + level_sets_internal(f,df,levels,solsets,a,f(a),b,f(b),tol); + // Fuse overlapping intervals... + for (unsigned i=0; i level_set (SBasis const &f, double level, double vtol, double a, double b, double tol){ + Interval fat_level( level - vtol, level + vtol ); + return level_set(f, fat_level, a, b, tol); +} +std::vector level_set (SBasis const &f, Interval const &level, double a, double b, double tol){ + std::vector levels(1,level); + return level_sets(f,levels, a, b, tol).front() ; +} +std::vector > level_sets (SBasis const &f, std::vector const &levels, double vtol, double a, double b, double tol){ + std::vector fat_levels( levels.size(), Interval()); + for (unsigned i = 0; i < levels.size(); i++){ + fat_levels[i] = Interval( levels[i]-vtol, levels[i]+vtol); + } + return level_sets(f, fat_levels, a, b, tol); +} + + +//------------------------------------- //------------------------------------- @@ -358,6 +563,17 @@ std::vector roots1(SBasis const & s) { return res; } +std::vector roots1(SBasis const & s, Interval const ivl) { + std::vector res; + double d = s[0][0] - s[0][1]; + if(d != 0) { + double r = s[0][0] / d; + if(ivl.contains(r)) + res.push_back(r); + } + return res; +} + /** Find all t s.t s(t) = 0 \param a sbasis function \returns vector of zeros (roots) @@ -377,6 +593,20 @@ std::vector roots(SBasis const & s) { } } } +std::vector roots(SBasis const & s, Interval const ivl) { + switch(s.size()) { + case 0: + return std::vector(); + case 1: + return roots1(s, ivl); + default: + { + Bezier bz; + sbasis_to_bezier(bz, s); + return bz.roots(ivl); + } + } +} }; diff --git a/src/2geom/sbasis.h b/src/2geom/sbasis.h index d7390c64d..b1b0b6c2a 100644 --- a/src/2geom/sbasis.h +++ b/src/2geom/sbasis.h @@ -63,7 +63,10 @@ class SBasis : public SBasisN<1>; namespace Geom{ -/*** An empty SBasis is identically 0. */ +/** +* \brief S-power basis function class +* +* An empty SBasis is identically 0. */ class SBasis{ std::vector d; void push_back(Linear const&l) { d.push_back(l); } @@ -125,8 +128,9 @@ public: } inline bool isConstant() const { if (empty()) return true; - for (unsigned i = 0; i < size(); i++) { - if(!(*this)[i].isConstant()) return false; + if(!(*this)[0].isConstant()) return false; + for (unsigned i = 1; i < size(); i++) { + if(!(*this)[i].isZero()) return false; } return true; } @@ -188,6 +192,7 @@ OptInterval bounds_local(SBasis const &a, const OptInterval &t, int order = 0); /** Returns a function which reverses the domain of a. \param a sbasis function + \relates SBasis useful for reversing a parameteric curve. */ @@ -312,7 +317,8 @@ inline SBasis& operator*=(SBasis& a, SBasis const & b) { /** Returns the degree of the first non zero coefficient. \param a sbasis function \param tol largest abs val considered 0 - \returns first non zero coefficient + \return first non zero coefficient + \relates SBasis */ inline unsigned valuation(SBasis const &a, double tol=0){ @@ -333,10 +339,10 @@ SBasis inverse(SBasis a, int k); SBasis compose_inverse(SBasis const &f, SBasis const &g, unsigned order=2, double tol=1e-3); /** Returns the sbasis on domain [0,1] that was t on [from, to] - \param a sbasis function + \param t sbasis function \param from,to interval - \returns sbasis - + \return sbasis + \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])); } @@ -364,13 +370,75 @@ SBasis sin(Linear bo, int k); SBasis cos(Linear bo, int k); std::vector roots(SBasis const & s); +std::vector roots(SBasis const & s, Interval const inside); std::vector > multi_roots(SBasis const &f, std::vector const &levels, double htol=1e-7, double vtol=1e-7, double a=0, double b=1); - + +//--------- Levelset like functions ----------------------------------------------------- + +/** Solve f(t) = v +/- tolerance. The collection of intervals where + * v - vtol <= f(t) <= v+vtol + * is returned (with a precision tol on the boundaries). + \param f sbasis function + \param level the value of v. + \param vtol: error tolerance on v. + \param a, b limit search on domain [a,b] + \param tol: tolerance on the result bounds. + \returns a vector of intervals. +*/ +std::vector level_set (SBasis const &f, + double level, + double vtol = 1e-5, + double a=0., + double b=1., + double tol = 1e-5); + +/** Solve f(t)\in I=[u,v], which defines a collection of intervals (J_k). More precisely, + * a collection (J'_k) is returned with J'_k = J_k up to a given tolerance. + \param f sbasis function + \param level: the given interval of deisred values for f. + \param a, b limit search on domain [a,b] + \param tol: tolerance on the bounds of the result. + \returns a vector of intervals. +*/ +std::vector level_set (SBasis const &f, + Interval const &level, + double a=0., + double b=1., + double tol = 1e-5); + +/** 'Solve' f(t) = v +/- tolerance for several values of v at once. + \param f sbasis function + \param levels vector of values, that should be sorted. + \param vtol: error tolerance on v. + \param a, b limit search on domain [a,b] + \param tol: the bounds of the returned intervals are exact up to that tolerance. + \returns a vector of vectors of intervals. +*/ +std::vector > level_sets (SBasis const &f, + std::vector const &levels, + double a=0., + double b=1., + double vtol = 1e-5, + double tol = 1e-5); + +/** 'Solve' f(t)\in I=[u,v] for several intervals I at once. + \param f sbasis function + \param levels vector of 'y' intervals, that should be disjoints and sorted. + \param a, b limit search on domain [a,b] + \param tol: the bounds of the returned intervals are exact up to that tolerance. + \returns a vector of vectors of intervals. +*/ +std::vector > level_sets (SBasis const &f, + std::vector const &levels, + double a=0., + double b=1., + double tol = 1e-5); + } #endif diff --git a/src/2geom/shape.cpp b/src/2geom/shape.cpp index 92af814cb..e9f5e55dc 100644 --- a/src/2geom/shape.cpp +++ b/src/2geom/shape.cpp @@ -622,7 +622,7 @@ Shape sanitize(std::vector const & ps) { /* This transforms a shape by a matrix. In the case that the matrix flips * the shape, it reverses the paths in order to preserve the fill. */ -Shape Shape::operator*(Matrix const &m) const { +Shape Shape::operator*(Affine const &m) const { Shape ret; for(unsigned i = 0; i < size(); i++) ret.content.push_back(content[i] * m); diff --git a/src/2geom/shape.h b/src/2geom/shape.h index 960f9668b..0a7ee9709 100644 --- a/src/2geom/shape.h +++ b/src/2geom/shape.h @@ -89,7 +89,7 @@ class Shape { const Region &operator[](unsigned ix) const { return content[ix]; } Shape inverse() const; - Shape operator*(Matrix const &m) const; + Shape operator*(Affine const &m) const; bool contains(Point const &p) const; diff --git a/src/2geom/solve-bezier-one-d.cpp b/src/2geom/solve-bezier-one-d.cpp index 876c483fe..c74e3243c 100644 --- a/src/2geom/solve-bezier-one-d.cpp +++ b/src/2geom/solve-bezier-one-d.cpp @@ -1,7 +1,12 @@ + #include <2geom/solver.h> +#include <2geom/choose.h> +#include <2geom/bezier.h> #include <2geom/point.h> + +#include #include -#include +//#include /*** Find the zeros of the bernstein function. The code subdivides until it is happy with the * linearity of the function. This requires an O(degree^2) subdivision for each step, even when @@ -11,176 +16,208 @@ namespace Geom{ template -static int SGN(t x) { return (x > 0 ? 1 : (x < 0 ? -1 : 0)); } +static int SGN(t x) { return (x > 0 ? 1 : (x < 0 ? -1 : 0)); } -const unsigned MAXDEPTH = 23; // Maximum depth for recursion. Using floats means 23 bits precision max +//const unsigned MAXDEPTH = 23; // Maximum depth for recursion. Using floats means 23 bits precision max -const double BEPSILON = ldexp(1.0,(-MAXDEPTH-1)); /*Flatness control value */ -const double SECANT_EPSILON = 1e-13; // secant method converges much faster, get a bit more precision +//const double BEPSILON = ldexp(1.0,(-MAXDEPTH-1)); /*Flatness control value */ +//const double SECANT_EPSILON = 1e-13; // secant method converges much faster, get a bit more precision /** * This function is called _a lot_. We have included various manual memory management stuff to reduce the amount of mallocing that goes on. In the future it is possible that this will hurt performance. **/ class Bernsteins{ public: - double *Vtemp; - unsigned N,degree; + static const size_t MAX_DEPTH = 22; + size_t degree, N; std::vector &solutions; - bool use_secant; - Bernsteins(int degr, std::vector &so) : N(degr+1), degree(degr),solutions(so), use_secant(false) { - Vtemp = new double[N*2]; - } - ~Bernsteins() { - delete[] Vtemp; + //std::vector bc; + BinomialCoefficient bc; + + Bernsteins(size_t _degree, std::vector & sol) + : degree(_degree), N(degree+1), solutions(sol), bc(degree) + { } + void subdivide(double const *V, double t, double *Left, double *Right); - double horner(const double *b, double t); - - unsigned + unsigned control_poly_flat_enough(double const *V); + double horner(const double *b, double t); + + void find_bernstein_roots(double const *w, /* The control points */ unsigned depth, /* The depth of the recursion */ double left_t, double right_t); }; /* - * find_bernstein_roots : Given an equation in Bernstein-Bernstein form, find all + * find_bernstein_roots : Given an equation in Bernstein-Bernstein form, find all * of the roots in the open interval (0, 1). Return the number of roots found. */ void find_bernstein_roots(double const *w, /* The control points */ - unsigned degree, /* The degree of the polynomial */ + unsigned degree, /* The degree of the polynomial */ std::vector &solutions, /* RETURN candidate t-values */ - unsigned depth, /* The depth of the recursion */ - double left_t, double right_t, bool use_secant) -{ + unsigned depth, /* The depth of the recursion */ + double left_t, double right_t, bool /*use_secant*/) +{ Bernsteins B(degree, solutions); - B.use_secant = use_secant; B.find_bernstein_roots(w, depth, left_t, right_t); } void -Bernsteins::find_bernstein_roots(double const *w, /* The control points */ - unsigned depth, /* The depth of the recursion */ - double left_t, double right_t) +find_bernstein_roots(std::vector &solutions, /* RETURN candidate t-values */ + Geom::Bezier const& bz, /* The control points */ + double left_t, double right_t) +{ + Bernsteins B(bz.degree(), solutions); + Geom::Bezier& bzl = const_cast(bz); + double* w = &(bzl[0]); + B.find_bernstein_roots(w, 0, left_t, right_t); +} + + + +void Bernsteins::find_bernstein_roots(double const *w, /* The control points */ + unsigned depth, /* The depth of the recursion */ + double left_t, + double right_t) { - unsigned n_crossings = 0; /* Number of zero-crossings */ - + size_t n_crossings = 0; + int old_sign = SGN(w[0]); - for (unsigned i = 1; i < N; i++) { - int sign = SGN(w[i]); - if (sign) { - if (sign != old_sign && old_sign) { - n_crossings++; + //std::cout << "w[0] = " << w[0] << std::endl; + int sign; + for (size_t i = 1; i < N; i++) + { + //std::cout << "w[" << i << "] = " << w[i] << std::endl; + sign = SGN(w[i]); + if (sign != 0) + { + if (sign != old_sign && old_sign != 0) + { + ++n_crossings; } old_sign = sign; } } - - if (n_crossings == 0) // no solutions here - return; - - if (n_crossings == 1) { - /* Unique solution */ - /* Stop recursion when the tree is deep enough */ + //std::cout << "n_crossings = " << n_crossings << std::endl; + if (n_crossings == 0) return; // no solutions here + + if (n_crossings == 1) /* Unique solution */ + { + //std::cout << "depth = " << depth << std::endl; + /* Stop recursion when the tree is deep enough */ /* if deep enough, return 1 solution at midpoint */ - if (depth >= MAXDEPTH) { + if (depth > MAX_DEPTH) + { //printf("bottom out %d\n", depth); const double Ax = right_t - left_t; const double Ay = w[degree] - w[0]; - + solutions.push_back(left_t - Ax*w[0] / Ay); return; - solutions.push_back((left_t + right_t) / 2.0); - return; } - - // I thought secant method would be faster here, but it'aint. -- njh - // Actually, it was, I just was using the wrong method for bezier evaluation. Horner's rule results in a very efficient algorithm - 10* faster (20080816) - // Future work: try using brent's method - if(use_secant) { // false position - double s = 0;double t = 1; - double e = 1e-10; - int n,side=0; - double r,fr,fs = w[0],ft = w[degree]; - - for (n = 1; n <= 100; n++) + + + double s = 0, t = 1; + double e = 1e-10; + int side = 0; + double r, fr, fs = w[0], ft = w[degree]; + + for (size_t n = 0; n < 100; ++n) + { + r = (fs*t - ft*s) / (fs - ft); + if (fabs(t-s) < e * fabs(t+s)) break; + + fr = horner(w, r); + + if (fr * ft > 0) { - r = (fs*t - ft*s) / (fs - ft); - if (fabs(t-s) < e*fabs(t+s)) break; - fr = horner(w, r); - - if (fr * ft > 0) - { - t = r; ft = fr; - if (side==-1) fs /= 2; - side = -1; - } - else if (fs * fr > 0) - { - s = r; fs = fr; - if (side==+1) ft /= 2; - side = +1; - } - else break; + t = r; ft = fr; + if (side == -1) fs /= 2; + side = -1; } - solutions.push_back(r*right_t + (1-r)*left_t); - return; + else if (fs * fr > 0) + { + s = r; fs = fr; + if (side == +1) ft /= 2; + side = +1; + } + else break; } + solutions.push_back(r*right_t + (1-r)*left_t); + return; + } /* Otherwise, solve recursively after subdividing control polygon */ - std::valarray new_controls(2*N); // New left and right control polygons - const double t = 0.5; +// double Left[N], /* New left and right */ +// Right[N]; /* control polygons */ + //const double t = 0.5; + double* LR = new double[2*N]; + double* Left = LR; + double* Right = LR + N; + std::copy(w, w + N, Right); -/* - * Bernstein : - * Evaluate a Bernstein function at a particular parameter value - * Fill in control points for resulting sub-curves. - * - */ - for (unsigned i = 0; i < N; i++) - Vtemp[i] = w[i]; - - /* Triangle computation */ - const double omt = (1-t); - new_controls[0] = Vtemp[0]; - new_controls[N+degree] = Vtemp[degree]; - double *prev_row = Vtemp; - double *row = Vtemp + N; - for (unsigned i = 1; i < N; i++) { - for (unsigned j = 0; j < N - i; j++) { - row[j] = omt*prev_row[j] + t*prev_row[j+1]; + Left[0] = Right[0]; + for (size_t i = 1; i < N; ++i) + { + for (size_t j = 0; j < N-i; ++j) + { + Right[j] = (Right[j] + Right[j+1]) * 0.5; } - new_controls[i] = row[0]; - new_controls[N+degree-i] = row[degree-i]; - std::swap(prev_row, row); + Left[i] = Right[0]; } - - double mid_t = left_t*(1-t) + right_t*t; - - find_bernstein_roots(&new_controls[0], depth+1, left_t, mid_t); - + + double mid_t = (left_t + right_t) * 0.5; + + + find_bernstein_roots(Left, depth+1, left_t, mid_t); + + /* Solution is exactly on the subdivision point. */ - if (new_controls[N] == 0) + if (Right[0] == 0) + { solutions.push_back(mid_t); - - find_bernstein_roots(&new_controls[N], depth+1, mid_t, right_t); + } + + find_bernstein_roots(Right, depth+1, mid_t, right_t); + delete[] LR; } + +// suggested by Sederberg. +double Bernsteins::horner(const double *b, double t) +{ + double u, tn, tmp; + u = 1.0 - t; + tn = 1.0; + tmp = b[0] * u; + for(size_t i = 1; i < degree; ++i) + { + tn *= t; + tmp = (tmp + tn*bc[i]*b[i]) * u; + } + return (tmp + tn*t*b[degree]); +} + + + +#if 0 /* * control_poly_flat_enough : * Check if the control polygon of a Bernstein curve is flat enough * for recursive subdivision to bottom out. * */ -unsigned +unsigned Bernsteins::control_poly_flat_enough(double const *V) { /* Find the perpendicular distance from each interior control point to line connecting V[0] and @@ -204,7 +241,7 @@ Bernsteins::control_poly_flat_enough(double const *V) else max_distance_above = std::max(max_distance_above, dist); } - + const double abSquared = 1./((a * a) + 1); const double intercept_1 = (a - max_distance_above * abSquared); @@ -218,23 +255,7 @@ Bernsteins::control_poly_flat_enough(double const *V) //printf("error %g %g %g\n", error, a, BEPSILON * a); return error < BEPSILON * a; } - -// suggested by Sederberg. -double Bernsteins::horner(const double *b, double t) { - int n = degree; - double u, bc, tn, tmp; - int i; - u = 1.0 - t; - bc = 1; - tn = 1; - tmp = b[0]*u; - for(i=1; i - * + * * Copyright ?-? authors * * This library is free software; you can redistribute it and/or @@ -37,9 +37,14 @@ #include <2geom/point.h> #include <2geom/sbasis.h> + +#include + + namespace Geom{ class Point; + class Bezier; unsigned crossing_count(Geom::Point const *V, /* Control pts of Bezier curve */ @@ -55,6 +60,8 @@ unsigned crossing_count(double const *V, /* Control pts of Bezier curve */ unsigned degree, /* Degree of Bezier curve */ double left_t, double right_t); + + void find_bernstein_roots( double const *w, /* The control points */ @@ -64,6 +71,12 @@ find_bernstein_roots( double left_t=0, double right_t=1, bool use_secant=true); }; + +void +find_bernstein_roots(std::vector &solutions, /* RETURN candidate t-values */ + Geom::Bezier const& bz, + double left_t, double right_t); + #endif /* diff --git a/src/2geom/svg-elliptical-arc.cpp b/src/2geom/svg-elliptical-arc.cpp index 877667b43..ae8a3192c 100644 --- a/src/2geom/svg-elliptical-arc.cpp +++ b/src/2geom/svg-elliptical-arc.cpp @@ -36,6 +36,7 @@ #include #include +#include #include <2geom/numeric/vector.h> #include <2geom/numeric/fitting-tool.h> @@ -46,929 +47,15 @@ namespace Geom { - -OptRect SVGEllipticalArc::boundsExact() const -{ - if (isDegenerate() && is_svg_compliant()) - return chord().boundsExact(); - - std::vector extremes(4); - double cosrot = std::cos(rotation_angle()); - double sinrot = std::sin(rotation_angle()); - extremes[0] = std::atan2( -ray(Y) * sinrot, ray(X) * cosrot ); - extremes[1] = extremes[0] + M_PI; - if ( extremes[0] < 0 ) extremes[0] += 2*M_PI; - extremes[2] = std::atan2( ray(Y) * cosrot, ray(X) * sinrot ); - extremes[3] = extremes[2] + M_PI; - if ( extremes[2] < 0 ) extremes[2] += 2*M_PI; - - - std::vectorarc_extremes(4); - arc_extremes[0] = initialPoint()[X]; - arc_extremes[1] = finalPoint()[X]; - if ( arc_extremes[0] < arc_extremes[1] ) - std::swap(arc_extremes[0], arc_extremes[1]); - arc_extremes[2] = initialPoint()[Y]; - arc_extremes[3] = finalPoint()[Y]; - if ( arc_extremes[2] < arc_extremes[3] ) - std::swap(arc_extremes[2], arc_extremes[3]); - - - if ( start_angle() < end_angle() ) - { - if ( sweep_flag() ) - { - for ( unsigned int i = 0; i < extremes.size(); ++i ) - { - if ( start_angle() < extremes[i] && extremes[i] < end_angle() ) - { - arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1]; - } - } - } - else - { - for ( unsigned int i = 0; i < extremes.size(); ++i ) - { - if ( start_angle() > extremes[i] || extremes[i] > end_angle() ) - { - arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1]; - } - } - } - } - else - { - if ( sweep_flag() ) - { - for ( unsigned int i = 0; i < extremes.size(); ++i ) - { - if ( start_angle() < extremes[i] || extremes[i] < end_angle() ) - { - arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1]; - } - } - } - else - { - for ( unsigned int i = 0; i < extremes.size(); ++i ) - { - if ( start_angle() > extremes[i] && extremes[i] > end_angle() ) - { - arc_extremes[i] = pointAtAngle(extremes[i])[i >> 1]; - } - } - } - } - - return Rect( Point(arc_extremes[1], arc_extremes[3]) , - Point(arc_extremes[0], arc_extremes[2]) ); -} - - -double SVGEllipticalArc::valueAtAngle(Coord t, Dim2 d) const -{ - double sin_rot_angle = std::sin(rotation_angle()); - double cos_rot_angle = std::cos(rotation_angle()); - if ( d == X ) - { - return ray(X) * cos_rot_angle * std::cos(t) - - ray(Y) * sin_rot_angle * std::sin(t) - + center(X); - } - else if ( d == Y ) - { - return ray(X) * sin_rot_angle * std::cos(t) - + ray(Y) * cos_rot_angle * std::sin(t) - + center(Y); - } - THROW_RANGEERROR("dimension parameter out of range"); -} - - -std::vector -SVGEllipticalArc::roots(double v, Dim2 d) const -{ - if ( d > Y ) - { - THROW_RANGEERROR("dimention out of range"); - } - - std::vector sol; - - if (isDegenerate() && is_svg_compliant()) - { - return chord().roots(v, d); - } - else - { - if ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) - { - if ( center(d) == v ) - sol.push_back(0); - return sol; - } - - const char* msg[2][2] = - { - { "d == X; ray(X) == 0; " - "s = (v - center(X)) / ( -ray(Y) * std::sin(rotation_angle()) ); " - "s should be contained in [-1,1]", - "d == X; ray(Y) == 0; " - "s = (v - center(X)) / ( ray(X) * std::cos(rotation_angle()) ); " - "s should be contained in [-1,1]" - }, - { "d == Y; ray(X) == 0; " - "s = (v - center(X)) / ( ray(Y) * std::cos(rotation_angle()) ); " - "s should be contained in [-1,1]", - "d == Y; ray(Y) == 0; " - "s = (v - center(X)) / ( ray(X) * std::sin(rotation_angle()) ); " - "s should be contained in [-1,1]" - }, - }; - - for ( unsigned int dim = 0; dim < 2; ++dim ) - { - if ( are_near(ray(dim), 0) ) - { - if ( initialPoint()[d] == v && finalPoint()[d] == v ) - { - THROW_INFINITESOLUTIONS(0); - } - if ( (initialPoint()[d] < finalPoint()[d]) - && (initialPoint()[d] > v || finalPoint()[d] < v) ) - { - return sol; - } - if ( (initialPoint()[d] > finalPoint()[d]) - && (finalPoint()[d] > v || initialPoint()[d] < v) ) - { - return sol; - } - double ray_prj; - switch(d) - { - case X: - switch(dim) - { - case X: ray_prj = -ray(Y) * std::sin(rotation_angle()); - break; - case Y: ray_prj = ray(X) * std::cos(rotation_angle()); - break; - } - break; - case Y: - switch(dim) - { - case X: ray_prj = ray(Y) * std::cos(rotation_angle()); - break; - case Y: ray_prj = ray(X) * std::sin(rotation_angle()); - break; - } - break; - } - - double s = (v - center(d)) / ray_prj; - if ( s < -1 || s > 1 ) - { - THROW_LOGICALERROR(msg[d][dim]); - } - switch(dim) - { - case X: - s = std::asin(s); // return a value in [-PI/2,PI/2] - if ( logical_xor( sweep_flag(), are_near(start_angle(), M_PI/2) ) ) - { - if ( s < 0 ) s += 2*M_PI; - } - else - { - s = M_PI - s; - if (!(s < 2*M_PI) ) s -= 2*M_PI; - } - break; - case Y: - s = std::acos(s); // return a value in [0,PI] - if ( logical_xor( sweep_flag(), are_near(start_angle(), 0) ) ) - { - s = 2*M_PI - s; - if ( !(s < 2*M_PI) ) s -= 2*M_PI; - } - break; - } - - //std::cerr << "s = " << rad_to_deg(s); - s = map_to_01(s); - //std::cerr << " -> t: " << s << std::endl; - if ( !(s < 0 || s > 1) ) - sol.push_back(s); - return sol; - } - } - - } - - double rotx, roty; - switch(d) - { - case X: - rotx = std::cos(rotation_angle()); - roty = -std::sin(rotation_angle()); - break; - case Y: - rotx = std::sin(rotation_angle()); - roty = std::cos(rotation_angle()); - break; - } - double rxrotx = ray(X) * rotx; - double c_v = center(d) - v; - - double a = -rxrotx + c_v; - double b = ray(Y) * roty; - double c = rxrotx + c_v; - //std::cerr << "a = " << a << std::endl; - //std::cerr << "b = " << b << std::endl; - //std::cerr << "c = " << c << std::endl; - - if ( are_near(a,0) ) - { - sol.push_back(M_PI); - if ( !are_near(b,0) ) - { - double s = 2 * std::atan(-c/(2*b)); - if ( s < 0 ) s += 2*M_PI; - sol.push_back(s); - } - } - else - { - double delta = b * b - a * c; - //std::cerr << "delta = " << delta << std::endl; - if ( are_near(delta, 0) ) - { - double s = 2 * std::atan(-b/a); - if ( s < 0 ) s += 2*M_PI; - sol.push_back(s); - } - else if ( delta > 0 ) - { - double sq = std::sqrt(delta); - double s = 2 * std::atan( (-b - sq) / a ); - if ( s < 0 ) s += 2*M_PI; - sol.push_back(s); - s = 2 * std::atan( (-b + sq) / a ); - if ( s < 0 ) s += 2*M_PI; - sol.push_back(s); - } - } - - std::vector arc_sol; - for (unsigned int i = 0; i < sol.size(); ++i ) - { - //std::cerr << "s = " << rad_to_deg(sol[i]); - sol[i] = map_to_01(sol[i]); - //std::cerr << " -> t: " << sol[i] << std::endl; - if ( !(sol[i] < 0 || sol[i] > 1) ) - arc_sol.push_back(sol[i]); - } - return arc_sol; -} - - -// D(E(t,C),t) = E(t+PI/2,O), where C is the ellipse center -// the derivative doesn't rotate the ellipse but there is a translation -// of the parameter t by an angle of PI/2 so the ellipse points are shifted -// of such an angle in the cw direction -Curve* SVGEllipticalArc::derivative() const -{ - if (isDegenerate() && is_svg_compliant()) - return chord().derivative(); - - SVGEllipticalArc* result = new SVGEllipticalArc(*this); - result->m_center[X] = result->m_center[Y] = 0; - result->m_start_angle += M_PI/2; - if( !( result->m_start_angle < 2*M_PI ) ) - { - result->m_start_angle -= 2*M_PI; - } - result->m_end_angle += M_PI/2; - if( !( result->m_end_angle < 2*M_PI ) ) - { - result->m_end_angle -= 2*M_PI; - } - result->m_initial_point = result->pointAtAngle( result->start_angle() ); - result->m_final_point = result->pointAtAngle( result->end_angle() ); - return result; -} - - -std::vector -SVGEllipticalArc::pointAndDerivatives(Coord t, unsigned int n) const -{ - if (isDegenerate() && is_svg_compliant()) - return chord().pointAndDerivatives(t, n); - - unsigned int nn = n+1; // nn represents the size of the result vector. - std::vector result; - result.reserve(nn); - double angle = map_unit_interval_on_circular_arc(t, start_angle(), - end_angle(), sweep_flag()); - SVGEllipticalArc ea(*this); - ea.m_center = Point(0,0); - unsigned int m = std::min(nn, 4u); - for ( unsigned int i = 0; i < m; ++i ) - { - result.push_back( ea.pointAtAngle(angle) ); - angle += M_PI/2; - if ( !(angle < 2*M_PI) ) angle -= 2*M_PI; - } - m = nn / 4; - for ( unsigned int i = 1; i < m; ++i ) - { - for ( unsigned int j = 0; j < 4; ++j ) - result.push_back( result[j] ); - } - m = nn - 4 * m; - for ( unsigned int i = 0; i < m; ++i ) - { - result.push_back( result[i] ); - } - if ( !result.empty() ) // nn != 0 - result[0] = pointAtAngle(angle); - return result; -} - -bool SVGEllipticalArc::containsAngle(Coord angle) const -{ - if ( sweep_flag() ) - if ( start_angle() < end_angle() ) - return ( !( angle < start_angle() || angle > end_angle() ) ); - else - return ( !( angle < start_angle() && angle > end_angle() ) ); - else - if ( start_angle() > end_angle() ) - return ( !( angle > start_angle() || angle < end_angle() ) ); - else - return ( !( angle > start_angle() && angle < end_angle() ) ); -} - -Curve* SVGEllipticalArc::portion(double f, double t) const -{ - // fix input arguments - if (f < 0) f = 0; - if (f > 1) f = 1; - if (t < 0) t = 0; - if (t > 1) t = 1; - - if ( are_near(f, t) ) - { - SVGEllipticalArc* arc = new SVGEllipticalArc(); - arc->m_center = arc->m_initial_point = arc->m_final_point = pointAt(f); - arc->m_start_angle = arc->m_end_angle = m_start_angle; - arc->m_rot_angle = m_rot_angle; - arc->m_sweep = m_sweep; - arc->m_large_arc = m_large_arc; - } - - SVGEllipticalArc* arc = new SVGEllipticalArc( *this ); - arc->m_initial_point = pointAt(f); - arc->m_final_point = pointAt(t); - double sa = sweep_flag() ? sweep_angle() : -sweep_angle(); - arc->m_start_angle = m_start_angle + sa * f; - if ( !(arc->m_start_angle < 2*M_PI) ) - arc->m_start_angle -= 2*M_PI; - if ( arc->m_start_angle < 0 ) - arc->m_start_angle += 2*M_PI; - arc->m_end_angle = m_start_angle + sa * t; - if ( !(arc->m_end_angle < 2*M_PI) ) - arc->m_end_angle -= 2*M_PI; - if ( arc->m_end_angle < 0 ) - arc->m_end_angle += 2*M_PI; - if ( f > t ) arc->m_sweep = !sweep_flag(); - if ( large_arc_flag() && (arc->sweep_angle() < M_PI) ) - arc->m_large_arc = false; - return arc; -} - - -std::vector SVGEllipticalArc:: -allNearestPoints( Point const& p, double from, double to ) const -{ - std::vector result; - if (isDegenerate() && is_svg_compliant()) - { - result.push_back( chord().nearestPoint(p, from, to) ); - return result; - } - - if ( from > to ) std::swap(from, to); - if ( from < 0 || to > 1 ) - { - THROW_RANGEERROR("[from,to] interval out of range"); - } - - if ( ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) || are_near(from, to) ) - { - result.push_back(from); - return result; - } - else if ( are_near(ray(X), 0) || are_near(ray(Y), 0) ) - { - LineSegment seg(pointAt(from), pointAt(to)); - Point np = seg.pointAt( seg.nearestPoint(p) ); - if ( are_near(ray(Y), 0) ) - { - if ( are_near(rotation_angle(), M_PI/2) - || are_near(rotation_angle(), 3*M_PI/2) ) - { - result = roots(np[Y], Y); - } - else - { - result = roots(np[X], X); - } - } - else - { - if ( are_near(rotation_angle(), M_PI/2) - || are_near(rotation_angle(), 3*M_PI/2) ) - { - result = roots(np[X], X); - } - else - { - result = roots(np[Y], Y); - } - } - return result; - } - else if ( are_near(ray(X), ray(Y)) ) - { - Point r = p - center(); - if ( are_near(r, Point(0,0)) ) - { - THROW_INFINITESOLUTIONS(0); - } - // TODO: implement case r != 0 -// Point np = ray(X) * unit_vector(r); -// std::vector solX = roots(np[X],X); -// std::vector solY = roots(np[Y],Y); -// double t; -// if ( are_near(solX[0], solY[0]) || are_near(solX[0], solY[1])) -// { -// t = solX[0]; -// } -// else -// { -// t = solX[1]; -// } -// if ( !(t < from || t > to) ) -// { -// result.push_back(t); -// } -// else -// { -// -// } - } - - // solve the equation == 0 - // that provides min and max distance points - // on the ellipse E wrt the point p - // after the substitutions: - // cos(t) = (1 - s^2) / (1 + s^2) - // sin(t) = 2t / (1 + s^2) - // where s = tan(t/2) - // we get a 4th degree equation in s - /* - * ry s^4 ((-cy + py) Cos[Phi] + (cx - px) Sin[Phi]) + - * ry ((cy - py) Cos[Phi] + (-cx + px) Sin[Phi]) + - * 2 s^3 (rx^2 - ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi]) + - * 2 s (-rx^2 + ry^2 + (-cx + px) rx Cos[Phi] + (-cy + py) rx Sin[Phi]) - */ - - Point p_c = p - center(); - double rx2_ry2 = (ray(X) - ray(Y)) * (ray(X) + ray(Y)); - double cosrot = std::cos( rotation_angle() ); - double sinrot = std::sin( rotation_angle() ); - double expr1 = ray(X) * (p_c[X] * cosrot + p_c[Y] * sinrot); - Poly coeff; - coeff.resize(5); - coeff[4] = ray(Y) * ( p_c[Y] * cosrot - p_c[X] * sinrot ); - coeff[3] = 2 * ( rx2_ry2 + expr1 ); - coeff[2] = 0; - coeff[1] = 2 * ( -rx2_ry2 + expr1 ); - coeff[0] = -coeff[4]; - -// for ( unsigned int i = 0; i < 5; ++i ) -// std::cerr << "c[" << i << "] = " << coeff[i] << std::endl; - - std::vector real_sol; - // gsl_poly_complex_solve raises an error - // if the leading coefficient is zero - if ( are_near(coeff[4], 0) ) - { - real_sol.push_back(0); - if ( !are_near(coeff[3], 0) ) - { - double sq = -coeff[1] / coeff[3]; - if ( sq > 0 ) - { - double s = std::sqrt(sq); - real_sol.push_back(s); - real_sol.push_back(-s); - } - } - } - else - { - real_sol = solve_reals(coeff); - } - - for ( unsigned int i = 0; i < real_sol.size(); ++i ) - { - real_sol[i] = 2 * std::atan(real_sol[i]); - if ( real_sol[i] < 0 ) real_sol[i] += 2*M_PI; - } - // when s -> Infinity then -> 0 iff coeff[4] == 0 - // so we add M_PI to the solutions being lim arctan(s) = PI when s->Infinity - if ( (real_sol.size() % 2) != 0 ) - { - real_sol.push_back(M_PI); - } - - double mindistsq1 = std::numeric_limits::max(); - double mindistsq2 = std::numeric_limits::max(); - double dsq; - unsigned int mi1, mi2; - for ( unsigned int i = 0; i < real_sol.size(); ++i ) - { - dsq = distanceSq(p, pointAtAngle(real_sol[i])); - if ( mindistsq1 > dsq ) - { - mindistsq2 = mindistsq1; - mi2 = mi1; - mindistsq1 = dsq; - mi1 = i; - } - else if ( mindistsq2 > dsq ) - { - mindistsq2 = dsq; - mi2 = i; - } - } - - double t = map_to_01( real_sol[mi1] ); - if ( !(t < from || t > to) ) - { - result.push_back(t); - } - - bool second_sol = false; - t = map_to_01( real_sol[mi2] ); - if ( real_sol.size() == 4 && !(t < from || t > to) ) - { - if ( result.empty() || are_near(mindistsq1, mindistsq2) ) - { - result.push_back(t); - second_sol = true; - } - } - - // we need to test extreme points too - double dsq1 = distanceSq(p, pointAt(from)); - double dsq2 = distanceSq(p, pointAt(to)); - if ( second_sol ) - { - if ( mindistsq2 > dsq1 ) - { - result.clear(); - result.push_back(from); - mindistsq2 = dsq1; - } - else if ( are_near(mindistsq2, dsq) ) - { - result.push_back(from); - } - if ( mindistsq2 > dsq2 ) - { - result.clear(); - result.push_back(to); - } - else if ( are_near(mindistsq2, dsq2) ) - { - result.push_back(to); - } - - } - else - { - if ( result.empty() ) - { - if ( are_near(dsq1, dsq2) ) - { - result.push_back(from); - result.push_back(to); - } - else if ( dsq2 > dsq1 ) - { - result.push_back(from); - } - else - { - result.push_back(to); - } - } - } - - return result; -} - - -/* - * NOTE: this implementation follows Standard SVG 1.1 implementation guidelines - * for elliptical arc curves. See Appendix F.6. - */ -void SVGEllipticalArc::calculate_center_and_extreme_angles() -{ - Point d = initialPoint() - finalPoint(); - - if (is_svg_compliant()) - { - if ( initialPoint() == finalPoint() ) - { - m_rx = m_ry = m_rot_angle = m_start_angle = m_end_angle = 0; - m_center = initialPoint(); - m_large_arc = m_sweep = false; - return; - } - - m_rx = std::fabs(m_rx); - m_ry = std::fabs(m_ry); - - if ( are_near(ray(X), 0) || are_near(ray(Y), 0) ) - { - m_rx = L2(d) / 2; - m_ry = 0; - m_rot_angle = std::atan2(d[Y], d[X]); - if (m_rot_angle < 0) m_rot_angle += 2*M_PI; - m_start_angle = 0; - m_end_angle = M_PI; - m_center = middle_point(initialPoint(), finalPoint()); - m_large_arc = false; - m_sweep = false; - return; - } - } - else - { - if ( are_near(initialPoint(), finalPoint()) ) - { - if ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) - { - m_start_angle = m_end_angle = 0; - m_center = initialPoint(); - return; - } - else - { - THROW_RANGEERROR("initial and final point are the same"); - } - } - if ( are_near(ray(X), 0) && are_near(ray(Y), 0) ) - { // but initialPoint != finalPoint - THROW_RANGEERROR( - "there is no ellipse that satisfies the given constraints: " - "ray(X) == 0 && ray(Y) == 0 but initialPoint != finalPoint" - ); - } - if ( are_near(ray(Y), 0) ) - { - Point v = initialPoint() - finalPoint(); - if ( are_near(L2sq(v), 4*ray(X)*ray(X)) ) - { - double angle = std::atan2(v[Y], v[X]); - if (angle < 0) angle += 2*M_PI; - if ( are_near( angle, rotation_angle() ) ) - { - m_start_angle = 0; - m_end_angle = M_PI; - m_center = v/2 + finalPoint(); - return; - } - angle -= M_PI; - if ( angle < 0 ) angle += 2*M_PI; - if ( are_near( angle, rotation_angle() ) ) - { - m_start_angle = M_PI; - m_end_angle = 0; - m_center = v/2 + finalPoint(); - return; - } - THROW_RANGEERROR( - "there is no ellipse that satisfies the given constraints: " - "ray(Y) == 0 " - "and slope(initialPoint - finalPoint) != rotation_angle " - "and != rotation_angle + PI" - ); - } - if ( L2sq(v) > 4*ray(X)*ray(X) ) - { - THROW_RANGEERROR( - "there is no ellipse that satisfies the given constraints: " - "ray(Y) == 0 and distance(initialPoint, finalPoint) > 2*ray(X)" - ); - } - else - { - THROW_RANGEERROR( - "there is infinite ellipses that satisfy the given constraints: " - "ray(Y) == 0 and distance(initialPoint, finalPoint) < 2*ray(X)" - ); - } - - } - - if ( are_near(ray(X), 0) ) - { - Point v = initialPoint() - finalPoint(); - if ( are_near(L2sq(v), 4*ray(Y)*ray(Y)) ) - { - double angle = std::atan2(v[Y], v[X]); - if (angle < 0) angle += 2*M_PI; - double rot_angle = rotation_angle() + M_PI/2; - if ( !(rot_angle < 2*M_PI) ) rot_angle -= 2*M_PI; - if ( are_near( angle, rot_angle ) ) - { - m_start_angle = M_PI/2; - m_end_angle = 3*M_PI/2; - m_center = v/2 + finalPoint(); - return; - } - angle -= M_PI; - if ( angle < 0 ) angle += 2*M_PI; - if ( are_near( angle, rot_angle ) ) - { - m_start_angle = 3*M_PI/2; - m_end_angle = M_PI/2; - m_center = v/2 + finalPoint(); - return; - } - THROW_RANGEERROR( - "there is no ellipse that satisfies the given constraints: " - "ray(X) == 0 " - "and slope(initialPoint - finalPoint) != rotation_angle + PI/2 " - "and != rotation_angle + (3/2)*PI" - ); - } - if ( L2sq(v) > 4*ray(Y)*ray(Y) ) - { - THROW_RANGEERROR( - "there is no ellipse that satisfies the given constraints: " - "ray(X) == 0 and distance(initialPoint, finalPoint) > 2*ray(Y)" - ); - } - else - { - THROW_RANGEERROR( - "there is infinite ellipses that satisfy the given constraints: " - "ray(X) == 0 and distance(initialPoint, finalPoint) < 2*ray(Y)" - ); - } - - } - - } - - double sin_rot_angle = std::sin(rotation_angle()); - double cos_rot_angle = std::cos(rotation_angle()); - - - Matrix m( cos_rot_angle, -sin_rot_angle, - sin_rot_angle, cos_rot_angle, - 0, 0 ); - - Point p = (d / 2) * m; - double rx2 = m_rx * m_rx; - double ry2 = m_ry * m_ry; - double rxpy = m_rx * p[Y]; - double rypx = m_ry * p[X]; - double rx2py2 = rxpy * rxpy; - double ry2px2 = rypx * rypx; - double num = rx2 * ry2; - double den = rx2py2 + ry2px2; - assert(den != 0); - double rad = num / den; - Point c(0,0); - if (rad > 1) - { - rad -= 1; - rad = std::sqrt(rad); - - if (m_large_arc == m_sweep) rad = -rad; - c = rad * Point(rxpy / m_ry, -rypx / m_rx); - - m[1] = -m[1]; - m[2] = -m[2]; - - m_center = c * m + middle_point(initialPoint(), finalPoint()); - } - else if (rad == 1 || is_svg_compliant()) - { - double lamda = std::sqrt(1 / rad); - m_rx *= lamda; - m_ry *= lamda; - m_center = middle_point(initialPoint(), finalPoint()); - } - else - { - THROW_RANGEERROR( - "there is no ellipse that satisfies the given constraints" - ); - } - - Point sp((p[X] - c[X]) / m_rx, (p[Y] - c[Y]) / m_ry); - Point ep((-p[X] - c[X]) / m_rx, (-p[Y] - c[Y]) / m_ry); - Point v(1, 0); - m_start_angle = angle_between(v, sp); - double sweep_angle = angle_between(sp, ep); - if (!m_sweep && sweep_angle > 0) sweep_angle -= 2*M_PI; - if (m_sweep && sweep_angle < 0) sweep_angle += 2*M_PI; - - if (m_start_angle < 0) m_start_angle += 2*M_PI; - m_end_angle = m_start_angle + sweep_angle; - if (m_end_angle < 0) m_end_angle += 2*M_PI; - if (m_end_angle >= 2*M_PI) m_end_angle -= 2*M_PI; -} - - -D2 SVGEllipticalArc::toSBasis() const -{ - - if (isDegenerate() && is_svg_compliant()) - return chord().toSBasis(); - - D2 arc; - // the interval of parametrization has to be [0,1] - Coord et = start_angle() + ( sweep_flag() ? sweep_angle() : -sweep_angle() ); - Linear param(start_angle(), et); - Coord cos_rot_angle = std::cos(rotation_angle()); - Coord sin_rot_angle = std::sin(rotation_angle()); - // order = 4 seems to be enough to get a perfect looking elliptical arc - SBasis arc_x = ray(X) * cos(param,4); - SBasis arc_y = ray(Y) * sin(param,4); - arc[0] = arc_x * cos_rot_angle - arc_y * sin_rot_angle + Linear(center(X),center(X)); - arc[1] = arc_x * sin_rot_angle + arc_y * cos_rot_angle + Linear(center(Y),center(Y)); - - // ensure that endpoints remain exact - for ( int d = 0 ; d < 2 ; d++ ) { - arc[d][0][0] = initialPoint()[d]; - arc[d][0][1] = finalPoint()[d]; - } - - return arc; -} - - -Curve* SVGEllipticalArc::transformed(Matrix const& m) const -{ - Ellipse e(center(X), center(Y), ray(X), ray(Y), rotation_angle()); - Ellipse et = e.transformed(m); - Point inner_point = pointAt(0.5); - SVGEllipticalArc ea = et.arc( initialPoint() * m, - inner_point * m, - finalPoint() * m, - is_svg_compliant() ); - return ea.duplicate(); -} - -/* - * helper routine to convert the parameter t value - * btw [0,1] and [0,2PI] domain and back +/** + * @class SVGEllipticalArc + * @brief SVG 1.1-compliant elliptical arc. + * + * This class is almost identical to the normal elliptical arc, but it differs slightly + * in the handling of degenerate arcs to be compliant with SVG 1.1 implementation guidelines. * + * @ingroup Curves */ -Coord SVGEllipticalArc::map_to_02PI(Coord t) const -{ - Coord angle = start_angle(); - if ( sweep_flag() ) - { - angle += sweep_angle() * t; - } - else - { - angle -= sweep_angle() * t; - } - angle = std::fmod(angle, 2*M_PI); - if ( angle < 0 ) angle += 2*M_PI; - return angle; -} - -Coord SVGEllipticalArc::map_to_01(Coord angle) const -{ - return map_circular_arc_on_unit_interval(angle, start_angle(), - end_angle(), sweep_flag()); -} - namespace detail { @@ -1015,7 +102,7 @@ struct ellipse_equation } make_elliptical_arc:: -make_elliptical_arc( SVGEllipticalArc& _ea, +make_elliptical_arc( EllipticalArc& _ea, curve_type const& _curve, unsigned int _total_samples, double _tolerance ) @@ -1133,13 +220,16 @@ bool make_elliptical_arc::make_elliptiarc() if (svg_compliant_flag()) { - ea = e.arc(initial_point, inner_point, final_point); + std::auto_ptr arc( e.arc(initial_point, inner_point, final_point, true) ); + ea = *arc; } else { try { - ea = e.arc(initial_point, inner_point, final_point, false); + std::auto_ptr eap( + e.arc(initial_point, inner_point, final_point, false) ); + ea = *eap; } catch(RangeError exc) { diff --git a/src/2geom/svg-elliptical-arc.h b/src/2geom/svg-elliptical-arc.h index 34c51508b..79497cdb3 100644 --- a/src/2geom/svg-elliptical-arc.h +++ b/src/2geom/svg-elliptical-arc.h @@ -1,12 +1,14 @@ /** * \file - * \brief Elliptical Arc - implementation of the SVGEllipticalArc path element + * \brief SVG 1.1-compliant elliptical arc curve * + *//* * Authors: - * MenTaLguY - * Marco Cecchetti - * - * Copyright 2007-2008 authors + * MenTaLguY + * Marco Cecchetti + * Krzysztof Kosiński + * + * 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 @@ -36,339 +38,95 @@ #ifndef _2GEOM_SVG_ELLIPTICAL_ARC_H_ #define _2GEOM_SVG_ELLIPTICAL_ARC_H_ - #include <2geom/curve.h> #include <2geom/angle.h> #include <2geom/utils.h> #include <2geom/bezier-curve.h> +#include <2geom/elliptical-arc.h> #include <2geom/sbasis-curve.h> // for non-native methods #include <2geom/numeric/vector.h> #include <2geom/numeric/fitting-tool.h> #include <2geom/numeric/fitting-model.h> - - #include - - namespace Geom { -class SVGEllipticalArc : public Curve -{ - public: - SVGEllipticalArc(bool _svg_compliant = true) - : m_initial_point(Point(0,0)), m_final_point(Point(0,0)), - m_rx(0), m_ry(0), m_rot_angle(0), - m_large_arc(true), m_sweep(true), - m_svg_compliant(_svg_compliant), - m_start_angle(0), m_end_angle(0), - m_center(Point(0,0)) - { - } - - /** - * \brief constructor - * - * \param _initial_point: initial arc end point; - * \param _rx: ellipse x-axis ray length - * \param _ry: ellipse y-axis ray length - * \param _rot_angle: ellipse x-axis rotation angle in radians; - * \param _large_arc: if true the largest arc is chosen, - * if false the smallest arc is chosen; - * \param _sweep : if true the clockwise arc is chosen, - * if false the counter-clockwise arc is chosen; - * \param _final_point: final arc end point; - * \param _svg_compliant: if true the class behaviour follows the Standard - * SVG 1.1 implementation guidelines (see Appendix F.6) - * if false the class behavoiur is more strict - * on input parameter - * - * in case the initial and the final arc end-points overlaps - * a degenerate arc of zero length is generated - * - */ - SVGEllipticalArc( Point _initial_point, double _rx, double _ry, - double _rot_angle, bool _large_arc, bool _sweep, - Point _final_point, - bool _svg_compliant = true +class SVGEllipticalArc : public EllipticalArc { +public: + SVGEllipticalArc() + : EllipticalArc() + {} + SVGEllipticalArc( Point ip, double rx, double ry, + double rot_angle, bool large_arc, bool sweep, + Point fp ) - : m_initial_point(_initial_point), m_final_point(_final_point), - m_rx(_rx), m_ry(_ry), m_rot_angle(_rot_angle), - m_large_arc(_large_arc), m_sweep(_sweep), - m_svg_compliant(_svg_compliant) + : EllipticalArc() { - calculate_center_and_extreme_angles(); + _initial_point = ip; + _final_point = fp; + _rays[X] = rx; _rays[Y] = ry; + _rot_angle = rot_angle; + _large_arc = large_arc; + _sweep = sweep; + _updateCenterAndAngles(true); } - void set( Point _initial_point, double _rx, double _ry, - double _rot_angle, bool _large_arc, bool _sweep, - Point _final_point - ) - { - m_initial_point = _initial_point; - m_final_point = _final_point; - m_rx = _rx; - m_ry = _ry; - m_rot_angle = _rot_angle; - m_large_arc = _large_arc; - m_sweep = _sweep; - calculate_center_and_extreme_angles(); - } - - Curve* duplicate() const - { +#ifndef DOXYGEN_SHOULD_SKIP_THIS + virtual Curve *duplicate() const { return new SVGEllipticalArc(*this); } - - double center(unsigned int i) const - { - return m_center[i]; + virtual Coord valueAt(Coord t, Dim2 d) const { + if (isDegenerate()) return chord().valueAt(t, d); + return EllipticalArc::valueAt(t, d); } - - Point center() const - { - return m_center; + virtual Point pointAt(Coord t) const { + if (isDegenerate()) return chord().pointAt(t); + return EllipticalArc::pointAt(t); } - - Point initialPoint() const - { - return m_initial_point; + virtual std::vector pointAndDerivatives(Coord t, unsigned int n) const { + if (isDegenerate()) return chord().pointAndDerivatives(t, n); + return EllipticalArc::pointAndDerivatives(t, n); } - - Point finalPoint() const - { - return m_final_point; + virtual Rect boundsExact() const { + if (isDegenerate()) return chord().boundsExact(); + return EllipticalArc::boundsExact(); } - - double start_angle() const - { - return m_start_angle; + virtual OptRect boundsLocal(OptInterval const &i, unsigned int deg) const { + if (isDegenerate()) return chord().boundsLocal(i, deg); + return EllipticalArc::boundsLocal(i, deg); } - double end_angle() const - { - return m_end_angle; + virtual Curve *derivative() const { + if (isDegenerate()) return chord().derivative(); + return EllipticalArc::derivative(); } - double ray(unsigned int i) const - { - return (i == 0) ? m_rx : m_ry; + virtual std::vector roots(Coord v, Dim2 d) const { + if (isDegenerate()) return chord().roots(v, d); + return EllipticalArc::roots(v, d); } - - bool large_arc_flag() const - { - return m_large_arc; - } - - bool sweep_flag() const - { - return m_sweep; - } - - double rotation_angle() const - { - return m_rot_angle; - } - - void setInitial( const Point _point) - { - m_initial_point = _point; - calculate_center_and_extreme_angles(); - } - - void setFinal( const Point _point) - { - m_final_point = _point; - calculate_center_and_extreme_angles(); - } - - void setExtremes( const Point& _initial_point, const Point& _final_point ) - { - m_initial_point = _initial_point; - m_final_point = _final_point; - calculate_center_and_extreme_angles(); - } - - bool isDegenerate() const - { - return ( are_near(ray(X), 0) || are_near(ray(Y), 0) ); - } - - bool is_svg_compliant() const - { - return m_svg_compliant; - } - - virtual OptRect boundsFast() const - { - return boundsExact(); - } - - virtual OptRect boundsExact() const; - - // TODO: native implementation of the following methods - virtual OptRect boundsLocal(OptInterval i, unsigned int deg) const - { - if (isDegenerate() && is_svg_compliant()) - return chord().boundsLocal(i, deg); - else - return SBasisCurve(toSBasis()).boundsLocal(i, deg); - } - - std::vector roots(double v, Dim2 d) const; - - /* - * find all the points on the curve portion between "from" and "to" - * at the same smallest distance from the point "p" the points are returned - * as their parameter t value; - */ - std::vector - allNearestPoints( Point const& p, double from = 0, double to = 1 ) const; - - /* - * find a point on the curve portion between "from" and "to" - * at the same smallest distance from the point "p"; - * the point is returned as its parameter t value; - */ - double nearestPoint( Point const& p, double from = 0, double to = 1 ) const - { - if ( are_near(ray(X), ray(Y)) && are_near(center(), p) ) - { - return from; +#ifdef HAVE_GSL + virtual std::vector allNearestPoints( Point const& p, double from = 0, double to = 1 ) const { + if (isDegenerate()) { + std::vector result; + result.push_back(chord().nearestPoint(p, from, to)); + return result; } - return allNearestPoints(p, from, to).front(); - } - - // TODO: native implementation of the following methods - int winding(Point p) const - { - if (isDegenerate() && is_svg_compliant()) - return chord().winding(p); - else - return SBasisCurve(toSBasis()).winding(p); - } - - int degreesOfFreedom() const { return 5;} - - Curve *derivative() const; - - Curve *transformed(Matrix const &m) const; - - std::vector pointAndDerivatives(Coord t, unsigned int n) const; - - D2 toSBasis() const; - - /* - * return true if the angle argument (in radiants) is contained - * in the range [start_angle(), end_angle() ] - */ - bool containsAngle(Coord angle) const; - - /* - * return the value of the d-dimensional coordinate related to "t" - * here t belongs to the [0,2PI] domain - */ - double valueAtAngle(Coord t, Dim2 d) const; - - /* - * return the point related to the parameter value "t" - * here t belongs to the [0,2PI] domain - */ - Point pointAtAngle(Coord t) const - { - double sin_rot_angle = std::sin(rotation_angle()); - double cos_rot_angle = std::cos(rotation_angle()); - Matrix m( ray(X) * cos_rot_angle, ray(X) * sin_rot_angle, - -ray(Y) * sin_rot_angle, ray(Y) * cos_rot_angle, - center(X), center(Y) ); - Point p( std::cos(t), std::sin(t) ); - return p * m; - } - - /* - * return the value of the d-dimensional coordinate related to "t" - * here t belongs to the [0,1] domain - */ - double valueAt(Coord t, Dim2 d) const - { - if (isDegenerate() && is_svg_compliant()) - return chord().valueAt(t, d); - - Coord tt = map_to_02PI(t); - return valueAtAngle(tt, d); - } - - /* - * return the point related to the parameter value "t" - * here t belongs to the [0,1] domain - */ - Point pointAt(Coord t) const - { - if (isDegenerate() && is_svg_compliant()) - return chord().pointAt(t); - - Coord tt = map_to_02PI(t); - return pointAtAngle(tt); - } - - std::pair - subdivide(Coord t) const - { - SVGEllipticalArc* arc1 = static_cast(portion(0, t)); - SVGEllipticalArc* arc2 = static_cast(portion(t, 1)); - assert( arc1 != NULL && arc2 != NULL); - std::pair arc_pair(*arc1, *arc2); - delete arc1; - delete arc2; - return arc_pair; - } - - Curve* portion(double f, double t) const; - - // the arc is the same but traversed in the opposite direction - Curve* reverse() const - { - SVGEllipticalArc* rarc = new SVGEllipticalArc( *this ); - rarc->m_sweep = !m_sweep; - rarc->m_initial_point = m_final_point; - rarc->m_final_point = m_initial_point; - rarc->m_start_angle = m_end_angle; - rarc->m_end_angle = m_start_angle; - return rarc; - } - - - double sweep_angle() const - { - Coord d = end_angle() - start_angle(); - if ( !sweep_flag() ) d = -d; - if ( d < 0 ) - d += 2*M_PI; - return d; - } - - LineSegment chord() const - { - return LineSegment(initialPoint(), finalPoint()); - } - - private: - Coord map_to_02PI(Coord t) const; - Coord map_to_01(Coord angle) const; - void calculate_center_and_extreme_angles(); - - private: - Point m_initial_point, m_final_point; - double m_rx, m_ry, m_rot_angle; - bool m_large_arc, m_sweep; - bool m_svg_compliant; - double m_start_angle, m_end_angle; - Point m_center; - + return EllipticalArc::allNearestPoints(p, from, to); + } +#endif + virtual D2 toSBasis() const { + if (isDegenerate()) return chord().toSBasis(); + return EllipticalArc::toSBasis(); + } + virtual bool isSVGCompliant() const { return true; } + // TODO move SVG-specific behavior here. +//protected: + //virtual void _updateCenterAndAngles(); +#endif }; // end class SVGEllipticalArc - /* * useful for testing and debugging */ @@ -379,9 +137,9 @@ operator<< (std::basic_ostream & os, const SVGEllipticalArc & ea) { os << "{ cx: " << ea.center(X) << ", cy: " << ea.center(Y) << ", rx: " << ea.ray(X) << ", ry: " << ea.ray(Y) - << ", rot angle: " << decimal_round(rad_to_deg(ea.rotation_angle()),2) - << ", start angle: " << decimal_round(rad_to_deg(ea.start_angle()),2) - << ", end angle: " << decimal_round(rad_to_deg(ea.end_angle()),2) + << ", rot angle: " << decimal_round(rad_to_deg(ea.rotationAngle()),2) + << ", start angle: " << decimal_round(rad_to_deg(ea.initialAngle()),2) + << ", end angle: " << decimal_round(rad_to_deg(ea.finalAngle()),2) << " }"; return os; @@ -396,6 +154,7 @@ namespace detail struct ellipse_equation; } +// TODO this needs to be rewritten and moved to EllipticalArc header /* * make_elliptical_arc * @@ -428,7 +187,7 @@ class make_elliptical_arc * and the generated elliptical arc; the smaller it is the * the tolerance the higher it is the likelihood. */ - make_elliptical_arc( SVGEllipticalArc& _ea, + make_elliptical_arc( EllipticalArc& _ea, curve_type const& _curve, unsigned int _total_samples, double _tolerance ); @@ -486,7 +245,7 @@ class make_elliptical_arc } private: - SVGEllipticalArc& ea; // output elliptical arc + EllipticalArc& ea; // output elliptical arc const curve_type & curve; // input curve Piecewise > dcurve; // derivative of the input curve NL::LFMEllipse model; // model used for fitting diff --git a/src/2geom/svg-path-parser.cpp b/src/2geom/svg-path-parser.cpp index 804284077..4d35ccb35 100644 --- a/src/2geom/svg-path-parser.cpp +++ b/src/2geom/svg-path-parser.cpp @@ -1,3 +1,4 @@ +#line 1 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" /** * \file * \brief parse SVG path specifications @@ -139,7 +140,7 @@ private: }; -#line 144 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.cpp" +#line 144 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.cpp" static const char _svg_path_actions[] = { 0, 1, 0, 1, 1, 1, 2, 1, 3, 1, 4, 1, 5, 1, 15, 1, @@ -1144,7 +1145,7 @@ static const int svg_path_first_final = 270; static const int svg_path_en_main = 1; -#line 144 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 144 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" void Parser::parse(char const *str) @@ -1157,12 +1158,12 @@ throw(SVGPathParseError) _reset(); -#line 1162 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.cpp" +#line 1162 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.cpp" { cs = svg_path_start; } -#line 1167 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.cpp" +#line 1167 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.cpp" { int _klen; unsigned int _trans; @@ -1235,13 +1236,13 @@ _match: switch ( *_acts++ ) { case 0: -#line 156 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 156 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { start = p; } break; case 1: -#line 160 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 160 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { char const *end=p; std::string buf(start, end); @@ -1250,55 +1251,55 @@ _match: } break; case 2: -#line 167 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 167 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { _push(1.0); } break; case 3: -#line 171 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 171 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { _push(0.0); } break; case 4: -#line 175 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 175 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { _absolute = true; } break; case 5: -#line 179 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 179 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { _absolute = false; } break; case 6: -#line 183 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 183 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { _moveTo(_pop_point()); } break; case 7: -#line 187 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 187 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { _lineTo(_pop_point()); } break; case 8: -#line 191 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 191 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { _hlineTo(Point(_pop_coord(X), _current[Y])); } break; case 9: -#line 195 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 195 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { _vlineTo(Point(_current[X], _pop_coord(Y))); } break; case 10: -#line 199 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 199 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { Point p = _pop_point(); Point c1 = _pop_point(); @@ -1307,7 +1308,7 @@ _match: } break; case 11: -#line 206 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 206 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { Point p = _pop_point(); Point c1 = _pop_point(); @@ -1315,7 +1316,7 @@ _match: } break; case 12: -#line 212 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 212 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { Point p = _pop_point(); Point c = _pop_point(); @@ -1323,14 +1324,14 @@ _match: } break; case 13: -#line 218 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 218 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { Point p = _pop_point(); _quadTo(_quad_tangent, p); } break; case 14: -#line 223 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 223 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { Point point = _pop_point(); bool sweep = _pop_flag(); @@ -1343,16 +1344,16 @@ _match: } break; case 15: -#line 234 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 234 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" { _closePath(); } break; case 16: -#line 370 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 370 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" {goto _out;} break; -#line 1357 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.cpp" +#line 1357 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.cpp" } } @@ -1363,7 +1364,7 @@ _again: goto _resume; _out: {} } -#line 380 "/home/njh/svn/lib2geom/src/2geom/svg-path-parser.rl" +#line 380 "/opt/shared/work/programming/eclipse/eclipse_3.4/lib2geom/src/2geom/svg-path-parser.rl" if ( cs < svg_path_first_final ) { diff --git a/src/2geom/svg-path.cpp b/src/2geom/svg-path.cpp index 3e4bf7bec..d459b3e1b 100644 --- a/src/2geom/svg-path.cpp +++ b/src/2geom/svg-path.cpp @@ -61,8 +61,8 @@ void output(QuadraticBezier const &curve, SVGPathSink &sink) { } void output(SVGEllipticalArc const &curve, SVGPathSink &sink) { - sink.arcTo( curve.ray(X), curve.ray(Y), curve.rotation_angle(), - curve.large_arc_flag(), curve.sweep_flag(), + sink.arcTo( curve.ray(X), curve.ray(Y), curve.rotationAngle(), + curve.largeArc(), curve.sweep(), curve.finalPoint() ); } diff --git a/src/2geom/sweep.h b/src/2geom/sweep.h index 299813244..1c73efee0 100644 --- a/src/2geom/sweep.h +++ b/src/2geom/sweep.h @@ -51,6 +51,9 @@ struct Event { if(x > other.x) return false; return closing < other.closing; } + bool operator==(Event const &other) const { + return other.x == x && other.ix == ix && other.closing == closing; + } }; std::vector > sweep_bounds(std::vector, Dim2 dim = X); diff --git a/src/2geom/transforms.cpp b/src/2geom/transforms.cpp index 8182ce16d..2658719c4 100644 --- a/src/2geom/transforms.cpp +++ b/src/2geom/transforms.cpp @@ -1,106 +1,143 @@ +/** + * @file + * @brief Affine transformation classes + *//* + * Authors: + * ? + * Krzysztof Kosiński + * + * Copyright ?-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 +#include <2geom/point.h> #include <2geom/transforms.h> namespace Geom { -Matrix operator*(Translate const &t, Scale const &s) { - Matrix ret(s); - ret[4] = t[X] * s[X]; - ret[5] = t[Y] * s[Y]; - return ret; +// Point transformation methods. +Point &Point::operator*=(Translate const &t) +{ + _pt[X] += t.vec[X]; + _pt[Y] += t.vec[Y]; + return *this; } - -Matrix operator*(Translate const &t, Rotate const &r) { - Matrix ret(r); - ret.setTranslation(t.vec * ret); - return ret; +Point &Point::operator*=(Scale const &s) +{ + _pt[X] *= s.vec[X]; + _pt[Y] *= s.vec[Y]; + return *this; } - -Matrix operator*(Scale const &s, Translate const &t) { - return Matrix(s[0], 0, - 0 , s[1], - t[0], t[1]); +Point &Point::operator*=(Rotate const &r) +{ + double x = _pt[X], y = _pt[Y]; + _pt[X] = x * r.vec[X] - y * r.vec[Y]; + _pt[Y] = y * r.vec[X] + x * r.vec[Y]; + return *this; } - -Matrix operator*(Scale const &s, Matrix const &m) { - Matrix ret(m); - ret[0] *= s[X]; - ret[1] *= s[X]; - ret[2] *= s[Y]; - ret[3] *= s[Y]; - return ret; +Point &Point::operator*=(HShear const &h) +{ + _pt[X] += h.f * _pt[X]; + return *this; } - -Matrix operator*(Matrix const &m, Translate const &t) { - Matrix ret(m); - ret[4] += t[X]; - ret[5] += t[Y]; - return ret; +Point &Point::operator*=(VShear const &v) +{ + _pt[Y] += v.f * _pt[Y]; + return *this; } -Matrix operator*(Matrix const &m, Scale const &s) { - Matrix ret(m); - ret[0] *= s[X]; ret[1] *= s[Y]; - ret[2] *= s[X]; ret[3] *= s[Y]; - ret[4] *= s[X]; ret[5] *= s[Y]; - return ret; -} +// Affine multiplication methods. -Matrix operator*(Matrix const &m, Rotate const &r) { - // TODO: we just convert the Rotate to a matrix and use the existing operator*(); is there a better way? - Matrix ret(m); - ret *= (Matrix) r; - return ret; +/** @brief Combine this transformation with a translation. */ +Affine &Affine::operator*=(Translate const &t) { + _c[4] += t[X]; + _c[5] += t[Y]; + return *this; } -Translate pow(Translate const &t, int n) { - return Translate(t[0]*n, t[1]*n); +/** @brief Combine this transformation with scaling. */ +Affine &Affine::operator*=(Scale const &s) { + _c[0] *= s[X]; _c[1] *= s[Y]; + _c[2] *= s[X]; _c[3] *= s[Y]; + _c[4] *= s[X]; _c[5] *= s[Y]; + return *this; } -Coord pow(Coord x, long n) // shamelessly lifted from WP -{ - Coord result = 1; - while ( n ) { - if ( n & 1 ) { - result = result * x; - n = n-1; - } - x = x*x; - n = n/2; - } - return result; +/** @brief Combine this transformation a rotation. */ +Affine &Affine::operator*=(Rotate const &r) { + // TODO: we just convert the Rotate to an Affine and use the existing operator*=() + // is there a better way? + *this *= (Affine) r; + return *this; } -Scale pow(Scale const &s, int n) { - return Scale(pow(s[0],n), pow(s[1],n)); +/** @brief Combine this transformation with horizontal shearing (skew). */ +Affine &Affine::operator*=(HShear const &h) { + _c[0] += h.f * _c[1]; + _c[2] += h.f * _c[3]; + _c[4] += h.f * _c[5]; + return *this; } -Rotate pow(Rotate x, long n) -{ - Rotate result(0,1); // identity - while ( n ) { - if ( n & 1 ) { - result = result * x; - n = n-1; - } - x = x*x; - n = n/2; - } - return result; +/** @brief Combine this transformation with vertical shearing (skew). */ +Affine &Affine::operator*=(VShear const &v) { + _c[1] += v.f * _c[0]; + _c[3] += v.f * _c[2]; + _c[5] += v.f * _c[4]; + return *this; } -Matrix pow(Matrix x, long n) +// this checks whether the requirements of TransformConcept are satisfied for all transforms. +// if you add a new transform type, include it here! +void check_transforms() { - Matrix result; - result.setIdentity(); - while ( n ) { - if ( n & 1 ) { - result = result * x; - n = n-1; - } - x = x*x; - n = n/2; - } - return result; +#ifdef BOOST_CONCEPT_ASSERT + BOOST_CONCEPT_ASSERT((TransformConcept)); + BOOST_CONCEPT_ASSERT((TransformConcept)); + BOOST_CONCEPT_ASSERT((TransformConcept)); + BOOST_CONCEPT_ASSERT((TransformConcept)); + BOOST_CONCEPT_ASSERT((TransformConcept)); + BOOST_CONCEPT_ASSERT((TransformConcept)); // Affine is also a transform +#endif + + // check inter-transform multiplication + Affine m; + Translate t(Translate::identity()); + Scale s(Scale::identity()); + Rotate r(Rotate::identity()); + HShear h(HShear::identity()); + VShear v(VShear::identity()); + + // notice that the first column is always the same and enumerates all transform types, + // while the second one changes to each transform type in turn. + m = t * t; m = t * s; m = t * r; m = t * h; m = t * v; + m = s * t; m = s * s; m = s * r; m = s * h; m = s * v; + m = r * t; m = r * s; m = r * r; m = r * h; m = r * v; + m = h * t; m = h * s; m = h * r; m = h * h; m = h * v; + m = v * t; m = v * s; m = v * r; m = v * h; m = v * v; } } diff --git a/src/2geom/transforms.h b/src/2geom/transforms.h index 1d8d87da3..b8db82f14 100644 --- a/src/2geom/transforms.h +++ b/src/2geom/transforms.h @@ -1,11 +1,12 @@ /** - * \file - * \brief Transforms should be applied left to right. scale * translate means: first scale, then translate. - * + * @file + * @brief Affine transformation classes + *//* * Authors: - * ? + * ? + * Krzysztof Kosiński * - * Copyright ?-? authors + * Copyright ?-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 @@ -29,132 +30,235 @@ * 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_TRANSFORMS_H #define SEEN_Geom_TRANSFORMS_H -#include <2geom/matrix.h> +#include <2geom/forward.h> +#include <2geom/affine.h> #include namespace Geom { +/** @brief Type requirements for transforms. + * @ingroup Concepts */ template struct TransformConcept { T t; - Matrix m; + Affine m; Point p; + bool bool_; void constraints() { m = t; //implicit conversion - t = t.inverse(); + m *= t; + m = m * t; + m = t * m; + p *= t; p = p * t; + p = t * p; + t *= t; t = t * t; + t = pow(t, 3); + p /= t; // multiplication by inverse + p = p / t; + bool_ = (t == t); + bool_ = (t != t); + t = T::identity(); + t = t.inverse(); } }; +/** @brief Base template for transforms. */ +template +class TransformOperations + : boost::equality_comparable< T + , boost::multipliable< T + > > +{ +public: + template + Affine operator*(T2 const &t) const { + Affine ret(*static_cast(this)); ret *= t; return ret; + } +}; -class Rotate; -class Translate { - private: - Translate(); +/** @brief Integer exponentiation for transforms. + * Negative exponents will yield the corresponding power of the inverse. This function + * can also be applied to matrices. + * @param t Affine or transform to exponantiate + * @param n Exponent + * @return \f$A^n\f$ if @a n is positive, \f$(A^{-1})^n\f$ if negative, identity if zero. + * @ingroup Transforms */ +template +T pow(T const &t, int n) { + if (n == 0) return T::identity(); + T result(T::identity()); + T x(n < 0 ? t.inverse() : t); + if (n < 0) n = -n; + while ( n ) { // binary exponentiation - fast + if ( n & 1 ) { result *= x; --n; } + x *= x; n /= 2; + } + return result; +} + +/** @brief Translation by a vector. + * @ingroup Transforms */ +class Translate + : public TransformOperations< Translate > +{ + Translate() : vec(0, 0) {} Point vec; - public: +public: + /** @brief Construct a translation from its vector. */ explicit Translate(Point const &p) : vec(p) {} - explicit Translate(Coord const x, Coord const y) : vec(x, y) {} - inline operator Matrix() const { return Matrix(1, 0, 0, 1, vec[X], vec[Y]); } + /** @brief Construct a translation from its coordinates. */ + explicit Translate(Coord x, Coord y) : vec(x, y) {} - inline Coord operator[](Dim2 const dim) const { return vec[dim]; } - inline Coord operator[](unsigned const dim) const { return vec[dim]; } - inline bool operator==(Translate const &o) const { return vec == o.vec; } - inline bool operator!=(Translate const &o) const { return vec != o.vec; } + operator Affine() const { Affine ret(1, 0, 0, 1, vec[X], vec[Y]); return ret; } + Coord operator[](Dim2 dim) const { return vec[dim]; } + Coord operator[](unsigned dim) const { return vec[dim]; } + Translate &operator*=(Translate const &o) { vec += o.vec; return *this; } + bool operator==(Translate const &o) const { return vec == o.vec; } - inline Translate inverse() const { return Translate(-vec); } + /** @brief Get the inverse translation. */ + Translate inverse() const { return Translate(-vec); } + /** @brief Get a translation that doesn't do anything. */ + static Translate identity() { Translate ret; return ret; } - friend Point operator*(Point const &v, Translate const &t); - inline Translate operator*(Translate const &b) const { return Translate(vec + b.vec); } - - friend Matrix operator*(Translate const &t, Rotate const &r); + friend class Point; }; -inline Point operator*(Point const &v, Translate const &t) { return v + t.vec; } - -class Scale { - private: +/** @brief Scaling from the origin. + * During scaling, the point (0,0) will not move. To obtain a scale with a different + * invariant point, combine with translation to the origin and back. + * @ingroup Transforms */ +class Scale + : public TransformOperations< Scale > +{ Point vec; - Scale(); - public: + Scale() : vec(1, 1) {} +public: explicit Scale(Point const &p) : vec(p) {} - Scale(Coord const x, Coord const y) : vec(x, y) {} - explicit Scale(Coord const s) : vec(s, s) {} - inline operator Matrix() const { return Matrix(vec[X], 0, 0, vec[Y], 0, 0); } + Scale(Coord x, Coord y) : vec(x, y) {} + explicit Scale(Coord s) : vec(s, s) {} + inline operator Affine() const { Affine ret(vec[X], 0, 0, vec[Y], 0, 0); return ret; } - inline Coord operator[](Dim2 const d) const { return vec[d]; } - inline Coord operator[](unsigned const d) const { return vec[d]; } + Coord operator[](Dim2 d) const { return vec[d]; } + Coord operator[](unsigned d) const { return vec[d]; } //TODO: should we keep these mutators? add them to the other transforms? - inline Coord &operator[](Dim2 const d) { return vec[d]; } - inline Coord &operator[](unsigned const d) { return vec[d]; } - inline bool operator==(Scale const &o) const { return vec == o.vec; } - inline bool operator!=(Scale const &o) const { return vec != o.vec; } + Coord &operator[](Dim2 d) { return vec[d]; } + Coord &operator[](unsigned d) { return vec[d]; } + Scale &operator*=(Scale const &b) { vec[X] *= b[X]; vec[Y] *= b[Y]; return *this; } + bool operator==(Scale const &o) const { return vec == o.vec; } + Scale inverse() const { return Scale(1./vec[0], 1./vec[1]); } + static Scale identity() { Scale ret; return ret; } - inline Scale inverse() const { return Scale(1./vec[0], 1./vec[1]); } - - friend Point operator*(Point const &v, Translate const &t); - inline Scale operator*(Scale const &b) const { return Scale(vec[X]*b[X], vec[Y]*b[Y]); } + friend class Point; }; -inline Point operator*(Point const &p, Scale const &s) { return Point(p[X] * s[X], p[Y] * s[Y]); } - -/** Notionally an Geom::Matrix corresponding to rotation about the origin. - Behaves like Geom::Matrix for multiplication. -**/ -class Rotate { - private: - Rotate() {} +/** @brief Rotation around the origin. + * Combine with translations to the origin and back to get a rotation around a different point. + * @ingroup Transforms */ +class Rotate + : public TransformOperations< Rotate > +{ + Rotate() : vec(1, 0) {} Point vec; - public: - explicit Rotate(Coord theta) : vec(std::cos(theta), std::sin(theta)) {} - Rotate(Point const &p) {Point v = p; v.normalize(); vec = v;} //TODO: UGLY! +public: + /** @brief Construct a rotation from its angle in radians. + * Positive arguments correspond to counter-clockwise rotations (if Y grows upwards). */ + explicit Rotate(Coord theta) : vec(Point::polar(theta)) {} + /** @brief Construct a rotation from its characteristic vector. */ + explicit Rotate(Point const &p) : vec(unit_vector(p)) {} + /** @brief Construct a rotation from the coordinates of its characteristic vector. */ explicit Rotate(Coord x, Coord y) { Rotate(Point(x, y)); } - inline operator Matrix() const { return Matrix(vec[X], vec[Y], -vec[Y], vec[X], 0, 0); } + operator Affine() const { Affine ret(vec[X], vec[Y], -vec[Y], vec[X], 0, 0); return ret; } - inline Point vector() const { return vec; } - inline Coord operator[](Dim2 const dim) const { return vec[dim]; } - inline Coord operator[](unsigned const dim) const { return vec[dim]; } - inline bool operator==(Rotate const &o) const { return vec == o.vec; } - inline bool operator!=(Rotate const &o) const { return vec != o.vec; } - - inline Rotate inverse() const { + /** @brief Get the characteristic vector of the rotation. + * @return A vector that would be obtained by applying this transform to the X versor. */ + Point vector() const { return vec; } + Coord operator[](Dim2 dim) const { return vec[dim]; } + Coord operator[](unsigned dim) const { return vec[dim]; } + Rotate &operator*=(Rotate const &o) { vec *= o; return *this; } + bool operator==(Rotate const &o) const { return vec == o.vec; } + Rotate inverse() const { Rotate r; r.vec = Point(vec[X], -vec[Y]); return r; } + /** @brief Get a 0-degree rotation. */ + static Rotate identity() { Rotate ret; return ret; } + /** @brief Construct a rotation from its angle in degrees. + * Positive arguments correspond to counter-clockwise rotations (if Y grows upwards). */ static Rotate from_degrees(Coord deg) { Coord rad = (deg / 180.0) * M_PI; return Rotate(rad); } - friend Point operator*(Point const &v, Rotate const &r); - inline Rotate operator*(Rotate const &b) const { return Rotate(vec * b); } + friend class Point; }; -inline Point operator*(Point const &v, Rotate const &r) { return v ^ r.vec; } +/** @brief Common base for shearing transforms. + * @ingroup Transforms */ +template +class ShearBase + : public TransformOperations< S > +{ +protected: + Coord f; + ShearBase(Coord _f) : f(_f) {} +public: + Coord factor() const { return f; } + void setFactor(Coord nf) { f = nf; } + S &operator*=(S const &s) { f += s.f; return *static_cast(this); } + bool operator==(S const &s) const { return f == s.f; } + S inverse() const { return S(-f); } + static S identity() { return S(0); } -Matrix operator*(Translate const &t, Scale const &s); -Matrix operator*(Translate const &t, Rotate const &r); + friend class Point; + friend class Affine; +}; -Matrix operator*(Scale const &s, Translate const &t); -Matrix operator*(Scale const &s, Matrix const &m); +/** @brief Horizontal shearing. + * Points on the X axis will not move. Combine with translations to get a shear + * with a different invariant line. + * @ingroup Transforms */ +class HShear + : public ShearBase +{ +public: + explicit HShear(Coord h) : ShearBase(h) {} + operator Affine() const { Affine ret(1, 0, f, 1, 0, 0); return ret; } +}; -Matrix operator*(Matrix const &m, Translate const &t); -Matrix operator*(Matrix const &m, Scale const &s); -Matrix operator*(Matrix const &m, Rotate const &r); -Matrix operator*(Matrix const &m1, Matrix const &m2); +/** @brief Vertical shearing. + * Points on the Y axis will not move. Combine with translations to get a shear + * with a different invariant line. + * @ingroup Transforms */ +class VShear + : public ShearBase +{ +public: + explicit VShear(Coord h) : ShearBase(h) {} + operator Affine() const { Affine ret(1, f, 0, 1, 0, 0); return ret; } +}; -Translate pow(Translate const &t, int n); -Scale pow(Scale const &t, int n); -Rotate pow(Rotate t, int n); -Matrix pow(Matrix t, int n); +/** @brief Specialization of exponentiation for Scale. + * @relates Scale */ +template<> +inline Scale pow(Scale const &s, int n) { + Scale ret(::pow(s[X], n), ::pow(s[Y], n)); + return ret; +} +/** @brief Specialization of exponentiation for Translate. + * @relates Translate */ +template<> +inline Translate pow(Translate const &t, int n) { + Translate ret(t[X] * n, t[Y] * n); + return ret; +} //TODO: matrix to trans/scale/rotate diff --git a/src/2geom/utils.h b/src/2geom/utils.h index dcadc8431..31468a204 100644 --- a/src/2geom/utils.h +++ b/src/2geom/utils.h @@ -33,7 +33,7 @@ * */ -#include +#include <2geom/math-utils.h> #include namespace Geom { @@ -41,45 +41,6 @@ namespace Geom { // proper logical xor inline bool logical_xor (bool a, bool b) { return (a || b) && !(a && b); } -/** Sign function - indicates the sign of a numeric type. -1 indicates negative, 1 indicates - * positive, and 0 indicates, well, 0. Mathsy people will know this is basically the derivative - * of abs, except for the fact that it is defined on 0. - */ -template inline int sgn(const T& x) {return (x < 0 ? -1 : (x > 0 ? 1 : 0) );} - -template inline T sqr(const T& x) {return x * x;} -template inline T cube(const T& x) {return x * x * x;} - -/** Between function - returns true if a number x is within a range. The values delimiting the - * range and the number must have the same type. - */ -template inline const T& between (const T& min, const T& max, const T& x) - { return min < x && max > x; } - -/** Returns x rounded to the nearest integer. It is unspecified what happens - * if x is half way between two integers: we may in future use rint/round - * on platforms that have them. - */ -inline double round(double const x) { return std::floor(x + .5); } - -/** Returns x rounded to the nearest \a places decimal places. - - Implemented in terms of round, i.e. we make no guarantees as to what happens if x is - half way between two rounded numbers. - - Note: places is the number of decimal places without using scientific (e) notation, not the - number of significant figures. This function may not be suitable for values of x whose - magnitude is so far from 1 that one would want to use scientific (e) notation. - - places may be negative: e.g. places = -2 means rounding to a multiple of .01 -**/ -inline double decimal_round(double const x, int const places) { - //TODO: possibly implement with modulus instead? - double const multiplier = std::pow(10.0, places); - return round( x * multiplier ) / multiplier; -} - - void binomial_coefficients(std::vector& bc, size_t n); } diff --git a/src/arc-context.cpp b/src/arc-context.cpp index 1c480ecbc..76b064f06 100644 --- a/src/arc-context.cpp +++ b/src/arc-context.cpp @@ -447,7 +447,7 @@ static void sp_arc_drag(SPArcContext *ac, Geom::Point pt, guint state) Geom::Point c = r.midpoint(); if (!ctrl_save) { if (fabs(dir[Geom::X]) > 1E-6 && fabs(dir[Geom::Y]) > 1E-6) { - Geom::Matrix const i2d ((ac->item)->i2d_affine ()); + Geom::Affine const i2d ((ac->item)->i2d_affine ()); Geom::Point new_dir = pt * i2d - c; new_dir[Geom::X] *= dir[Geom::Y] / dir[Geom::X]; double lambda = new_dir.length() / dir[Geom::Y]; diff --git a/src/box3d.cpp b/src/box3d.cpp index d51df9df3..cc3280150 100644 --- a/src/box3d.cpp +++ b/src/box3d.cpp @@ -49,7 +49,7 @@ static void box3d_update(SPObject *object, SPCtx *ctx, guint flags); static Inkscape::XML::Node *box3d_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); static gchar *box3d_description(SPItem *item); -static Geom::Matrix box3d_set_transform(SPItem *item, Geom::Matrix const &xform); +static Geom::Affine box3d_set_transform(SPItem *item, Geom::Affine const &xform); static void box3d_convert_to_guides(SPItem *item); static void box3d_ref_changed(SPObject *old_ref, SPObject *ref, SPBox3D *box); @@ -335,15 +335,15 @@ void box3d_position_set(SPBox3D *box) } } -static Geom::Matrix -box3d_set_transform(SPItem *item, Geom::Matrix const &xform) +static Geom::Affine +box3d_set_transform(SPItem *item, Geom::Affine const &xform) { SPBox3D *box = SP_BOX3D(item); // We don't apply the transform to the box directly but instead to its perspective (which is // done in sp_selection_apply_affine). Here we only adjust strokes, patterns, etc. - Geom::Matrix ret(Geom::Matrix(xform).without_translation()); + Geom::Affine ret(Geom::Affine(xform).withoutTranslation()); gdouble const sw = hypot(ret[0], ret[1]); gdouble const sh = hypot(ret[2], ret[3]); @@ -390,7 +390,7 @@ box3d_get_corner_screen (SPBox3D const *box, guint id, bool item_coords) { if (!box3d_get_perspective(box)) { return Geom::Point (NR_HUGE, NR_HUGE); } - Geom::Matrix const i2d (SP_ITEM(box)->i2d_affine ()); + Geom::Affine const i2d (SP_ITEM(box)->i2d_affine ()); if (item_coords) { return box3d_get_perspective(box)->perspective_impl->tmat.image(proj_corner).affine() * i2d.inverse(); } else { @@ -414,7 +414,7 @@ box3d_get_center_screen (SPBox3D *box) { if (!box3d_get_perspective(box)) { return Geom::Point (NR_HUGE, NR_HUGE); } - Geom::Matrix const i2d (SP_ITEM(box)->i2d_affine ()); + Geom::Affine const i2d (SP_ITEM(box)->i2d_affine ()); return box3d_get_perspective(box)->perspective_impl->tmat.image(proj_center).affine() * i2d.inverse(); } diff --git a/src/conn-avoid-ref.cpp b/src/conn-avoid-ref.cpp index 21ef2deab..410090e22 100644 --- a/src/conn-avoid-ref.cpp +++ b/src/conn-avoid-ref.cpp @@ -390,7 +390,7 @@ Geom::Point SPAvoidRef::getConnectionPointPos(const int type, const int id) { g_assert(item); Geom::Point pos; - const Geom::Matrix& transform = item->i2doc_affine(); + const Geom::Affine& transform = item->i2doc_affine(); if ( type == ConnPointDefault ) { @@ -475,7 +475,7 @@ static std::vector approxCurveWithPoints(SPCurve *curve) return poly_points; } -static std::vector approxItemWithPoints(SPItem const *item, const Geom::Matrix& item_transform) +static std::vector approxItemWithPoints(SPItem const *item, const Geom::Affine& item_transform) { // The structure to hold the output std::vector poly_points; @@ -512,7 +512,7 @@ static Avoid::Polygon avoid_item_poly(SPItem const *item) g_assert(desktop != NULL); double spacing = desktop->namedview->connector_spacing; - Geom::Matrix itd_mat = item->i2doc_affine(); + Geom::Affine itd_mat = item->i2doc_affine(); std::vector hull_points; hull_points = approxItemWithPoints(item, itd_mat); @@ -525,15 +525,15 @@ static Avoid::Polygon avoid_item_poly(SPItem const *item) Geom::Line hull_edge(hull[-1], hull[0]); Geom::Line prev_parallel_hull_edge; - prev_parallel_hull_edge.origin(hull_edge.origin()+hull_edge.versor().ccw()*spacing); - prev_parallel_hull_edge.versor(hull_edge.versor()); + prev_parallel_hull_edge.setOrigin(hull_edge.origin()+hull_edge.versor().ccw()*spacing); + prev_parallel_hull_edge.setVersor(hull_edge.versor()); int hull_size = hull.boundary.size(); for (int i = 0; i < hull_size; ++i) { - hull_edge.setBy2Points(hull[i], hull[i+1]); + hull_edge.setPoints(hull[i], hull[i+1]); Geom::Line parallel_hull_edge; - parallel_hull_edge.origin(hull_edge.origin()+hull_edge.versor().ccw()*spacing); - parallel_hull_edge.versor(hull_edge.versor()); + parallel_hull_edge.setOrigin(hull_edge.origin()+hull_edge.versor().ccw()*spacing); + parallel_hull_edge.setVersor(hull_edge.versor()); // determine the intersection point @@ -578,7 +578,7 @@ GSList *get_avoided_items(GSList *list, SPObject *from, SPDesktop *desktop, } -void avoid_item_move(Geom::Matrix const */*mp*/, SPItem *moved_item) +void avoid_item_move(Geom::Affine const */*mp*/, SPItem *moved_item) { Avoid::ShapeRef *shapeRef = moved_item->avoidRef->shapeRef; g_assert(shapeRef); diff --git a/src/conn-avoid-ref.h b/src/conn-avoid-ref.h index 5dff8dd38..eaf479e37 100644 --- a/src/conn-avoid-ref.h +++ b/src/conn-avoid-ref.h @@ -65,7 +65,7 @@ private: extern GSList *get_avoided_items(GSList *list, SPObject *from, SPDesktop *desktop, bool initialised = true); -extern void avoid_item_move(Geom::Matrix const *mp, SPItem *moved_item); +extern void avoid_item_move(Geom::Affine const *mp, SPItem *moved_item); extern void init_avoided_shape_geometry(SPDesktop *desktop); static const double defaultConnSpacing = 3.0; diff --git a/src/connector-context.cpp b/src/connector-context.cpp index f4b202451..ac39831b7 100644 --- a/src/connector-context.cpp +++ b/src/connector-context.cpp @@ -977,8 +977,8 @@ connector_handle_motion_notify(SPConnectorContext *const cc, GdkEventMotion cons m.unSetup(); // Update the hidden path - Geom::Matrix i2d = (cc->clickeditem)->i2d_affine(); - Geom::Matrix d2i = i2d.inverse(); + Geom::Affine i2d = (cc->clickeditem)->i2d_affine(); + Geom::Affine d2i = i2d.inverse(); SPPath *path = SP_PATH(cc->clickeditem); SPCurve *curve = path->original_curve ? path->original_curve : path->curve; if (cc->clickedhandle == cc->endpt_handle[0]) { @@ -1203,7 +1203,7 @@ connector_handle_key_press(SPConnectorContext *const cc, guint const keyval) // Obtain original position ConnectionPoint const& cp = cc->connpthandles[cc->selected_handle]; SPDesktop *desktop = SP_EVENT_CONTEXT_DESKTOP(cc); - const Geom::Matrix& i2doc = (cc->active_shape)->i2doc_affine(); + const Geom::Affine& i2doc = (cc->active_shape)->i2doc_affine(); sp_knot_set_position(cc->selected_handle, cp.pos * i2doc * desktop->doc2dt(), 0); cc->state = SP_CONNECTOR_CONTEXT_IDLE; desktop->messageStack()->flash( Inkscape::NORMAL_MESSAGE, @@ -1607,7 +1607,7 @@ endpt_handler(SPKnot */*knot*/, GdkEvent *event, SPConnectorContext *cc) // Show the red path for dragging. cc->red_curve = SP_PATH(cc->clickeditem)->original_curve ? SP_PATH(cc->clickeditem)->original_curve->copy() : SP_PATH(cc->clickeditem)->curve->copy(); - Geom::Matrix i2d = (cc->clickeditem)->i2d_affine(); + Geom::Affine i2d = (cc->clickeditem)->i2d_affine(); cc->red_curve->transform(i2d); sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), cc->red_curve); @@ -1766,7 +1766,7 @@ cc_set_active_conn(SPConnectorContext *cc, SPItem *item) g_assert( SP_IS_PATH(item) ); SPCurve *curve = SP_PATH(item)->original_curve ? SP_PATH(item)->original_curve : SP_PATH(item)->curve; - Geom::Matrix i2d = item->i2d_affine(); + Geom::Affine i2d = item->i2d_affine(); if (cc->active_conn == item) { diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp index c580d6767..b8de8aadc 100644 --- a/src/desktop-style.cpp +++ b/src/desktop-style.cpp @@ -121,7 +121,7 @@ sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines) // Scale the style by the inverse of the accumulated parent transform in the paste context. { - Geom::Matrix const local(SP_ITEM(o)->i2doc_affine()); + Geom::Affine const local(SP_ITEM(o)->i2doc_affine()); double const ex(local.descrim()); if ( ( ex != 0. ) && ( ex != 1. ) ) { @@ -420,7 +420,7 @@ stroke_average_width (GSList const *objects) if (!SP_IS_ITEM (l->data)) continue; - Geom::Matrix i2d = SP_ITEM(l->data)->i2d_affine(); + Geom::Affine i2d = SP_ITEM(l->data)->i2d_affine(); SPObject *object = SP_OBJECT(l->data); @@ -714,7 +714,7 @@ objects_query_strokewidth (GSList *objects, SPStyle *style_res) noneSet &= style->stroke.isNone(); - Geom::Matrix i2d = SP_ITEM(obj)->i2d_affine(); + Geom::Affine i2d = SP_ITEM(obj)->i2d_affine(); double sw = style->stroke_width.computed * i2d.descrim(); if (prev_sw != -1 && fabs(sw - prev_sw) > 1e-3) @@ -932,7 +932,7 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res) if (!style) continue; texts ++; - size += style->font_size.computed * Geom::Matrix(SP_ITEM(obj)->i2d_affine()).descrim(); /// \todo FIXME: we assume non-% units here + size += style->font_size.computed * Geom::Affine(SP_ITEM(obj)->i2d_affine()).descrim(); /// \todo FIXME: we assume non-% units here if (style->letter_spacing.normal) { if (!different && (letterspacing_prev == 0 || letterspacing_prev == letterspacing)) @@ -1380,7 +1380,7 @@ objects_query_blur (GSList *objects, SPStyle *style_res) if (!style) continue; if (!SP_IS_ITEM(obj)) continue; - Geom::Matrix i2d = SP_ITEM(obj)->i2d_affine(); + Geom::Affine i2d = SP_ITEM(obj)->i2d_affine(); items ++; diff --git a/src/desktop.cpp b/src/desktop.cpp index bfde0ee92..b382a1d91 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -1159,7 +1159,7 @@ SPDesktop::scroll_to_point (Geom::Point const &p, gdouble autoscrollspeed) if (!(p[X] > dbox.min()[X] && p[X] < dbox.max()[X]) || !(p[Y] > dbox.min()[Y] && p[Y] < dbox.max()[Y]) ) { - Geom::Point const s_w( p * (Geom::Matrix)_d2w ); + Geom::Point const s_w( p * (Geom::Affine)_d2w ); gdouble x_to; if (p[X] < dbox.min()[X]) @@ -1754,7 +1754,7 @@ _namedview_modified (SPObject *obj, guint flags, SPDesktop *desktop) } } -Geom::Matrix SPDesktop::w2d() const +Geom::Affine SPDesktop::w2d() const { return _w2d; } @@ -1769,12 +1769,12 @@ Geom::Point SPDesktop::d2w(Geom::Point const &p) const return p * _d2w; } -Geom::Matrix SPDesktop::doc2dt() const +Geom::Affine SPDesktop::doc2dt() const { return _doc2dt; } -Geom::Matrix SPDesktop::dt2doc() const +Geom::Affine SPDesktop::dt2doc() const { // doc2dt is its own inverse return _doc2dt; diff --git a/src/desktop.h b/src/desktop.h index 957c3b342..8f89df418 100644 --- a/src/desktop.h +++ b/src/desktop.h @@ -31,7 +31,7 @@ #include #include -#include <2geom/matrix.h> +#include <2geom/affine.h> #include <2geom/rect.h> #include "ui/view/view.h" @@ -312,11 +312,11 @@ public: void fullscreen(); void focusMode(bool mode = true); - Geom::Matrix w2d() const; //transformation from window to desktop coordinates (used for zooming) + Geom::Affine w2d() const; //transformation from window to desktop coordinates (used for zooming) Geom::Point w2d(Geom::Point const &p) const; Geom::Point d2w(Geom::Point const &p) const; - Geom::Matrix doc2dt() const; - Geom::Matrix dt2doc() const; + Geom::Affine doc2dt() const; + Geom::Affine dt2doc() const; Geom::Point doc2dt(Geom::Point const &p) const; Geom::Point dt2doc(Geom::Point const &p) const; @@ -335,9 +335,9 @@ private: Inkscape::Application *_inkscape; Inkscape::MessageContext *_guides_message_context; bool _active; - Geom::Matrix _w2d; - Geom::Matrix _d2w; - Geom::Matrix _doc2dt; + Geom::Affine _w2d; + Geom::Affine _d2w; + Geom::Affine _doc2dt; bool grids_visible; /* don't set this variable directly, use the method below */ void set_grids_visible(bool visible); diff --git a/src/dialogs/clonetiler.cpp b/src/dialogs/clonetiler.cpp index 8045675b4..bd5be5be5 100644 --- a/src/dialogs/clonetiler.cpp +++ b/src/dialogs/clonetiler.cpp @@ -196,7 +196,7 @@ enum { }; -static Geom::Matrix +static Geom::Affine clonetiler_get_transform ( // symmetry group @@ -287,7 +287,7 @@ clonetiler_get_transform ( if ( shifty_exp != 1.0 ) shiftj = pow( shiftj, shifty_exp ); // Final shift - Geom::Matrix rect_translate (Geom::Translate (w * shifti, h * shiftj)); + Geom::Affine rect_translate (Geom::Translate (w * shifti, h * shiftj)); // Rotation (in degrees) ------------ double delta_rotationi = 0.0; @@ -370,25 +370,25 @@ clonetiler_get_transform ( // Calculate transformation matrices, translating back to "center of tile" (rotation center) before transforming - Geom::Matrix drot_c = Geom::Translate(-cx, -cy) * Geom::Rotate (M_PI*dr/180) * Geom::Translate(cx, cy); + Geom::Affine drot_c = Geom::Translate(-cx, -cy) * Geom::Rotate (M_PI*dr/180) * Geom::Translate(cx, cy); - Geom::Matrix dscale_c = Geom::Translate(-cx, -cy) * Geom::Scale (scalex, scaley) * Geom::Translate(cx, cy); + Geom::Affine dscale_c = Geom::Translate(-cx, -cy) * Geom::Scale (scalex, scaley) * Geom::Translate(cx, cy); - Geom::Matrix d_s_r = dscale_c * drot_c; + Geom::Affine d_s_r = dscale_c * drot_c; - Geom::Matrix rotate_180_c = Geom::Translate(-cx, -cy) * Geom::Rotate (M_PI) * Geom::Translate(cx, cy); + Geom::Affine rotate_180_c = Geom::Translate(-cx, -cy) * Geom::Rotate (M_PI) * Geom::Translate(cx, cy); - Geom::Matrix rotate_90_c = Geom::Translate(-cx, -cy) * Geom::Rotate (-M_PI/2) * Geom::Translate(cx, cy); - Geom::Matrix rotate_m90_c = Geom::Translate(-cx, -cy) * Geom::Rotate ( M_PI/2) * Geom::Translate(cx, cy); + Geom::Affine rotate_90_c = Geom::Translate(-cx, -cy) * Geom::Rotate (-M_PI/2) * Geom::Translate(cx, cy); + Geom::Affine rotate_m90_c = Geom::Translate(-cx, -cy) * Geom::Rotate ( M_PI/2) * Geom::Translate(cx, cy); - Geom::Matrix rotate_120_c = Geom::Translate(-cx, -cy) * Geom::Rotate (-2*M_PI/3) * Geom::Translate(cx, cy); - Geom::Matrix rotate_m120_c = Geom::Translate(-cx, -cy) * Geom::Rotate ( 2*M_PI/3) * Geom::Translate(cx, cy); + Geom::Affine rotate_120_c = Geom::Translate(-cx, -cy) * Geom::Rotate (-2*M_PI/3) * Geom::Translate(cx, cy); + Geom::Affine rotate_m120_c = Geom::Translate(-cx, -cy) * Geom::Rotate ( 2*M_PI/3) * Geom::Translate(cx, cy); - Geom::Matrix rotate_60_c = Geom::Translate(-cx, -cy) * Geom::Rotate (-M_PI/3) * Geom::Translate(cx, cy); - Geom::Matrix rotate_m60_c = Geom::Translate(-cx, -cy) * Geom::Rotate ( M_PI/3) * Geom::Translate(cx, cy); + Geom::Affine rotate_60_c = Geom::Translate(-cx, -cy) * Geom::Rotate (-M_PI/3) * Geom::Translate(cx, cy); + Geom::Affine rotate_m60_c = Geom::Translate(-cx, -cy) * Geom::Rotate ( M_PI/3) * Geom::Translate(cx, cy); - Geom::Matrix flip_x = Geom::Translate(-cx, -cy) * Geom::Scale (-1, 1) * Geom::Translate(cx, cy); - Geom::Matrix flip_y = Geom::Translate(-cx, -cy) * Geom::Scale (1, -1) * Geom::Translate(cx, cy); + Geom::Affine flip_x = Geom::Translate(-cx, -cy) * Geom::Scale (-1, 1) * Geom::Translate(cx, cy); + Geom::Affine flip_y = Geom::Translate(-cx, -cy) * Geom::Scale (1, -1) * Geom::Translate(cx, cy); // Create tile with required symmetry @@ -513,9 +513,9 @@ clonetiler_get_transform ( case TILE_P4: { - Geom::Matrix ori (Geom::Translate ((w + h) * pow((i/2), shiftx_exp) + dx, (h + w) * pow((j/2), shifty_exp) + dy)); - Geom::Matrix dia1 (Geom::Translate (w/2 + h/2, -h/2 + w/2)); - Geom::Matrix dia2 (Geom::Translate (-w/2 + h/2, h/2 + w/2)); + Geom::Affine ori (Geom::Translate ((w + h) * pow((i/2), shiftx_exp) + dx, (h + w) * pow((j/2), shifty_exp) + dy)); + Geom::Affine dia1 (Geom::Translate (w/2 + h/2, -h/2 + w/2)); + Geom::Affine dia2 (Geom::Translate (-w/2 + h/2, h/2 + w/2)); if (j % 2 == 0) { if (i % 2 == 0) { return d_s_r * ori; @@ -535,9 +535,9 @@ clonetiler_get_transform ( case TILE_P4M: { double max = MAX(w, h); - Geom::Matrix ori (Geom::Translate ((max + max) * pow((i/4), shiftx_exp) + dx, (max + max) * pow((j/2), shifty_exp) + dy)); - Geom::Matrix dia1 (Geom::Translate ( w/2 - h/2, h/2 - w/2)); - Geom::Matrix dia2 (Geom::Translate (-h/2 + w/2, w/2 - h/2)); + Geom::Affine ori (Geom::Translate ((max + max) * pow((i/4), shiftx_exp) + dx, (max + max) * pow((j/2), shifty_exp) + dy)); + Geom::Affine dia1 (Geom::Translate ( w/2 - h/2, h/2 - w/2)); + Geom::Affine dia2 (Geom::Translate (-h/2 + w/2, w/2 - h/2)); if (j % 2 == 0) { if (i % 4 == 0) { return d_s_r * ori; @@ -565,9 +565,9 @@ clonetiler_get_transform ( case TILE_P4G: { double max = MAX(w, h); - Geom::Matrix ori (Geom::Translate ((max + max) * pow((i/4), shiftx_exp) + dx, (max + max) * pow(j, shifty_exp) + dy)); - Geom::Matrix dia1 (Geom::Translate ( w/2 + h/2, h/2 - w/2)); - Geom::Matrix dia2 (Geom::Translate (-h/2 + w/2, w/2 + h/2)); + Geom::Affine ori (Geom::Translate ((max + max) * pow((i/4), shiftx_exp) + dx, (max + max) * pow(j, shifty_exp) + dy)); + Geom::Affine dia1 (Geom::Translate ( w/2 + h/2, h/2 - w/2)); + Geom::Affine dia2 (Geom::Translate (-h/2 + w/2, w/2 + h/2)); if (((i/4) + j) % 2 == 0) { if (i % 4 == 0) { return d_s_r * ori; @@ -596,20 +596,20 @@ clonetiler_get_transform ( { double width; double height; - Geom::Matrix dia1; - Geom::Matrix dia2; + Geom::Affine dia1; + Geom::Affine dia2; if (w > h) { width = w + w * cos60; height = 2 * w * sin60; - dia1 = Geom::Matrix (Geom::Translate (w/2 + w/2 * cos60, -(w/2 * sin60))); - dia2 = dia1 * Geom::Matrix (Geom::Translate (0, 2 * (w/2 * sin60))); + dia1 = Geom::Affine (Geom::Translate (w/2 + w/2 * cos60, -(w/2 * sin60))); + dia2 = dia1 * Geom::Affine (Geom::Translate (0, 2 * (w/2 * sin60))); } else { width = h * cos (M_PI/6); height = h; - dia1 = Geom::Matrix (Geom::Translate (h/2 * cos30, -(h/2 * sin30))); - dia2 = dia1 * Geom::Matrix (Geom::Translate (0, h/2)); + dia1 = Geom::Affine (Geom::Translate (h/2 * cos30, -(h/2 * sin30))); + dia2 = dia1 * Geom::Affine (Geom::Translate (0, h/2)); } - Geom::Matrix ori (Geom::Translate (width * pow((2*(i/3) + j%2), shiftx_exp) + dx, (height/2) * pow(j, shifty_exp) + dy)); + Geom::Affine ori (Geom::Translate (width * pow((2*(i/3) + j%2), shiftx_exp) + dx, (height/2) * pow(j, shifty_exp) + dy)); if (i % 3 == 0) { return d_s_r * ori; } else if (i % 3 == 1) { @@ -622,23 +622,23 @@ clonetiler_get_transform ( case TILE_P31M: { - Geom::Matrix ori; - Geom::Matrix dia1; - Geom::Matrix dia2; - Geom::Matrix dia3; - Geom::Matrix dia4; + Geom::Affine ori; + Geom::Affine dia1; + Geom::Affine dia2; + Geom::Affine dia3; + Geom::Affine dia4; if (w > h) { - ori = Geom::Matrix(Geom::Translate (w * pow((i/6) + 0.5*(j%2), shiftx_exp) + dx, (w * cos30) * pow(j, shifty_exp) + dy)); - dia1 = Geom::Matrix (Geom::Translate (0, h/2) * Geom::Translate (w/2, 0) * Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (-h/2 * cos30, -h/2 * sin30) ); - dia2 = dia1 * Geom::Matrix (Geom::Translate (h * cos30, h * sin30)); - dia3 = dia2 * Geom::Matrix (Geom::Translate (0, 2 * (w/2 * sin60 - h/2 * sin30))); - dia4 = dia3 * Geom::Matrix (Geom::Translate (-h * cos30, h * sin30)); + ori = Geom::Affine(Geom::Translate (w * pow((i/6) + 0.5*(j%2), shiftx_exp) + dx, (w * cos30) * pow(j, shifty_exp) + dy)); + dia1 = Geom::Affine (Geom::Translate (0, h/2) * Geom::Translate (w/2, 0) * Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (-h/2 * cos30, -h/2 * sin30) ); + dia2 = dia1 * Geom::Affine (Geom::Translate (h * cos30, h * sin30)); + dia3 = dia2 * Geom::Affine (Geom::Translate (0, 2 * (w/2 * sin60 - h/2 * sin30))); + dia4 = dia3 * Geom::Affine (Geom::Translate (-h * cos30, h * sin30)); } else { - ori = Geom::Matrix (Geom::Translate (2*h * cos30 * pow((i/6 + 0.5*(j%2)), shiftx_exp) + dx, (2*h - h * sin30) * pow(j, shifty_exp) + dy)); - dia1 = Geom::Matrix (Geom::Translate (0, -h/2) * Geom::Translate (h/2 * cos30, h/2 * sin30)); - dia2 = dia1 * Geom::Matrix (Geom::Translate (h * cos30, h * sin30)); - dia3 = dia2 * Geom::Matrix (Geom::Translate (0, h/2)); - dia4 = dia3 * Geom::Matrix (Geom::Translate (-h * cos30, h * sin30)); + ori = Geom::Affine (Geom::Translate (2*h * cos30 * pow((i/6 + 0.5*(j%2)), shiftx_exp) + dx, (2*h - h * sin30) * pow(j, shifty_exp) + dy)); + dia1 = Geom::Affine (Geom::Translate (0, -h/2) * Geom::Translate (h/2 * cos30, h/2 * sin30)); + dia2 = dia1 * Geom::Affine (Geom::Translate (h * cos30, h * sin30)); + dia3 = dia2 * Geom::Affine (Geom::Translate (0, h/2)); + dia4 = dia3 * Geom::Affine (Geom::Translate (-h * cos30, h * sin30)); } if (i % 6 == 0) { return d_s_r * ori; @@ -660,26 +660,26 @@ clonetiler_get_transform ( { double width; double height; - Geom::Matrix dia1; - Geom::Matrix dia2; - Geom::Matrix dia3; - Geom::Matrix dia4; + Geom::Affine dia1; + Geom::Affine dia2; + Geom::Affine dia3; + Geom::Affine dia4; if (w > h) { width = w + w * cos60; height = 2 * w * sin60; - dia1 = Geom::Matrix (Geom::Translate (0, h/2) * Geom::Translate (w/2, 0) * Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (-h/2 * cos30, -h/2 * sin30) ); - dia2 = dia1 * Geom::Matrix (Geom::Translate (h * cos30, h * sin30)); - dia3 = dia2 * Geom::Matrix (Geom::Translate (0, 2 * (w/2 * sin60 - h/2 * sin30))); - dia4 = dia3 * Geom::Matrix (Geom::Translate (-h * cos30, h * sin30)); + dia1 = Geom::Affine (Geom::Translate (0, h/2) * Geom::Translate (w/2, 0) * Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (-h/2 * cos30, -h/2 * sin30) ); + dia2 = dia1 * Geom::Affine (Geom::Translate (h * cos30, h * sin30)); + dia3 = dia2 * Geom::Affine (Geom::Translate (0, 2 * (w/2 * sin60 - h/2 * sin30))); + dia4 = dia3 * Geom::Affine (Geom::Translate (-h * cos30, h * sin30)); } else { width = 2 * h * cos (M_PI/6); height = 2 * h; - dia1 = Geom::Matrix (Geom::Translate (0, -h/2) * Geom::Translate (h/2 * cos30, h/2 * sin30)); - dia2 = dia1 * Geom::Matrix (Geom::Translate (h * cos30, h * sin30)); - dia3 = dia2 * Geom::Matrix (Geom::Translate (0, h/2)); - dia4 = dia3 * Geom::Matrix (Geom::Translate (-h * cos30, h * sin30)); + dia1 = Geom::Affine (Geom::Translate (0, -h/2) * Geom::Translate (h/2 * cos30, h/2 * sin30)); + dia2 = dia1 * Geom::Affine (Geom::Translate (h * cos30, h * sin30)); + dia3 = dia2 * Geom::Affine (Geom::Translate (0, h/2)); + dia4 = dia3 * Geom::Affine (Geom::Translate (-h * cos30, h * sin30)); } - Geom::Matrix ori (Geom::Translate (width * pow((2*(i/6) + j%2), shiftx_exp) + dx, (height/2) * pow(j, shifty_exp) + dy)); + Geom::Affine ori (Geom::Translate (width * pow((2*(i/6) + j%2), shiftx_exp) + dx, (height/2) * pow(j, shifty_exp) + dy)); if (i % 6 == 0) { return d_s_r * ori; } else if (i % 6 == 1) { @@ -698,24 +698,24 @@ clonetiler_get_transform ( case TILE_P6: { - Geom::Matrix ori; - Geom::Matrix dia1; - Geom::Matrix dia2; - Geom::Matrix dia3; - Geom::Matrix dia4; - Geom::Matrix dia5; + Geom::Affine ori; + Geom::Affine dia1; + Geom::Affine dia2; + Geom::Affine dia3; + Geom::Affine dia4; + Geom::Affine dia5; if (w > h) { - ori = Geom::Matrix(Geom::Translate (w * pow((2*(i/6) + (j%2)), shiftx_exp) + dx, (2*w * sin60) * pow(j, shifty_exp) + dy)); - dia1 = Geom::Matrix (Geom::Translate (w/2 * cos60, -w/2 * sin60)); - dia2 = dia1 * Geom::Matrix (Geom::Translate (w/2, 0)); - dia3 = dia2 * Geom::Matrix (Geom::Translate (w/2 * cos60, w/2 * sin60)); - dia4 = dia3 * Geom::Matrix (Geom::Translate (-w/2 * cos60, w/2 * sin60)); - dia5 = dia4 * Geom::Matrix (Geom::Translate (-w/2, 0)); + ori = Geom::Affine(Geom::Translate (w * pow((2*(i/6) + (j%2)), shiftx_exp) + dx, (2*w * sin60) * pow(j, shifty_exp) + dy)); + dia1 = Geom::Affine (Geom::Translate (w/2 * cos60, -w/2 * sin60)); + dia2 = dia1 * Geom::Affine (Geom::Translate (w/2, 0)); + dia3 = dia2 * Geom::Affine (Geom::Translate (w/2 * cos60, w/2 * sin60)); + dia4 = dia3 * Geom::Affine (Geom::Translate (-w/2 * cos60, w/2 * sin60)); + dia5 = dia4 * Geom::Affine (Geom::Translate (-w/2, 0)); } else { - ori = Geom::Matrix(Geom::Translate (2*h * cos30 * pow((i/6 + 0.5*(j%2)), shiftx_exp) + dx, (h + h * sin30) * pow(j, shifty_exp) + dy)); - dia1 = Geom::Matrix (Geom::Translate (-w/2, -h/2) * Geom::Translate (h/2 * cos30, -h/2 * sin30) * Geom::Translate (w/2 * cos60, w/2 * sin60)); - dia2 = dia1 * Geom::Matrix (Geom::Translate (-w/2 * cos60, -w/2 * sin60) * Geom::Translate (h/2 * cos30, -h/2 * sin30) * Geom::Translate (h/2 * cos30, h/2 * sin30) * Geom::Translate (-w/2 * cos60, w/2 * sin60)); - dia3 = dia2 * Geom::Matrix (Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (h/2 * cos30, h/2 * sin30) * Geom::Translate (-w/2, h/2)); + ori = Geom::Affine(Geom::Translate (2*h * cos30 * pow((i/6 + 0.5*(j%2)), shiftx_exp) + dx, (h + h * sin30) * pow(j, shifty_exp) + dy)); + dia1 = Geom::Affine (Geom::Translate (-w/2, -h/2) * Geom::Translate (h/2 * cos30, -h/2 * sin30) * Geom::Translate (w/2 * cos60, w/2 * sin60)); + dia2 = dia1 * Geom::Affine (Geom::Translate (-w/2 * cos60, -w/2 * sin60) * Geom::Translate (h/2 * cos30, -h/2 * sin30) * Geom::Translate (h/2 * cos30, h/2 * sin30) * Geom::Translate (-w/2 * cos60, w/2 * sin60)); + dia3 = dia2 * Geom::Affine (Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (h/2 * cos30, h/2 * sin30) * Geom::Translate (-w/2, h/2)); dia4 = dia3 * dia1.inverse(); dia5 = dia3 * dia2.inverse(); } @@ -738,28 +738,28 @@ clonetiler_get_transform ( case TILE_P6M: { - Geom::Matrix ori; - Geom::Matrix dia1, dia2, dia3, dia4, dia5, dia6, dia7, dia8, dia9, dia10; + Geom::Affine ori; + Geom::Affine dia1, dia2, dia3, dia4, dia5, dia6, dia7, dia8, dia9, dia10; if (w > h) { - ori = Geom::Matrix(Geom::Translate (w * pow((2*(i/12) + (j%2)), shiftx_exp) + dx, (2*w * sin60) * pow(j, shifty_exp) + dy)); - dia1 = Geom::Matrix (Geom::Translate (w/2, h/2) * Geom::Translate (-w/2 * cos60, -w/2 * sin60) * Geom::Translate (-h/2 * cos30, h/2 * sin30)); - dia2 = dia1 * Geom::Matrix (Geom::Translate (h * cos30, -h * sin30)); - dia3 = dia2 * Geom::Matrix (Geom::Translate (-h/2 * cos30, h/2 * sin30) * Geom::Translate (w * cos60, 0) * Geom::Translate (-h/2 * cos30, -h/2 * sin30)); - dia4 = dia3 * Geom::Matrix (Geom::Translate (h * cos30, h * sin30)); - dia5 = dia4 * Geom::Matrix (Geom::Translate (-h/2 * cos30, -h/2 * sin30) * Geom::Translate (-w/2 * cos60, w/2 * sin60) * Geom::Translate (w/2, -h/2)); - dia6 = dia5 * Geom::Matrix (Geom::Translate (0, h)); + ori = Geom::Affine(Geom::Translate (w * pow((2*(i/12) + (j%2)), shiftx_exp) + dx, (2*w * sin60) * pow(j, shifty_exp) + dy)); + dia1 = Geom::Affine (Geom::Translate (w/2, h/2) * Geom::Translate (-w/2 * cos60, -w/2 * sin60) * Geom::Translate (-h/2 * cos30, h/2 * sin30)); + dia2 = dia1 * Geom::Affine (Geom::Translate (h * cos30, -h * sin30)); + dia3 = dia2 * Geom::Affine (Geom::Translate (-h/2 * cos30, h/2 * sin30) * Geom::Translate (w * cos60, 0) * Geom::Translate (-h/2 * cos30, -h/2 * sin30)); + dia4 = dia3 * Geom::Affine (Geom::Translate (h * cos30, h * sin30)); + dia5 = dia4 * Geom::Affine (Geom::Translate (-h/2 * cos30, -h/2 * sin30) * Geom::Translate (-w/2 * cos60, w/2 * sin60) * Geom::Translate (w/2, -h/2)); + dia6 = dia5 * Geom::Affine (Geom::Translate (0, h)); dia7 = dia6 * dia1.inverse(); dia8 = dia6 * dia2.inverse(); dia9 = dia6 * dia3.inverse(); dia10 = dia6 * dia4.inverse(); } else { - ori = Geom::Matrix(Geom::Translate (4*h * cos30 * pow((i/12 + 0.5*(j%2)), shiftx_exp) + dx, (2*h + 2*h * sin30) * pow(j, shifty_exp) + dy)); - dia1 = Geom::Matrix (Geom::Translate (-w/2, -h/2) * Geom::Translate (h/2 * cos30, -h/2 * sin30) * Geom::Translate (w/2 * cos60, w/2 * sin60)); - dia2 = dia1 * Geom::Matrix (Geom::Translate (h * cos30, -h * sin30)); - dia3 = dia2 * Geom::Matrix (Geom::Translate (-w/2 * cos60, -w/2 * sin60) * Geom::Translate (h * cos30, 0) * Geom::Translate (-w/2 * cos60, w/2 * sin60)); - dia4 = dia3 * Geom::Matrix (Geom::Translate (h * cos30, h * sin30)); - dia5 = dia4 * Geom::Matrix (Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (h/2 * cos30, h/2 * sin30) * Geom::Translate (-w/2, h/2)); - dia6 = dia5 * Geom::Matrix (Geom::Translate (0, h)); + ori = Geom::Affine(Geom::Translate (4*h * cos30 * pow((i/12 + 0.5*(j%2)), shiftx_exp) + dx, (2*h + 2*h * sin30) * pow(j, shifty_exp) + dy)); + dia1 = Geom::Affine (Geom::Translate (-w/2, -h/2) * Geom::Translate (h/2 * cos30, -h/2 * sin30) * Geom::Translate (w/2 * cos60, w/2 * sin60)); + dia2 = dia1 * Geom::Affine (Geom::Translate (h * cos30, -h * sin30)); + dia3 = dia2 * Geom::Affine (Geom::Translate (-w/2 * cos60, -w/2 * sin60) * Geom::Translate (h * cos30, 0) * Geom::Translate (-w/2 * cos60, w/2 * sin60)); + dia4 = dia3 * Geom::Affine (Geom::Translate (h * cos30, h * sin30)); + dia5 = dia4 * Geom::Affine (Geom::Translate (w/2 * cos60, -w/2 * sin60) * Geom::Translate (h/2 * cos30, h/2 * sin30) * Geom::Translate (-w/2, h/2)); + dia6 = dia5 * Geom::Affine (Geom::Translate (0, h)); dia7 = dia6 * dia1.inverse(); dia8 = dia6 * dia2.inverse(); dia9 = dia6 * dia3.inverse(); @@ -870,7 +870,7 @@ clonetiler_trace_pick (Geom::Rect box) if (!trace_arena) return 0; - Geom::Matrix t(Geom::Scale(trace_zoom, trace_zoom)); + Geom::Affine t(Geom::Scale(trace_zoom, trace_zoom)); nr_arena_item_set_transform(trace_root, &t); NRGC gc(NULL); gc.transform.setIdentity(); @@ -1041,7 +1041,7 @@ clonetiler_remove( GtkWidget */*widget*/, void *, bool do_undo = true ) } static Geom::Rect -transform_rect( Geom::Rect const &r, Geom::Matrix const &m) +transform_rect( Geom::Rect const &r, Geom::Affine const &m) { using Geom::X; using Geom::Y; @@ -1263,7 +1263,7 @@ clonetiler_apply( GtkWidget */*widget*/, void * ) // Note: We create a clone at 0,0 too, right over the original, in case our clones are colored // Get transform from symmetry, shift, scale, rotation - Geom::Matrix t = clonetiler_get_transform (type, i, j, center[Geom::X], center[Geom::Y], w, h, + Geom::Affine t = clonetiler_get_transform (type, i, j, center[Geom::X], center[Geom::Y], w, h, shiftx_per_i, shifty_per_i, shiftx_per_j, shifty_per_j, shiftx_rand, shifty_rand, diff --git a/src/display/canvas-arena.cpp b/src/display/canvas-arena.cpp index fb7ca9d78..f3e1b0f0c 100644 --- a/src/display/canvas-arena.cpp +++ b/src/display/canvas-arena.cpp @@ -29,7 +29,7 @@ static void sp_canvas_arena_class_init(SPCanvasArenaClass *klass); static void sp_canvas_arena_init(SPCanvasArena *group); static void sp_canvas_arena_destroy(GtkObject *object); -static void sp_canvas_arena_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); +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 double sp_canvas_arena_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item); static gint sp_canvas_arena_event (SPCanvasItem *item, GdkEvent *event); @@ -134,7 +134,7 @@ sp_canvas_arena_destroy (GtkObject *object) } static void -sp_canvas_arena_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags) +sp_canvas_arena_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags) { SPCanvasArena *arena = SP_CANVAS_ARENA (item); diff --git a/src/display/canvas-axonomgrid.cpp b/src/display/canvas-axonomgrid.cpp index 550fd3559..845c4e077 100644 --- a/src/display/canvas-axonomgrid.cpp +++ b/src/display/canvas-axonomgrid.cpp @@ -511,7 +511,7 @@ CanvasAxonomGrid::updateWidgets() void -CanvasAxonomGrid::Update (Geom::Matrix const &affine, unsigned int /*flags*/) +CanvasAxonomGrid::Update (Geom::Affine const &affine, unsigned int /*flags*/) { ow = origin * affine; sw = Geom::Point(fabs(affine[0]),fabs(affine[3])); diff --git a/src/display/canvas-axonomgrid.h b/src/display/canvas-axonomgrid.h index 58185e2e6..282524c74 100644 --- a/src/display/canvas-axonomgrid.h +++ b/src/display/canvas-axonomgrid.h @@ -34,7 +34,7 @@ public: CanvasAxonomGrid(SPNamedView * nv, Inkscape::XML::Node * in_repr, SPDocument * in_doc); virtual ~CanvasAxonomGrid(); - void Update (Geom::Matrix const &affine, unsigned int flags); + void Update (Geom::Affine const &affine, unsigned int flags); void Render (SPCanvasBuf *buf); void readRepr(); diff --git a/src/display/canvas-bpath.cpp b/src/display/canvas-bpath.cpp index f8a8ef22c..725a1d0ff 100644 --- a/src/display/canvas-bpath.cpp +++ b/src/display/canvas-bpath.cpp @@ -34,7 +34,7 @@ static void sp_canvas_bpath_class_init (SPCanvasBPathClass *klass); static void sp_canvas_bpath_init (SPCanvasBPath *path); static void sp_canvas_bpath_destroy (GtkObject *object); -static void sp_canvas_bpath_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); +static void sp_canvas_bpath_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); static void sp_canvas_bpath_render (SPCanvasItem *item, SPCanvasBuf *buf); static double sp_canvas_bpath_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item); @@ -103,7 +103,7 @@ sp_canvas_bpath_destroy (GtkObject *object) } static void -sp_canvas_bpath_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags) +sp_canvas_bpath_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags) { SPCanvasBPath *cbp = SP_CANVAS_BPATH (item); diff --git a/src/display/canvas-bpath.h b/src/display/canvas-bpath.h index 0760baef6..7f8b75dfe 100644 --- a/src/display/canvas-bpath.h +++ b/src/display/canvas-bpath.h @@ -67,7 +67,7 @@ struct SPCanvasBPath { /* Line def */ SPCurve *curve; - Geom::Matrix affine; + Geom::Affine affine; /* Fill attributes */ guint32 fill_rgba; diff --git a/src/display/canvas-grid.cpp b/src/display/canvas-grid.cpp index 5892e1dc7..79bfc31ad 100644 --- a/src/display/canvas-grid.cpp +++ b/src/display/canvas-grid.cpp @@ -52,7 +52,7 @@ static void grid_canvasitem_class_init (GridCanvasItemClass *klass); static void grid_canvasitem_init (GridCanvasItem *grid); static void grid_canvasitem_destroy (GtkObject *object); -static void grid_canvasitem_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); +static void grid_canvasitem_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); static void grid_canvasitem_render (SPCanvasItem *item, SPCanvasBuf *buf); static SPCanvasItemClass * parent_class; @@ -124,7 +124,7 @@ grid_canvasitem_render (SPCanvasItem * item, SPCanvasBuf * buf) } static void -grid_canvasitem_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags) +grid_canvasitem_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags) { GridCanvasItem *gridcanvasitem = INKSCAPE_GRID_CANVASITEM (item); @@ -803,7 +803,7 @@ CanvasXYGrid::updateWidgets() void -CanvasXYGrid::Update (Geom::Matrix const &affine, unsigned int /*flags*/) +CanvasXYGrid::Update (Geom::Affine const &affine, unsigned int /*flags*/) { ow = origin * affine; sw = spacing * affine; diff --git a/src/display/canvas-grid.h b/src/display/canvas-grid.h index b8f313948..f386fe05e 100644 --- a/src/display/canvas-grid.h +++ b/src/display/canvas-grid.h @@ -79,7 +79,7 @@ public: GridCanvasItem * createCanvasItem(SPDesktop * desktop); - virtual void Update (Geom::Matrix const &affine, unsigned int flags) = 0; + virtual void Update (Geom::Affine const &affine, unsigned int flags) = 0; virtual void Render (SPCanvasBuf *buf) = 0; virtual void readRepr() = 0; @@ -129,7 +129,7 @@ public: CanvasXYGrid(SPNamedView * nv, Inkscape::XML::Node * in_repr, SPDocument * in_doc); virtual ~CanvasXYGrid(); - void Update (Geom::Matrix const &affine, unsigned int flags); + void Update (Geom::Affine const &affine, unsigned int flags); void Render (SPCanvasBuf *buf); void readRepr(); diff --git a/src/display/canvas-text.cpp b/src/display/canvas-text.cpp index e2bc09679..70196b307 100644 --- a/src/display/canvas-text.cpp +++ b/src/display/canvas-text.cpp @@ -31,7 +31,7 @@ static void sp_canvastext_class_init (SPCanvasTextClass *klass); static void sp_canvastext_init (SPCanvasText *canvastext); static void sp_canvastext_destroy (GtkObject *object); -static void sp_canvastext_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); +static void sp_canvastext_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); static void sp_canvastext_render (SPCanvasItem *item, SPCanvasBuf *buf); static SPCanvasItemClass *parent_class_ct; @@ -133,7 +133,7 @@ sp_canvastext_render (SPCanvasItem *item, SPCanvasBuf *buf) } static void -sp_canvastext_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags) +sp_canvastext_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags) { SPCanvasText *cl = SP_CANVASTEXT (item); diff --git a/src/display/canvas-text.h b/src/display/canvas-text.h index cc194ccc4..d8bd86b7d 100644 --- a/src/display/canvas-text.h +++ b/src/display/canvas-text.h @@ -31,7 +31,7 @@ struct SPCanvasText : public SPCanvasItem { gchar* text; Geom::Point s; - Geom::Matrix affine; + Geom::Affine affine; double fontsize; double anchor_x; double anchor_y; diff --git a/src/display/curve.cpp b/src/display/curve.cpp index 303d1bb4d..5c18324eb 100644 --- a/src/display/curve.cpp +++ b/src/display/curve.cpp @@ -180,7 +180,7 @@ SPCurve::split() const * Transform all paths in curve using matrix. */ void -SPCurve::transform(Geom::Matrix const &m) +SPCurve::transform(Geom::Affine const &m) { _pathv *= m; } diff --git a/src/display/curve.h b/src/display/curve.h index e6387a9f0..ec828e674 100644 --- a/src/display/curve.h +++ b/src/display/curve.h @@ -67,7 +67,7 @@ public: void closepath_current(); void backspace(); - void transform(Geom::Matrix const &m); + void transform(Geom::Affine const &m); void stretch_endpoints(Geom::Point const &, Geom::Point const &); void move_endpoints(Geom::Point const &, Geom::Point const &); void last_point_additive_move(Geom::Point const & p); diff --git a/src/display/gnome-canvas-acetate.cpp b/src/display/gnome-canvas-acetate.cpp index c257f1f92..b86892e32 100644 --- a/src/display/gnome-canvas-acetate.cpp +++ b/src/display/gnome-canvas-acetate.cpp @@ -20,7 +20,7 @@ static void sp_canvas_acetate_class_init (SPCanvasAcetateClass *klass); static void sp_canvas_acetate_init (SPCanvasAcetate *acetate); static void sp_canvas_acetate_destroy (GtkObject *object); -static void sp_canvas_acetate_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); +static void sp_canvas_acetate_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); static double sp_canvas_acetate_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item); static SPCanvasItemClass *parent_class; @@ -81,7 +81,7 @@ sp_canvas_acetate_destroy (GtkObject *object) } static void -sp_canvas_acetate_update( SPCanvasItem *item, Geom::Matrix const &/*affine*/, unsigned int /*flags*/ ) +sp_canvas_acetate_update( SPCanvasItem *item, Geom::Affine const &/*affine*/, unsigned int /*flags*/ ) { item->x1 = -G_MAXINT; item->y1 = -G_MAXINT; diff --git a/src/display/guideline.cpp b/src/display/guideline.cpp index ce1289faf..bebec2852 100644 --- a/src/display/guideline.cpp +++ b/src/display/guideline.cpp @@ -24,7 +24,7 @@ static void sp_guideline_class_init(SPGuideLineClass *c); static void sp_guideline_init(SPGuideLine *guideline); static void sp_guideline_destroy(GtkObject *object); -static void sp_guideline_update(SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); +static void sp_guideline_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf); static double sp_guideline_point(SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item); @@ -183,7 +183,7 @@ static void sp_guideline_render(SPCanvasItem *item, SPCanvasBuf *buf) } } -static void sp_guideline_update(SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags) +static void sp_guideline_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags) { SPGuideLine *gl = SP_GUIDELINE(item); @@ -243,8 +243,8 @@ SPCanvasItem *sp_guideline_new(SPCanvasGroup *parent, Geom::Point point_on_line, void sp_guideline_set_position(SPGuideLine *gl, Geom::Point point_on_line) { - sp_canvas_item_affine_absolute(SP_CANVAS_ITEM (gl), Geom::Matrix(Geom::Translate(point_on_line))); - sp_canvas_item_affine_absolute(SP_CANVAS_ITEM (gl->origin), Geom::Matrix(Geom::Translate(point_on_line))); + sp_canvas_item_affine_absolute(SP_CANVAS_ITEM (gl), Geom::Affine(Geom::Translate(point_on_line))); + sp_canvas_item_affine_absolute(SP_CANVAS_ITEM (gl->origin), Geom::Affine(Geom::Translate(point_on_line))); } void sp_guideline_set_normal(SPGuideLine *gl, Geom::Point normal_to_line) diff --git a/src/display/inkscape-cairo.cpp b/src/display/inkscape-cairo.cpp index fdbd49727..4fc492ba8 100644 --- a/src/display/inkscape-cairo.cpp +++ b/src/display/inkscape-cairo.cpp @@ -22,7 +22,7 @@ #include <2geom/pathvector.h> #include <2geom/bezier-curve.h> #include <2geom/hvlinesegment.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> #include <2geom/point.h> #include <2geom/path.h> #include <2geom/transforms.h> @@ -73,7 +73,7 @@ nr_create_cairo_context (NRRectL *area, NRPixBlock *pb) * If optimize_stroke == false, the view Rect is not used. */ static void -feed_curve_to_cairo(cairo_t *cr, Geom::Curve const &c, Geom::Matrix const & trans, Geom::Rect view, bool optimize_stroke) +feed_curve_to_cairo(cairo_t *cr, Geom::Curve const &c, Geom::Affine const & trans, Geom::Rect view, bool optimize_stroke) { if( is_straight_curve(c) ) { @@ -163,7 +163,7 @@ feed_path_to_cairo (cairo_t *ct, Geom::Path const &path) /** Feeds path-creating calls to the cairo context translating them from the Path, with the given transform and shift */ static void -feed_path_to_cairo (cairo_t *ct, Geom::Path const &path, Geom::Matrix trans, Geom::OptRect area, bool optimize_stroke, double stroke_width) +feed_path_to_cairo (cairo_t *ct, Geom::Path const &path, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width) { if (!area) return; @@ -174,9 +174,9 @@ feed_path_to_cairo (cairo_t *ct, Geom::Path const &path, Geom::Matrix trans, Geo Geom::Point shift = area->min(); Geom::Rect view = *area; view.expandBy (stroke_width); - view = view * (Geom::Matrix)Geom::Translate(-shift); + view = view * (Geom::Affine)Geom::Translate(-shift); // Pass transformation to feed_curve, so that we don't need to create a whole new path. - Geom::Matrix transshift(trans * Geom::Translate(-shift)); + Geom::Affine transshift(trans * Geom::Translate(-shift)); Geom::Point initial = path.initialPoint() * transshift; cairo_move_to(ct, initial[0], initial[1] ); @@ -211,7 +211,7 @@ feed_path_to_cairo (cairo_t *ct, Geom::Path const &path, Geom::Matrix trans, Geo /** Feeds path-creating calls to the cairo context translating them from the PathVector, with the given transform and shift * One must have done cairo_new_path(ct); before calling this function. */ void -feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Matrix trans, Geom::OptRect area, bool optimize_stroke, double stroke_width) +feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width) { if (!area) return; diff --git a/src/display/inkscape-cairo.h b/src/display/inkscape-cairo.h index 0b3c99a7f..4133661fe 100644 --- a/src/display/inkscape-cairo.h +++ b/src/display/inkscape-cairo.h @@ -21,7 +21,7 @@ class SPCanvasBuf; cairo_t *nr_create_cairo_context_canvasbuf (NRRectL *area, SPCanvasBuf *b); cairo_t *nr_create_cairo_context (NRRectL *area, NRPixBlock *pb); -void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Matrix trans, Geom::OptRect area, bool optimize_stroke, double stroke_width); +void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv, Geom::Affine trans, Geom::OptRect area, bool optimize_stroke, double stroke_width); void feed_pathvector_to_cairo (cairo_t *ct, Geom::PathVector const &pathv); #endif diff --git a/src/display/nr-3dutils.cpp b/src/display/nr-3dutils.cpp index de97c2e04..c5e7b4c1b 100644 --- a/src/display/nr-3dutils.cpp +++ b/src/display/nr-3dutils.cpp @@ -137,7 +137,7 @@ void compute_surface_normal(Fvector &N, gdouble ss, NRPixBlock *in, int i, int j //std::cout << "(" << N[X_3D] << ", " << N[Y_3D] << ", " << N[Z_3D] << ")" << std::endl; } -void convert_coord(gdouble &x, gdouble &y, gdouble &z, Geom::Matrix const &trans) { +void convert_coord(gdouble &x, gdouble &y, gdouble &z, Geom::Affine const &trans) { Point p = Point(x, y); p *= trans; x = p[Geom::X]; diff --git a/src/display/nr-3dutils.h b/src/display/nr-3dutils.h index 01138cf1f..56bed6ba2 100644 --- a/src/display/nr-3dutils.h +++ b/src/display/nr-3dutils.h @@ -94,7 +94,7 @@ void compute_surface_normal(Fvector &N, gdouble ss, NRPixBlock *in, int i, int j * \param z a reference to a z coordinate * \param z a reference to a transformation matrix */ -void convert_coord(gdouble &x, gdouble &y, gdouble &z, Geom::Matrix const &trans); +void convert_coord(gdouble &x, gdouble &y, gdouble &z, Geom::Affine const &trans); } /* namespace NR */ diff --git a/src/display/nr-arena-glyphs.cpp b/src/display/nr-arena-glyphs.cpp index fb7f57272..440a87012 100644 --- a/src/display/nr-arena-glyphs.cpp +++ b/src/display/nr-arena-glyphs.cpp @@ -18,7 +18,7 @@ #endif #include #include -#include <2geom/matrix.h> +#include <2geom/affine.h> #include "../style.h" #include "nr-arena.h" #include "nr-arena-glyphs.h" @@ -143,7 +143,7 @@ nr_arena_glyphs_update(NRArenaItem *item, NRRectL */*area*/, NRGC *gc, guint /*s float const scale = gc->transform.descrim(); if (!glyphs->style->fill.isNone()) { - Geom::Matrix t; + Geom::Affine t; t = glyphs->g_transform * gc->transform; glyphs->x = t[4]; glyphs->y = t[5]; @@ -165,7 +165,7 @@ nr_arena_glyphs_update(NRArenaItem *item, NRRectL */*area*/, NRGC *gc, guint /*s if (!glyphs->style->stroke.isNone()) { /* Build state data */ - Geom::Matrix t; + Geom::Affine t; t = glyphs->g_transform * gc->transform; glyphs->x = t[4]; glyphs->y = t[5]; @@ -252,7 +252,7 @@ nr_arena_glyphs_pick(NRArenaItem *item, Geom::Point p, gdouble delta, unsigned i } void -nr_arena_glyphs_set_path(NRArenaGlyphs *glyphs, SPCurve */*curve*/, unsigned int /*lieutenant*/, font_instance *font, gint glyph, Geom::Matrix const *transform) +nr_arena_glyphs_set_path(NRArenaGlyphs *glyphs, SPCurve */*curve*/, unsigned int /*lieutenant*/, font_instance *font, gint glyph, Geom::Affine const *transform) { nr_return_if_fail(glyphs != NULL); nr_return_if_fail(NR_IS_ARENA_GLYPHS(glyphs)); @@ -463,7 +463,7 @@ nr_arena_glyphs_group_render(cairo_t *ct, NRArenaItem *item, NRRectL *area, NRPi Geom::PathVector const * pathv = g->font->PathVector(g->glyph); cairo_new_path(ct); - Geom::Matrix transform = g->g_transform * group->ctm; + Geom::Affine transform = g->g_transform * group->ctm; feed_pathvector_to_cairo (ct, *pathv, transform, to_2geom((pb->area).upgrade()), false, 0); cairo_fill(ct); pb->empty = FALSE; @@ -613,7 +613,7 @@ nr_arena_glyphs_group_clear(NRArenaGlyphsGroup *sg) } void -nr_arena_glyphs_group_add_component(NRArenaGlyphsGroup *sg, font_instance *font, int glyph, Geom::Matrix const &transform) +nr_arena_glyphs_group_add_component(NRArenaGlyphsGroup *sg, font_instance *font, int glyph, Geom::Affine const &transform) { NRArenaGroup *group; diff --git a/src/display/nr-arena-glyphs.h b/src/display/nr-arena-glyphs.h index 1d15fef81..d04fdb4dc 100644 --- a/src/display/nr-arena-glyphs.h +++ b/src/display/nr-arena-glyphs.h @@ -33,7 +33,7 @@ NRType nr_arena_glyphs_get_type (void); struct NRArenaGlyphs : public NRArenaItem { /* Glyphs data */ SPStyle *style; - Geom::Matrix g_transform; + Geom::Affine g_transform; font_instance *font; gint glyph; @@ -41,7 +41,7 @@ struct NRArenaGlyphs : public NRArenaItem { raster_font *sfont; float x, y; -// Geom::Matrix cached_tr; +// Geom::Affine cached_tr; // Shape *cached_shp; // bool cached_shp_dirty; // bool cached_style_dirty; @@ -62,7 +62,7 @@ struct NRArenaGlyphsClass { void nr_arena_glyphs_set_path ( NRArenaGlyphs *glyphs, SPCurve *curve, unsigned int lieutenant, font_instance *font, int glyph, - Geom::Matrix const *transform ); + Geom::Affine const *transform ); void nr_arena_glyphs_set_style (NRArenaGlyphs *glyphs, SPStyle *style); /* Integrated group of component glyphss */ @@ -100,7 +100,7 @@ struct NRArenaGlyphsGroupClass { void nr_arena_glyphs_group_clear (NRArenaGlyphsGroup *group); -void nr_arena_glyphs_group_add_component (NRArenaGlyphsGroup *group, font_instance *font, int glyph, Geom::Matrix const &transform); +void nr_arena_glyphs_group_add_component (NRArenaGlyphsGroup *group, font_instance *font, int glyph, Geom::Affine const &transform); void nr_arena_glyphs_group_set_style (NRArenaGlyphsGroup *group, SPStyle *style); diff --git a/src/display/nr-arena-group.cpp b/src/display/nr-arena-group.cpp index e339fe5a7..6c6043b2c 100644 --- a/src/display/nr-arena-group.cpp +++ b/src/display/nr-arena-group.cpp @@ -271,13 +271,13 @@ nr_arena_group_set_transparent (NRArenaGroup *group, unsigned int transparent) group->transparent = transparent; } -void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Matrix const &t) +void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const &t) { - Geom::Matrix nt(t); + Geom::Affine nt(t); nr_arena_group_set_child_transform(group, &nt); } -void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Matrix const *t) +void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const *t) { if (!t) t = &GEOM_MATRIX_IDENTITY; diff --git a/src/display/nr-arena-group.h b/src/display/nr-arena-group.h index 4579d068f..58394643c 100644 --- a/src/display/nr-arena-group.h +++ b/src/display/nr-arena-group.h @@ -26,7 +26,7 @@ struct NRArenaGroup : public NRArenaItem{ unsigned int transparent : 1; NRArenaItem *children; NRArenaItem *last; - Geom::Matrix child_transform; + Geom::Affine child_transform; SPStyle *style; static NRArenaGroup *create(NRArena *arena) { @@ -42,8 +42,8 @@ struct NRArenaGroupClass { void nr_arena_group_set_transparent(NRArenaGroup *group, unsigned int transparent); -void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Matrix const &t); -void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Matrix const *t); +void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const &t); +void nr_arena_group_set_child_transform(NRArenaGroup *group, Geom::Affine const *t); void nr_arena_group_set_style(NRArenaGroup *group, SPStyle *style); #endif diff --git a/src/display/nr-arena-image.cpp b/src/display/nr-arena-image.cpp index 4132ada78..6539ae4d2 100644 --- a/src/display/nr-arena-image.cpp +++ b/src/display/nr-arena-image.cpp @@ -108,7 +108,7 @@ nr_arena_image_finalize (NRObject *object) static unsigned int nr_arena_image_update( NRArenaItem *item, NRRectL */*area*/, NRGC *gc, unsigned int /*state*/, unsigned int /*reset*/ ) { - Geom::Matrix grid2px; + Geom::Affine grid2px; // clear old bbox nr_arena_item_request_render(item); @@ -180,7 +180,7 @@ nr_arena_image_render( cairo_t *ct, NRArenaItem *item, NRRectL */*area*/, NRPixB NRArenaImage *image = NR_ARENA_IMAGE (item); - Geom::Matrix d2s; + Geom::Affine d2s; d2s[0] = b2i[0]; d2s[1] = b2i[1]; diff --git a/src/display/nr-arena-image.h b/src/display/nr-arena-image.h index 48ebc5bd0..c8d1525dc 100644 --- a/src/display/nr-arena-image.h +++ b/src/display/nr-arena-image.h @@ -34,7 +34,7 @@ struct NRArenaImage : public NRArenaItem { Geom::Point c00, c01, c11, c10; // all 4 corners of the image, for outline mode rect /* From GRID to PIXELS */ - Geom::Matrix grid2px; + Geom::Affine grid2px; SPStyle *style; diff --git a/src/display/nr-arena-item.cpp b/src/display/nr-arena-item.cpp index 5598efa32..c74e2baa0 100644 --- a/src/display/nr-arena-item.cpp +++ b/src/display/nr-arena-item.cpp @@ -735,14 +735,14 @@ nr_arena_item_append_child (NRArenaItem *parent, NRArenaItem *child) } void -nr_arena_item_set_transform (NRArenaItem *item, Geom::Matrix const &transform) +nr_arena_item_set_transform (NRArenaItem *item, Geom::Affine const &transform) { - Geom::Matrix const t (transform); + Geom::Affine const t (transform); nr_arena_item_set_transform (item, &t); } void -nr_arena_item_set_transform (NRArenaItem *item, Geom::Matrix const *transform) +nr_arena_item_set_transform (NRArenaItem *item, Geom::Affine const *transform) { nr_return_if_fail (item != NULL); nr_return_if_fail (NR_IS_ARENA_ITEM (item)); @@ -750,8 +750,8 @@ nr_arena_item_set_transform (NRArenaItem *item, Geom::Matrix const *transform) if (!transform && !item->transform) return; - const Geom::Matrix *md = (item->transform) ? item->transform : &GEOM_MATRIX_IDENTITY; - const Geom::Matrix *ms = (transform) ? transform : &GEOM_MATRIX_IDENTITY; + const Geom::Affine *md = (item->transform) ? item->transform : &GEOM_MATRIX_IDENTITY; + const Geom::Affine *ms = (transform) ? transform : &GEOM_MATRIX_IDENTITY; if (!Geom::matrix_equalp(*md, *ms, NR_EPSILON)) { nr_arena_item_request_render (item); @@ -760,7 +760,7 @@ nr_arena_item_set_transform (NRArenaItem *item, Geom::Matrix const *transform) item->transform = NULL; } else { if (!item->transform) - item->transform = new (GC::ATOMIC) Geom::Matrix (); + item->transform = new (GC::ATOMIC) Geom::Affine (); *item->transform = *transform; } nr_arena_item_request_update (item, NR_ARENA_ITEM_STATE_ALL, TRUE); diff --git a/src/display/nr-arena-item.h b/src/display/nr-arena-item.h index d1b157775..ff9965b85 100644 --- a/src/display/nr-arena-item.h +++ b/src/display/nr-arena-item.h @@ -52,7 +52,7 @@ #define NR_ARENA_ITEM_RENDER_NO_CACHE (1 << 0) -#include <2geom/matrix.h> +#include <2geom/affine.h> #include #include #include @@ -64,7 +64,7 @@ struct NRGC { NRGC(NRGC const *p) : parent(p) {} NRGC const *parent; - Geom::Matrix transform; + Geom::Affine transform; }; struct NRArenaItem : public NRObject { @@ -95,7 +95,7 @@ struct NRArenaItem : public NRObject { * specified in SVG standard. Required by filters. */ Geom::OptRect item_bbox; /* Our affine */ - Geom::Matrix *transform; + Geom::Affine *transform; /* Clip item */ NRArenaItem *clip; /* Mask item */ @@ -109,7 +109,7 @@ struct NRArenaItem : public NRObject { void *data; /* Current Transformation Matrix */ - Geom::Matrix ctm; + Geom::Affine ctm; /* These hold background buffer state for filter rendering */ NRPixBlock *background_pb; @@ -171,8 +171,8 @@ NRArenaItem *nr_arena_item_unparent (NRArenaItem *item); void nr_arena_item_append_child (NRArenaItem *parent, NRArenaItem *child); -void nr_arena_item_set_transform(NRArenaItem *item, Geom::Matrix const &transform); -void nr_arena_item_set_transform(NRArenaItem *item, Geom::Matrix const *transform); +void nr_arena_item_set_transform(NRArenaItem *item, Geom::Affine const &transform); +void nr_arena_item_set_transform(NRArenaItem *item, Geom::Affine const *transform); void nr_arena_item_set_opacity (NRArenaItem *item, double opacity); void nr_arena_item_set_sensitive (NRArenaItem *item, unsigned int sensitive); void nr_arena_item_set_visible (NRArenaItem *item, unsigned int visible); diff --git a/src/display/nr-arena-shape.cpp b/src/display/nr-arena-shape.cpp index 6f38fd97d..1f516c066 100644 --- a/src/display/nr-arena-shape.cpp +++ b/src/display/nr-arena-shape.cpp @@ -401,8 +401,8 @@ nr_arena_shape_update(NRArenaItem *item, NRRectL *area, NRGC *gc, guint state, g return NR_ARENA_ITEM_STATE_ALL; } -int matrix_is_isometry(Geom::Matrix p) { - Geom::Matrix tp; +int matrix_is_isometry(Geom::Affine p) { + Geom::Affine tp; // transposition tp[0]=p[0]; tp[1]=p[2]; @@ -410,7 +410,7 @@ int matrix_is_isometry(Geom::Matrix p) { tp[3]=p[3]; for (int i = 4; i < 6; i++) // shut valgrind up :) tp[i] = p[i] = 0; - Geom::Matrix isom = tp*p; // A^T * A = adjunct? + Geom::Affine isom = tp*p; // A^T * A = adjunct? // Is the adjunct nearly an identity function? if (isom.isTranslation(0.01)) { // the transformation is an isometry -> no need to recompute @@ -453,7 +453,7 @@ nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, NRRectL *area, bool fo if ((shape->_fill.paint.type() != NRArenaShape::Paint::NONE || force_shape) && has_inner_area(shape->curve->get_pathvector()) ) { - Geom::Matrix cached_to_new = Geom::identity(); + Geom::Affine cached_to_new = Geom::identity(); int isometry = 0; if ( shape->cached_fill ) { if (shape->cached_fctm == gc->transform) { @@ -472,7 +472,7 @@ nr_arena_shape_update_fill(NRArenaShape *shape, NRGC *gc, NRRectL *area, bool fo Path* thePath=new Path; Shape* theShape=new Shape; { - Geom::Matrix tempMat(gc->transform); + Geom::Affine tempMat(gc->transform); thePath->LoadPathVector(shape->curve->get_pathvector(), tempMat, true); } @@ -562,7 +562,7 @@ nr_arena_shape_update_stroke(NRArenaShape *shape,NRGC* gc, NRRectL *area) width = style_width; } - Geom::Matrix cached_to_new = Geom::identity(); + Geom::Affine cached_to_new = Geom::identity(); int isometry = 0; if ( shape->cached_stroke ) { @@ -586,7 +586,7 @@ nr_arena_shape_update_stroke(NRArenaShape *shape,NRGC* gc, NRRectL *area) Path* thePath = new Path; Shape* theShape = new Shape; { - Geom::Matrix tempMat( gc->transform ); + Geom::Affine tempMat( gc->transform ); thePath->LoadPathVector(shape->curve->get_pathvector(), tempMat, true); } diff --git a/src/display/nr-arena-shape.h b/src/display/nr-arena-shape.h index d484615a9..e00993901 100644 --- a/src/display/nr-arena-shape.h +++ b/src/display/nr-arena-shape.h @@ -112,7 +112,7 @@ struct NRArenaShape : public NRArenaItem { SPStyle *style; NRRect paintbox; /* State data */ - Geom::Matrix ctm; + Geom::Affine ctm; SPPainter *fill_painter; SPPainter *stroke_painter; @@ -135,8 +135,8 @@ struct NRArenaShape : public NRArenaItem { // polygon to get the *_shp polygon. Otherwise, recompute so this // works fine for translation and rotation, but not scaling and // skewing - Geom::Matrix cached_fctm; - Geom::Matrix cached_sctm; + Geom::Affine cached_fctm; + Geom::Affine cached_sctm; NRRectL cached_farea; NRRectL cached_sarea; bool cached_fpartialy; diff --git a/src/display/nr-filter-colormatrix.cpp b/src/display/nr-filter-colormatrix.cpp index 7d0792325..54d5dfd69 100644 --- a/src/display/nr-filter-colormatrix.cpp +++ b/src/display/nr-filter-colormatrix.cpp @@ -195,7 +195,7 @@ int FilterColorMatrix::render(FilterSlot &slot, FilterUnits const &/*units*/) { return 0; } -void FilterColorMatrix::area_enlarge(NRRectL &/*area*/, Geom::Matrix const &/*trans*/) +void FilterColorMatrix::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*trans*/) { } diff --git a/src/display/nr-filter-colormatrix.h b/src/display/nr-filter-colormatrix.h index 8507f8a63..7a2395f5d 100644 --- a/src/display/nr-filter-colormatrix.h +++ b/src/display/nr-filter-colormatrix.h @@ -35,7 +35,7 @@ public: virtual ~FilterColorMatrix(); virtual int render(FilterSlot &slot, FilterUnits const &units); - virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans); + virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans); virtual void set_type(FilterColorMatrixType type); virtual void set_value(gdouble value); virtual void set_values(std::vector &values); diff --git a/src/display/nr-filter-component-transfer.cpp b/src/display/nr-filter-component-transfer.cpp index 2b6f0c722..3fe8cbf4a 100644 --- a/src/display/nr-filter-component-transfer.cpp +++ b/src/display/nr-filter-component-transfer.cpp @@ -198,7 +198,7 @@ int FilterComponentTransfer::render(FilterSlot &slot, FilterUnits const &/*units return 0; } -void FilterComponentTransfer::area_enlarge(NRRectL &/*area*/, Geom::Matrix const &/*trans*/) +void FilterComponentTransfer::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*trans*/) { } diff --git a/src/display/nr-filter-component-transfer.h b/src/display/nr-filter-component-transfer.h index 2fda2692a..65b4d4079 100644 --- a/src/display/nr-filter-component-transfer.h +++ b/src/display/nr-filter-component-transfer.h @@ -36,7 +36,7 @@ public: virtual ~FilterComponentTransfer(); virtual int render(FilterSlot &slot, FilterUnits const &units); - virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans); + virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans); FilterComponentTransferType type[4]; std::vector tableValues[4]; diff --git a/src/display/nr-filter-convolve-matrix.cpp b/src/display/nr-filter-convolve-matrix.cpp index 4b88aa929..f5cc7175a 100644 --- a/src/display/nr-filter-convolve-matrix.cpp +++ b/src/display/nr-filter-convolve-matrix.cpp @@ -246,7 +246,7 @@ void FilterConvolveMatrix::set_preserveAlpha(bool pa){ preserveAlpha = pa; } -void FilterConvolveMatrix::area_enlarge(NRRectL &area, Geom::Matrix const &/*trans*/) +void FilterConvolveMatrix::area_enlarge(NRRectL &area, Geom::Affine const &/*trans*/) { //Seems to me that since this filter's operation is resolution dependent, // some spurious pixels may still appear at the borders when low zooming or rotating. Needs a better fix. diff --git a/src/display/nr-filter-convolve-matrix.h b/src/display/nr-filter-convolve-matrix.h index 846ef5685..50d97f1a0 100644 --- a/src/display/nr-filter-convolve-matrix.h +++ b/src/display/nr-filter-convolve-matrix.h @@ -35,7 +35,7 @@ public: virtual ~FilterConvolveMatrix(); virtual int render(FilterSlot &slot, FilterUnits const &units); - virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans); + virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans); virtual FilterTraits get_input_traits(); void set_targetY(int coord); diff --git a/src/display/nr-filter-diffuselighting.cpp b/src/display/nr-filter-diffuselighting.cpp index 7443039f6..8e764f6d4 100644 --- a/src/display/nr-filter-diffuselighting.cpp +++ b/src/display/nr-filter-diffuselighting.cpp @@ -62,7 +62,7 @@ int FilterDiffuseLighting::render(FilterSlot &slot, FilterUnits const &units) { int dx = 1; //TODO setup int dy = 1; //TODO setup //surface scale - Geom::Matrix trans = units.get_matrix_primitiveunits2pb(); + Geom::Affine trans = units.get_matrix_primitiveunits2pb(); gdouble ss = surfaceScale * trans[0]; gdouble kd = diffuseConstant; //diffuse lighting constant @@ -168,7 +168,7 @@ int FilterDiffuseLighting::render(FilterSlot &slot, FilterUnits const &units) { return 0; } -void FilterDiffuseLighting::area_enlarge(NRRectL &area, Geom::Matrix const &trans) +void FilterDiffuseLighting::area_enlarge(NRRectL &area, Geom::Affine const &trans) { // TODO: support kernelUnitLength double scalex = std::fabs(trans[0]) + std::fabs(trans[1]); diff --git a/src/display/nr-filter-diffuselighting.h b/src/display/nr-filter-diffuselighting.h index 5141d0b61..8dc7a1818 100644 --- a/src/display/nr-filter-diffuselighting.h +++ b/src/display/nr-filter-diffuselighting.h @@ -42,7 +42,7 @@ public: static FilterPrimitive *create(); virtual ~FilterDiffuseLighting(); virtual int render(FilterSlot &slot, FilterUnits const &units); - virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans); + virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans); virtual FilterTraits get_input_traits(); private: diff --git a/src/display/nr-filter-displacement-map.cpp b/src/display/nr-filter-displacement-map.cpp index 863927f4b..d71a691ef 100644 --- a/src/display/nr-filter-displacement-map.cpp +++ b/src/display/nr-filter-displacement-map.cpp @@ -190,7 +190,7 @@ int FilterDisplacementMap::render(FilterSlot &slot, FilterUnits const &units) { bool map_premultiplied = (map->mode == NR_PIXBLOCK_MODE_R8G8B8A8P); bool data_premultiplied = (out->mode == NR_PIXBLOCK_MODE_R8G8B8A8P); - Geom::Matrix trans = units.get_matrix_primitiveunits2pb(); + Geom::Affine trans = units.get_matrix_primitiveunits2pb(); double scalex = scale * trans.expansionX(); double scaley = scale * trans.expansionY(); @@ -237,7 +237,7 @@ void FilterDisplacementMap::set_channel_selector(int s, FilterDisplacementMapCha if (s == 1) Ychannel = channel; } -void FilterDisplacementMap::area_enlarge(NRRectL &area, Geom::Matrix const &trans) +void FilterDisplacementMap::area_enlarge(NRRectL &area, Geom::Affine const &trans) { //I assume scale is in user coordinates (?!?) //FIXME: trans should be multiplied by some primitiveunits2user, shouldn't it? diff --git a/src/display/nr-filter-displacement-map.h b/src/display/nr-filter-displacement-map.h index e76e47fec..1dad1873a 100644 --- a/src/display/nr-filter-displacement-map.h +++ b/src/display/nr-filter-displacement-map.h @@ -32,7 +32,7 @@ public: virtual void set_scale(double s); virtual void set_channel_selector(int s, FilterDisplacementMapChannelSelector channel); virtual int render(FilterSlot &slot, FilterUnits const &units); - virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans); + virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans); virtual FilterTraits get_input_traits(); private: diff --git a/src/display/nr-filter-flood.cpp b/src/display/nr-filter-flood.cpp index 3f4951dd6..ca073cfd8 100644 --- a/src/display/nr-filter-flood.cpp +++ b/src/display/nr-filter-flood.cpp @@ -87,7 +87,7 @@ void FilterFlood::set_icc(SVGICCColor *icc_color) { icc = icc_color; } -void FilterFlood::area_enlarge(NRRectL &/*area*/, Geom::Matrix const &/*trans*/) +void FilterFlood::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*trans*/) { } diff --git a/src/display/nr-filter-flood.h b/src/display/nr-filter-flood.h index b11fa117d..ebb7d4506 100644 --- a/src/display/nr-filter-flood.h +++ b/src/display/nr-filter-flood.h @@ -30,7 +30,7 @@ public: virtual void set_color(guint32 c); virtual void set_icc(SVGICCColor *icc_color); virtual int render(FilterSlot &slot, FilterUnits const &units); - virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans); + virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans); private: double opacity; guint32 color; diff --git a/src/display/nr-filter-gaussian.cpp b/src/display/nr-filter-gaussian.cpp index 5cfaab54d..3f7bea35d 100644 --- a/src/display/nr-filter-gaussian.cpp +++ b/src/display/nr-filter-gaussian.cpp @@ -33,7 +33,7 @@ #include "display/nr-filter-units.h" #include "libnr/nr-blit.h" #include "libnr/nr-pixblock.h" -#include <2geom/matrix.h> +#include <2geom/affine.h> #include "util/fixed_point.h" #include "preferences.h" @@ -582,7 +582,7 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units) nr_blit_pixblock_pixblock(in, original_in); } - Geom::Matrix trans = units.get_matrix_primitiveunits2pb(); + Geom::Affine trans = units.get_matrix_primitiveunits2pb(); // Some common constants int const width_org = in->area.x1-in->area.x0, height_org = in->area.y1-in->area.y0; @@ -847,7 +847,7 @@ int FilterGaussian::render(FilterSlot &slot, FilterUnits const &units) return 0; } -void FilterGaussian::area_enlarge(NRRectL &area, Geom::Matrix const &trans) +void FilterGaussian::area_enlarge(NRRectL &area, Geom::Affine const &trans) { int area_x = _effect_area_scr(_deviation_x * trans.expansionX()); int area_y = _effect_area_scr(_deviation_y * trans.expansionY()); diff --git a/src/display/nr-filter-gaussian.h b/src/display/nr-filter-gaussian.h index 1dcb07d67..87d74ac63 100644 --- a/src/display/nr-filter-gaussian.h +++ b/src/display/nr-filter-gaussian.h @@ -39,7 +39,7 @@ public: virtual ~FilterGaussian(); virtual int render(FilterSlot &slot, FilterUnits const &units); - virtual void area_enlarge(NRRectL &area, Geom::Matrix const &m); + virtual void area_enlarge(NRRectL &area, Geom::Affine const &m); virtual FilterTraits get_input_traits(); /** diff --git a/src/display/nr-filter-image.cpp b/src/display/nr-filter-image.cpp index 9a39168c2..cc6dc18fa 100644 --- a/src/display/nr-filter-image.cpp +++ b/src/display/nr-filter-image.cpp @@ -85,7 +85,7 @@ int FilterImage::render(FilterSlot &slot, FilterUnits const &units) { NRGC gc(NULL); /* Update to renderable state */ double sf = 1.0; - Geom::Matrix t(Geom::Scale(sf, sf)); + Geom::Affine t(Geom::Scale(sf, sf)); nr_arena_item_set_transform(ai, &t); gc.transform.setIdentity(); nr_arena_item_invoke_update( ai, NULL, &gc, @@ -166,7 +166,7 @@ int FilterImage::render(FilterSlot &slot, FilterUnits const &units) { // Get the object bounding box. Image is placed with respect to box. // Array values: 0: width; 3: height; 4: -x; 5: -y. - Geom::Matrix object_bbox = units.get_matrix_user2filterunits().inverse(); + Geom::Affine object_bbox = units.get_matrix_user2filterunits().inverse(); // feImage is suppose to use the same parameters as a normal SVG image. // If a width or height is set to zero, the image is not suppose to be displayed. @@ -181,8 +181,8 @@ int FilterImage::render(FilterSlot &slot, FilterUnits const &units) { int coordx,coordy; unsigned char *out_data = NR_PIXBLOCK_PX(out); - Geom::Matrix unit_trans = units.get_matrix_primitiveunits2pb().inverse(); - Geom::Matrix d2s = Geom::Translate(x0, y0) * unit_trans * Geom::Translate(object_bbox[4]-feImageX, object_bbox[5]-feImageY) * Geom::Scale(scaleX, scaleY); + Geom::Affine unit_trans = units.get_matrix_primitiveunits2pb().inverse(); + Geom::Affine d2s = Geom::Translate(x0, y0) * unit_trans * Geom::Translate(object_bbox[4]-feImageX, object_bbox[5]-feImageY) * Geom::Scale(scaleX, scaleY); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); int nr_arena_image_x_sample = prefs->getInt("/options/bitmapoversample/value", 1); diff --git a/src/display/nr-filter-morphology.cpp b/src/display/nr-filter-morphology.cpp index 6902bacc6..ceb2a2b9d 100644 --- a/src/display/nr-filter-morphology.cpp +++ b/src/display/nr-filter-morphology.cpp @@ -51,7 +51,7 @@ int FilterMorphology::render(FilterSlot &slot, FilterUnits const &units) { free_in_on_exit = true; } - Geom::Matrix p2pb = units.get_matrix_primitiveunits2pb(); + Geom::Affine p2pb = units.get_matrix_primitiveunits2pb(); int const xradius = (int)round(this->xradius * p2pb.expansionX()); int const yradius = (int)round(this->yradius * p2pb.expansionY()); @@ -112,7 +112,7 @@ int FilterMorphology::render(FilterSlot &slot, FilterUnits const &units) { return 0; } -void FilterMorphology::area_enlarge(NRRectL &area, Geom::Matrix const &trans) +void FilterMorphology::area_enlarge(NRRectL &area, Geom::Affine const &trans) { int const enlarge_x = (int)std::ceil(this->xradius * (std::fabs(trans[0]) + std::fabs(trans[1]))); int const enlarge_y = (int)std::ceil(this->yradius * (std::fabs(trans[2]) + std::fabs(trans[3]))); diff --git a/src/display/nr-filter-morphology.h b/src/display/nr-filter-morphology.h index 867a6a391..c8d8b2f50 100644 --- a/src/display/nr-filter-morphology.h +++ b/src/display/nr-filter-morphology.h @@ -32,7 +32,7 @@ public: virtual ~FilterMorphology(); virtual int render(FilterSlot &slot, FilterUnits const &units); - virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans); + virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans); virtual FilterTraits get_input_traits(); void set_operator(FilterMorphologyOperator &o); void set_xradius(double x); diff --git a/src/display/nr-filter-offset.cpp b/src/display/nr-filter-offset.cpp index bee73c998..7c924b7b7 100644 --- a/src/display/nr-filter-offset.cpp +++ b/src/display/nr-filter-offset.cpp @@ -43,7 +43,7 @@ int FilterOffset::render(FilterSlot &slot, FilterUnits const &units) { NRPixBlock *out = new NRPixBlock; - Geom::Matrix trans = units.get_matrix_primitiveunits2pb(); + Geom::Affine trans = units.get_matrix_primitiveunits2pb(); Geom::Point offset(dx, dy); offset *= trans; offset[X] -= trans[4]; @@ -74,7 +74,7 @@ void FilterOffset::set_dy(double amount) { dy = amount; } -void FilterOffset::area_enlarge(NRRectL &area, Geom::Matrix const &trans) +void FilterOffset::area_enlarge(NRRectL &area, Geom::Affine const &trans) { Geom::Point offset(dx, dy); offset *= trans; diff --git a/src/display/nr-filter-offset.h b/src/display/nr-filter-offset.h index 7c2b33742..a78450e17 100644 --- a/src/display/nr-filter-offset.h +++ b/src/display/nr-filter-offset.h @@ -27,7 +27,7 @@ public: virtual ~FilterOffset(); virtual int render(FilterSlot &slot, FilterUnits const &units); - virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans); + virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans); void set_dx(double amount); void set_dy(double amount); diff --git a/src/display/nr-filter-primitive.cpp b/src/display/nr-filter-primitive.cpp index f79af8bd8..f53ff4a7f 100644 --- a/src/display/nr-filter-primitive.cpp +++ b/src/display/nr-filter-primitive.cpp @@ -37,7 +37,7 @@ FilterPrimitive::~FilterPrimitive() // Nothing to do here } -void FilterPrimitive::area_enlarge(NRRectL &/*area*/, Geom::Matrix const &/*m*/) +void FilterPrimitive::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*m*/) { // This doesn't need to do anything by default } diff --git a/src/display/nr-filter-primitive.h b/src/display/nr-filter-primitive.h index 87fe21f31..7639a9d1d 100644 --- a/src/display/nr-filter-primitive.h +++ b/src/display/nr-filter-primitive.h @@ -44,7 +44,7 @@ public: virtual ~FilterPrimitive(); virtual int render(FilterSlot &slot, FilterUnits const &units) = 0; - virtual void area_enlarge(NRRectL &area, Geom::Matrix const &m); + virtual void area_enlarge(NRRectL &area, Geom::Affine const &m); /** * Sets the input slot number 'slot' to be used as input in rendering diff --git a/src/display/nr-filter-slot.cpp b/src/display/nr-filter-slot.cpp index 96e2a92e9..b019b194f 100644 --- a/src/display/nr-filter-slot.cpp +++ b/src/display/nr-filter-slot.cpp @@ -151,7 +151,7 @@ NRPixBlock *FilterSlot::get(int slot_nr) void FilterSlot::get_final(int slot_nr, NRPixBlock *result) { NRPixBlock *final_usr = get(slot_nr); - Geom::Matrix trans = units.get_matrix_pb2display(); + Geom::Affine trans = units.get_matrix_pb2display(); int size = (result->area.x1 - result->area.x0) * (result->area.y1 - result->area.y0) @@ -188,7 +188,7 @@ void FilterSlot::set(int slot_nr, NRPixBlock *pb, bool takeOwnership) assert(slot_nr == NR_FILTER_SLOT_NOT_SET ||_slots[index].number == slot_nr); if (slot_nr == NR_FILTER_SOURCEGRAPHIC || slot_nr == NR_FILTER_BACKGROUNDIMAGE) { - Geom::Matrix trans = units.get_matrix_display2pb(); + Geom::Affine trans = units.get_matrix_display2pb(); if (fabs(trans[1]) > 1e-6 || fabs(trans[2]) > 1e-6) { NRPixBlock *trans_pb = new NRPixBlock; int x0 = pb->area.x0; diff --git a/src/display/nr-filter-specularlighting.cpp b/src/display/nr-filter-specularlighting.cpp index 354695dd7..8ecee24e6 100644 --- a/src/display/nr-filter-specularlighting.cpp +++ b/src/display/nr-filter-specularlighting.cpp @@ -80,7 +80,7 @@ int FilterSpecularLighting::render(FilterSlot &slot, FilterUnits const &units) { int dx = 1; //TODO setup int dy = 1; //TODO setup //surface scale - Geom::Matrix trans = units.get_matrix_primitiveunits2pb(); + Geom::Affine trans = units.get_matrix_primitiveunits2pb(); gdouble ss = surfaceScale * trans[0]; gdouble ks = specularConstant; //diffuse lighting constant NR::Fvector L, N, LC, H; @@ -188,7 +188,7 @@ int FilterSpecularLighting::render(FilterSlot &slot, FilterUnits const &units) { return 0; } -void FilterSpecularLighting::area_enlarge(NRRectL &area, Geom::Matrix const &trans) +void FilterSpecularLighting::area_enlarge(NRRectL &area, Geom::Affine const &trans) { // TODO: support kernelUnitLength double scalex = std::fabs(trans[0]) + std::fabs(trans[1]); diff --git a/src/display/nr-filter-specularlighting.h b/src/display/nr-filter-specularlighting.h index 5d31b09f1..a5d29588a 100644 --- a/src/display/nr-filter-specularlighting.h +++ b/src/display/nr-filter-specularlighting.h @@ -43,7 +43,7 @@ public: static FilterPrimitive *create(); virtual ~FilterSpecularLighting(); virtual int render(FilterSlot &slot, FilterUnits const &units); - virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans); + virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans); virtual FilterTraits get_input_traits(); private: diff --git a/src/display/nr-filter-tile.cpp b/src/display/nr-filter-tile.cpp index 8eca6b18f..b1ca5d191 100644 --- a/src/display/nr-filter-tile.cpp +++ b/src/display/nr-filter-tile.cpp @@ -53,7 +53,7 @@ int FilterTile::render(FilterSlot &slot, FilterUnits const &/*units*/) { return 0; } -void FilterTile::area_enlarge(NRRectL &/*area*/, Geom::Matrix const &/*trans*/) +void FilterTile::area_enlarge(NRRectL &/*area*/, Geom::Affine const &/*trans*/) { } diff --git a/src/display/nr-filter-tile.h b/src/display/nr-filter-tile.h index 505fb9948..4a2a0dddc 100644 --- a/src/display/nr-filter-tile.h +++ b/src/display/nr-filter-tile.h @@ -27,7 +27,7 @@ public: virtual ~FilterTile(); virtual int render(FilterSlot &slot, FilterUnits const &units); - virtual void area_enlarge(NRRectL &area, Geom::Matrix const &trans); + virtual void area_enlarge(NRRectL &area, Geom::Affine const &trans); virtual FilterTraits get_input_traits(); }; diff --git a/src/display/nr-filter-turbulence.cpp b/src/display/nr-filter-turbulence.cpp index dde92c0a5..a91de0460 100644 --- a/src/display/nr-filter-turbulence.cpp +++ b/src/display/nr-filter-turbulence.cpp @@ -87,7 +87,7 @@ void FilterTurbulence::render_area(NRPixBlock *pix, NR::IRect &full_area, Filter const int bbox_x1 = full_area.max()[NR::X]; const int bbox_y1 = full_area.max()[NR::Y]; - Geom::Matrix unit_trans = units.get_matrix_primitiveunits2pb().inverse(); + Geom::Affine unit_trans = units.get_matrix_primitiveunits2pb().inverse(); double point[2]; diff --git a/src/display/nr-filter-units.cpp b/src/display/nr-filter-units.cpp index 4cf165800..b1c475c41 100644 --- a/src/display/nr-filter-units.cpp +++ b/src/display/nr-filter-units.cpp @@ -35,7 +35,7 @@ FilterUnits::FilterUnits(SPFilterUnits const filterUnits, SPFilterUnits const pr paraller_axis(false), automatic_resolution(true) {} -void FilterUnits::set_ctm(Geom::Matrix const &ctm) { +void FilterUnits::set_ctm(Geom::Affine const &ctm) { this->ctm = ctm; } @@ -63,12 +63,12 @@ void FilterUnits::set_automatic_resolution(bool const automatic) { automatic_resolution = automatic; } -Geom::Matrix FilterUnits::get_matrix_user2pb() const { +Geom::Affine FilterUnits::get_matrix_user2pb() const { g_assert(resolution_x > 0); g_assert(resolution_y > 0); g_assert(filter_area); - Geom::Matrix u2pb = ctm; + Geom::Affine u2pb = ctm; if (paraller_axis || !automatic_resolution) { u2pb[0] = resolution_x / (filter_area->max()[X] - filter_area->min()[X]); @@ -82,9 +82,9 @@ Geom::Matrix FilterUnits::get_matrix_user2pb() const { return u2pb; } -Geom::Matrix FilterUnits::get_matrix_units2pb(SPFilterUnits units) const { +Geom::Affine FilterUnits::get_matrix_units2pb(SPFilterUnits units) const { if ( item_bbox && (units == SP_FILTER_UNITS_OBJECTBOUNDINGBOX) ) { - Geom::Matrix u2pb = get_matrix_user2pb(); + Geom::Affine u2pb = get_matrix_user2pb(); Geom::Point origo(item_bbox->min()); origo *= u2pb; Geom::Point i_end(item_bbox->max()[X], item_bbox->min()[Y]); @@ -106,31 +106,31 @@ Geom::Matrix FilterUnits::get_matrix_units2pb(SPFilterUnits units) const { return get_matrix_user2pb(); } else { g_warning("Error in Inkscape::Filters::FilterUnits::get_matrix_units2pb: unrecognized unit type (%d)", units); - return Geom::Matrix(); + return Geom::Affine(); } } -Geom::Matrix FilterUnits::get_matrix_filterunits2pb() const { +Geom::Affine FilterUnits::get_matrix_filterunits2pb() const { return get_matrix_units2pb(filterUnits); } -Geom::Matrix FilterUnits::get_matrix_primitiveunits2pb() const { +Geom::Affine FilterUnits::get_matrix_primitiveunits2pb() const { return get_matrix_units2pb(primitiveUnits); } -Geom::Matrix FilterUnits::get_matrix_display2pb() const { - Geom::Matrix d2pb = ctm.inverse(); +Geom::Affine FilterUnits::get_matrix_display2pb() const { + Geom::Affine d2pb = ctm.inverse(); d2pb *= get_matrix_user2pb(); return d2pb; } -Geom::Matrix FilterUnits::get_matrix_pb2display() const { - Geom::Matrix pb2d = get_matrix_user2pb().inverse(); +Geom::Affine FilterUnits::get_matrix_pb2display() const { + Geom::Affine pb2d = get_matrix_user2pb().inverse(); pb2d *= ctm; return pb2d; } -Geom::Matrix FilterUnits::get_matrix_user2units(SPFilterUnits units) const { +Geom::Affine FilterUnits::get_matrix_user2units(SPFilterUnits units) const { if (item_bbox && units == SP_FILTER_UNITS_OBJECTBOUNDINGBOX) { /* No need to worry about rotations: bounding box coordinates * always have base vectors paraller with userspace coordinates */ @@ -139,22 +139,22 @@ Geom::Matrix FilterUnits::get_matrix_user2units(SPFilterUnits units) const { double scale_x = 1.0 / (max[X] - min[X]); double scale_y = 1.0 / (max[Y] - min[Y]); //return Geom::Translate(min) * Geom::Scale(scale_x,scale_y); ? - return Geom::Matrix(scale_x, 0, + return Geom::Affine(scale_x, 0, 0, scale_y, min[X] * scale_x, min[Y] * scale_y); } else if (units == SP_FILTER_UNITS_USERSPACEONUSE) { return Geom::identity(); } else { g_warning("Error in Inkscape::Filters::FilterUnits::get_matrix_user2units: unrecognized unit type (%d)", units); - return Geom::Matrix(); + return Geom::Affine(); } } -Geom::Matrix FilterUnits::get_matrix_user2filterunits() const { +Geom::Affine FilterUnits::get_matrix_user2filterunits() const { return get_matrix_user2units(filterUnits); } -Geom::Matrix FilterUnits::get_matrix_user2primitiveunits() const { +Geom::Affine FilterUnits::get_matrix_user2primitiveunits() const { return get_matrix_user2units(primitiveUnits); } @@ -162,7 +162,7 @@ NR::IRect 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::Matrix u2pb = get_matrix_user2pb(); + Geom::Affine u2pb = get_matrix_user2pb(); for (int i = 0 ; i < 4 ; i++) { Geom::Point p = filter_area->corner(i); diff --git a/src/display/nr-filter-units.h b/src/display/nr-filter-units.h index 2a64b1afc..9a0d8ea83 100644 --- a/src/display/nr-filter-units.h +++ b/src/display/nr-filter-units.h @@ -16,7 +16,7 @@ #include "libnr/nr-matrix.h" #include "libnr/nr-rect.h" #include "libnr/nr-rect-l.h" -#include <2geom/matrix.h> +#include <2geom/affine.h> #include <2geom/rect.h> namespace Inkscape { @@ -31,7 +31,7 @@ public: * Sets the current transformation matrix, i.e. transformation matrix * from object's user coordinates to screen coordinates */ - void set_ctm(Geom::Matrix const &ctm); + void set_ctm(Geom::Affine const &ctm); /** * Sets the resolution, the filter should be rendered with. @@ -64,39 +64,39 @@ public: /** * Gets the user coordinates to pixblock coordinates transformation matrix. */ - Geom::Matrix get_matrix_user2pb() const; + Geom::Affine get_matrix_user2pb() const; /** * Gets the filterUnits to pixblock coordinates transformation matrix. */ - Geom::Matrix get_matrix_filterunits2pb() const; + Geom::Affine get_matrix_filterunits2pb() const; /** * Gets the primitiveUnits to pixblock coordinates transformation matrix. */ - Geom::Matrix get_matrix_primitiveunits2pb() const; + Geom::Affine get_matrix_primitiveunits2pb() const; /** * Gets the display coordinates to pixblock coordinates transformation * matrix. */ - Geom::Matrix get_matrix_display2pb() const; + Geom::Affine get_matrix_display2pb() const; /** * Gets the pixblock coordinates to display coordinates transformation * matrix */ - Geom::Matrix get_matrix_pb2display() const; + Geom::Affine get_matrix_pb2display() const; /** * Gets the user coordinates to filterUnits transformation matrix. */ - Geom::Matrix get_matrix_user2filterunits() const; + Geom::Affine get_matrix_user2filterunits() const; /** * Gets the user coordinates to primitiveUnits transformation matrix. */ - Geom::Matrix get_matrix_user2primitiveunits() const; + Geom::Affine get_matrix_user2primitiveunits() const; /** * Returns the filter area in pixblock coordinates. @@ -108,14 +108,14 @@ public: FilterUnits& operator=(FilterUnits const &other); private: - Geom::Matrix get_matrix_units2pb(SPFilterUnits units) const; - Geom::Matrix get_matrix_user2units(SPFilterUnits units) const; + Geom::Affine get_matrix_units2pb(SPFilterUnits units) const; + Geom::Affine get_matrix_user2units(SPFilterUnits units) const; SPFilterUnits filterUnits, primitiveUnits; double resolution_x, resolution_y; bool paraller_axis; bool automatic_resolution; - Geom::Matrix ctm; + Geom::Affine ctm; Geom::OptRect item_bbox; Geom::OptRect filter_area; diff --git a/src/display/nr-filter.cpp b/src/display/nr-filter.cpp index 5ff9d2da5..ea9b4f7da 100644 --- a/src/display/nr-filter.cpp +++ b/src/display/nr-filter.cpp @@ -43,7 +43,7 @@ #include "display/nr-arena-item.h" #include "libnr/nr-pixblock.h" #include "libnr/nr-blit.h" -#include <2geom/matrix.h> +#include <2geom/affine.h> #include <2geom/rect.h> #include "svg/svg-length.h" #include "sp-filter-units.h" @@ -139,7 +139,7 @@ int Filter::render(NRArenaItem const *item, NRPixBlock *pb) FilterQuality const filterquality = (FilterQuality)item->arena->filterquality; int const blurquality = item->arena->blurquality; - Geom::Matrix trans = item->ctm; + Geom::Affine trans = item->ctm; FilterSlot slot(_slot_count, item); slot.set_quality(filterquality); slot.set_blurquality(blurquality); @@ -508,7 +508,7 @@ int Filter::_resolution_limit(FilterQuality const quality) const { } std::pair Filter::_filter_resolution( - Geom::Rect const &area, Geom::Matrix const &trans, + Geom::Rect const &area, Geom::Affine const &trans, FilterQuality const filterquality) const { std::pair resolution; diff --git a/src/display/nr-filter.h b/src/display/nr-filter.h index a7cf932b1..23acea99f 100644 --- a/src/display/nr-filter.h +++ b/src/display/nr-filter.h @@ -201,7 +201,7 @@ private: void _common_init(); int _resolution_limit(FilterQuality const quality) const; std::pair _filter_resolution(Geom::Rect const &area, - Geom::Matrix const &trans, + Geom::Affine const &trans, FilterQuality const q) const; }; diff --git a/src/display/nr-light.cpp b/src/display/nr-light.cpp index a8a31734d..74d83da70 100644 --- a/src/display/nr-light.cpp +++ b/src/display/nr-light.cpp @@ -43,7 +43,7 @@ void DistantLight::light_components(NR::Fvector &lc) { lc[LIGHT_BLUE] = NR_RGBA32_B(color); } -PointLight::PointLight(SPFePointLight *light, guint32 lighting_color, const Geom::Matrix &trans) { +PointLight::PointLight(SPFePointLight *light, guint32 lighting_color, const Geom::Affine &trans) { color = lighting_color; l_x = light->x; l_y = light->y; @@ -66,7 +66,7 @@ void PointLight::light_components(NR::Fvector &lc) { lc[LIGHT_BLUE] = NR_RGBA32_B(color); } -SpotLight::SpotLight(SPFeSpotLight *light, guint32 lighting_color, const Geom::Matrix &trans) { +SpotLight::SpotLight(SPFeSpotLight *light, guint32 lighting_color, const Geom::Affine &trans) { gdouble p_x, p_y, p_z; color = lighting_color; l_x = light->x; diff --git a/src/display/nr-light.h b/src/display/nr-light.h index 65c341a7e..49130cc4e 100644 --- a/src/display/nr-light.h +++ b/src/display/nr-light.h @@ -68,7 +68,7 @@ class PointLight { * employed in the sp light object) and current coordinate (those * employed in the rendering) */ - PointLight(SPFePointLight *light, guint32 lighting_color, const Geom::Matrix &trans); + PointLight(SPFePointLight *light, guint32 lighting_color, const Geom::Affine &trans); virtual ~PointLight(); /** * Computes the light vector of the distant light at point (x,y,z). @@ -108,7 +108,7 @@ class SpotLight { * employed in the sp light object) and current coordinate (those * employed in the rendering) */ - SpotLight(SPFeSpotLight *light, guint32 lighting_color, const Geom::Matrix &trans); + SpotLight(SPFeSpotLight *light, guint32 lighting_color, const Geom::Affine &trans); virtual ~SpotLight(); /** diff --git a/src/display/nr-svgfonts.cpp b/src/display/nr-svgfonts.cpp index 2b724246a..62d52b04b 100644 --- a/src/display/nr-svgfonts.cpp +++ b/src/display/nr-svgfonts.cpp @@ -253,7 +253,7 @@ SvgFont::scaled_font_render_glyph (cairo_scaled_font_t */*scaled_font*/, // Geom::Scale s(1.0/((SPFont*) node->parent)->horiz_adv_x); Geom::Scale s(1.0/1000);//TODO: use here the units-per-em attribute? //This matrix flips the glyph vertically - Geom::Matrix m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(0)); + Geom::Affine m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(0)); //then we offset it // pathv += Geom::Point(Geom::Coord(0),Geom::Coord(-((SPFont*) node->parent)->horiz_adv_x)); pathv += Geom::Point(Geom::Coord(0),Geom::Coord(-1000));//TODO: use here the units-per-em attribute? diff --git a/src/display/pixblock-scaler.cpp b/src/display/pixblock-scaler.cpp index c9df0c833..5af5230d8 100644 --- a/src/display/pixblock-scaler.cpp +++ b/src/display/pixblock-scaler.cpp @@ -70,7 +70,7 @@ inline static void _check_index(NRPixBlock const * const pb, int const location, } static void scale_bicubic_rgba(NRPixBlock *to, NRPixBlock *from, - Geom::Matrix const &trans) + Geom::Affine const &trans) { if (NR_PIXBLOCK_BPP(from) != 4 || NR_PIXBLOCK_BPP(to) != 4) { g_warning("A non-32-bpp image passed to scale_bicubic_rgba: scaling aborted."); @@ -203,7 +203,7 @@ static void scale_bicubic_rgba(NRPixBlock *to, NRPixBlock *from, } void scale_bicubic_alpha(NRPixBlock *to, NRPixBlock *from, - Geom::Matrix const &trans) + Geom::Affine const &trans) { if (NR_PIXBLOCK_BPP(from) != 1 || NR_PIXBLOCK_BPP(to) != 1) { g_warning("A non-8-bpp image passed to scale_bicubic_alpha: scaling aborted."); @@ -275,7 +275,7 @@ void scale_bicubic_alpha(NRPixBlock *to, NRPixBlock *from, } } -void scale_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &trans) +void scale_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans) { if (NR_PIXBLOCK_BPP(to) == 4 && NR_PIXBLOCK_BPP(from) == 4) { scale_bicubic_rgba(to, from, trans); diff --git a/src/display/pixblock-scaler.h b/src/display/pixblock-scaler.h index f7cbcb0be..ff9613ab8 100644 --- a/src/display/pixblock-scaler.h +++ b/src/display/pixblock-scaler.h @@ -23,7 +23,7 @@ namespace NR { * Source pixblock is not modified in process. * Only works for 32-bpp images. */ -void scale_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &trans); +void scale_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans); } /* namespace NR */ diff --git a/src/display/pixblock-transform.cpp b/src/display/pixblock-transform.cpp index 78324434a..5d5b8a9cf 100644 --- a/src/display/pixblock-transform.cpp +++ b/src/display/pixblock-transform.cpp @@ -23,7 +23,7 @@ using std::floor; #include "libnr/nr-blit.h" #include "libnr/nr-pixblock.h" -#include <2geom/matrix.h> +#include <2geom/affine.h> namespace NR { @@ -48,7 +48,7 @@ inline void _check_index(NRPixBlock const * const pb, int const location, int co } } -void transform_nearest(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &trans) +void transform_nearest(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans) { if (NR_PIXBLOCK_BPP(from) != 4 || NR_PIXBLOCK_BPP(to) != 4) { g_warning("A non-32-bpp image passed to transform_nearest: scaling aborted."); @@ -70,7 +70,7 @@ void transform_nearest(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &tra int to_width = to->area.x1 - to->area.x0; int to_height = to->area.y1 - to->area.y0; - Geom::Matrix itrans = trans.inverse(); + Geom::Affine itrans = trans.inverse(); // Loop through every pixel of destination image, a line at a time for (int to_y = 0 ; to_y < to_height ; to_y++) { @@ -133,7 +133,7 @@ inline static double sample(double const a, double const b, return sum; } -void transform_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &trans) +void transform_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans) { if (NR_PIXBLOCK_BPP(from) != 4 || NR_PIXBLOCK_BPP(to) != 4) { g_warning("A non-32-bpp image passed to transform_bicubic: scaling aborted."); @@ -160,7 +160,7 @@ void transform_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &tra int to_width = to->area.x1 - to->area.x0; int to_height = to->area.y1 - to->area.y0; - Geom::Matrix itrans = trans.inverse(); + Geom::Affine itrans = trans.inverse(); // Loop through every pixel of destination image, a line at a time for (int to_y = 0 ; to_y < to_height ; to_y++) { diff --git a/src/display/pixblock-transform.h b/src/display/pixblock-transform.h index 6c322835c..b73435fdf 100644 --- a/src/display/pixblock-transform.h +++ b/src/display/pixblock-transform.h @@ -17,8 +17,8 @@ namespace NR { -void transform_nearest(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &trans); -void transform_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Matrix const &trans); +void transform_nearest(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans); +void transform_bicubic(NRPixBlock *to, NRPixBlock *from, Geom::Affine const &trans); } /* namespace NR */ diff --git a/src/display/sodipodi-ctrl.cpp b/src/display/sodipodi-ctrl.cpp index a63f570cf..202fc206e 100644 --- a/src/display/sodipodi-ctrl.cpp +++ b/src/display/sodipodi-ctrl.cpp @@ -32,7 +32,7 @@ static void sp_ctrl_init (SPCtrl *ctrl); static void sp_ctrl_destroy (GtkObject *object); static void sp_ctrl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id); -static void sp_ctrl_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); +static void sp_ctrl_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); static void sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf); static double sp_ctrl_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item); @@ -210,7 +210,7 @@ sp_ctrl_set_arg (GtkObject *object, GtkArg *arg, guint arg_id) } static void -sp_ctrl_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags) +sp_ctrl_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags) { SPCtrl *ctrl; gint x, y; @@ -552,7 +552,7 @@ sp_ctrl_render (SPCanvasItem *item, SPCanvasBuf *buf) void SPCtrl::moveto (Geom::Point const p) { if (p != _point) { - sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (this), Geom::Matrix(Geom::Translate (p))); + sp_canvas_item_affine_absolute (SP_CANVAS_ITEM (this), Geom::Affine(Geom::Translate (p))); _moved = true; } _point = p; diff --git a/src/display/sodipodi-ctrlrect.cpp b/src/display/sodipodi-ctrlrect.cpp index 6d9c40858..380039798 100644 --- a/src/display/sodipodi-ctrlrect.cpp +++ b/src/display/sodipodi-ctrlrect.cpp @@ -30,7 +30,7 @@ static void sp_ctrlrect_class_init(SPCtrlRectClass *c); static void sp_ctrlrect_init(CtrlRect *ctrlrect); static void sp_ctrlrect_destroy(GtkObject *object); -static void sp_ctrlrect_update(SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); +static void sp_ctrlrect_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); static void sp_ctrlrect_render(SPCanvasItem *item, SPCanvasBuf *buf); static SPCanvasItemClass *parent_class; @@ -160,7 +160,7 @@ static void sp_ctrlrect_render(SPCanvasItem *item, SPCanvasBuf *buf) } -static void sp_ctrlrect_update(SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags) +static void sp_ctrlrect_update(SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags) { SP_CTRLRECT(item)->update(affine, flags); } @@ -220,7 +220,7 @@ void CtrlRect::render(SPCanvasBuf *buf) } -void CtrlRect::update(Geom::Matrix const &affine, unsigned int flags) +void CtrlRect::update(Geom::Affine const &affine, unsigned int flags) { if (((SPCanvasItemClass *) parent_class)->update) { ((SPCanvasItemClass *) parent_class)->update(this, affine, flags); diff --git a/src/display/sodipodi-ctrlrect.h b/src/display/sodipodi-ctrlrect.h index 9ecba47c8..2ba73a4c9 100644 --- a/src/display/sodipodi-ctrlrect.h +++ b/src/display/sodipodi-ctrlrect.h @@ -39,7 +39,7 @@ public: void setDashed(bool d); void render(SPCanvasBuf *buf); - void update(Geom::Matrix const &affine, unsigned int flags); + void update(Geom::Affine const &affine, unsigned int flags); private: void _requestUpdate(); diff --git a/src/display/sp-canvas-item.h b/src/display/sp-canvas-item.h index 1ae2ff2d1..cc0bdfc77 100644 --- a/src/display/sp-canvas-item.h +++ b/src/display/sp-canvas-item.h @@ -52,14 +52,14 @@ struct SPCanvasItem : public GtkObject { double x1, y1, x2, y2; Geom::Rect bounds; - Geom::Matrix xform; + Geom::Affine xform; }; /** * The vtable of an SPCanvasItem. */ struct _SPCanvasItemClass : public GtkObjectClass { - void (* update) (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); + void (* update) (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); void (* render) (SPCanvasItem *item, SPCanvasBuf *buf); double (* point) (SPCanvasItem *item, Geom::Point p, SPCanvasItem **actual_item); @@ -74,7 +74,7 @@ G_END_DECLS #define sp_canvas_item_set gtk_object_set -void sp_canvas_item_affine_absolute(SPCanvasItem *item, Geom::Matrix const &aff); +void sp_canvas_item_affine_absolute(SPCanvasItem *item, Geom::Affine const &aff); void sp_canvas_item_raise(SPCanvasItem *item, int positions); void sp_canvas_item_lower(SPCanvasItem *item, int positions); @@ -84,7 +84,7 @@ void sp_canvas_item_hide(SPCanvasItem *item); int sp_canvas_item_grab(SPCanvasItem *item, unsigned int event_mask, GdkCursor *cursor, guint32 etime); void sp_canvas_item_ungrab(SPCanvasItem *item, guint32 etime); -Geom::Matrix sp_canvas_item_i2w_affine(SPCanvasItem const *item); +Geom::Affine sp_canvas_item_i2w_affine(SPCanvasItem const *item); void sp_canvas_item_grab_focus(SPCanvasItem *item); diff --git a/src/display/sp-canvas-util.cpp b/src/display/sp-canvas-util.cpp index af80eed44..7eac32e2d 100644 --- a/src/display/sp-canvas-util.cpp +++ b/src/display/sp-canvas-util.cpp @@ -14,7 +14,7 @@ #include // for memset -#include <2geom/matrix.h> +#include <2geom/affine.h> #include "libnr/nr-pixops.h" #include "sp-canvas-item.h" #include "sp-canvas-util.h" @@ -77,7 +77,7 @@ sp_canvas_clear_buffer (SPCanvasBuf *buf) } } -Geom::Matrix sp_canvas_item_i2p_affine (SPCanvasItem * item) +Geom::Affine sp_canvas_item_i2p_affine (SPCanvasItem * item) { g_assert (item != NULL); /* this may be overly zealous - it is * plausible that this gets called @@ -86,7 +86,7 @@ Geom::Matrix sp_canvas_item_i2p_affine (SPCanvasItem * item) return item->xform; } -Geom::Matrix sp_canvas_item_i2i_affine (SPCanvasItem * from, SPCanvasItem * to) +Geom::Affine sp_canvas_item_i2i_affine (SPCanvasItem * from, SPCanvasItem * to) { g_assert (from != NULL); g_assert (to != NULL); @@ -94,7 +94,7 @@ Geom::Matrix sp_canvas_item_i2i_affine (SPCanvasItem * from, SPCanvasItem * to) return sp_canvas_item_i2w_affine(from) * sp_canvas_item_i2w_affine(to).inverse(); } -void sp_canvas_item_set_i2w_affine (SPCanvasItem * item, Geom::Matrix const &i2w) +void sp_canvas_item_set_i2w_affine (SPCanvasItem * item, Geom::Affine const &i2w) { g_assert (item != NULL); diff --git a/src/display/sp-canvas-util.h b/src/display/sp-canvas-util.h index 639163a28..f0aa15cb9 100644 --- a/src/display/sp-canvas-util.h +++ b/src/display/sp-canvas-util.h @@ -28,15 +28,15 @@ sp_canvas_clear_buffer (SPCanvasBuf * buf); /* get i2p (item to parent) affine transformation as general 6-element array */ -Geom::Matrix sp_canvas_item_i2p_affine (SPCanvasItem * item); +Geom::Affine sp_canvas_item_i2p_affine (SPCanvasItem * item); /* get i2i (item to item) affine transformation as general 6-element array */ -Geom::Matrix sp_canvas_item_i2i_affine (SPCanvasItem * from, SPCanvasItem * to); +Geom::Affine sp_canvas_item_i2i_affine (SPCanvasItem * from, SPCanvasItem * to); /* set item affine matrix to achieve given i2w matrix */ -void sp_canvas_item_set_i2w_affine (SPCanvasItem * item, Geom::Matrix const & aff); +void sp_canvas_item_set_i2w_affine (SPCanvasItem * item, Geom::Affine const & aff); void sp_canvas_item_move_to_z (SPCanvasItem * item, gint z); diff --git a/src/display/sp-canvas.cpp b/src/display/sp-canvas.cpp index fc68bcfc0..caf1ecbcc 100644 --- a/src/display/sp-canvas.cpp +++ b/src/display/sp-canvas.cpp @@ -30,7 +30,7 @@ #include #include "display/sp-canvas.h" #include "display/sp-canvas-group.h" -#include <2geom/matrix.h> +#include <2geom/affine.h> #include "libnr/nr-convex-hull.h" #include "preferences.h" #include "inkscape.h" @@ -171,7 +171,7 @@ sp_canvas_item_init (SPCanvasItem *item) // that should be initially invisible; examples of such items: node handles, the CtrlRect // used for rubberbanding, path outline, etc. item->flags |= SP_CANVAS_ITEM_VISIBLE; - item->xform = Geom::Matrix(Geom::identity()); + item->xform = Geom::Affine(Geom::identity()); } /** @@ -284,10 +284,10 @@ sp_canvas_item_dispose (GObject *object) * NB! affine is parent2canvas. */ static void -sp_canvas_item_invoke_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags) +sp_canvas_item_invoke_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags) { /* Apply the child item's transform */ - Geom::Matrix child_affine = item->xform * affine; + Geom::Affine child_affine = item->xform * affine; /* apply object flags to child flags */ int child_flags = flags & ~SP_CANVAS_UPDATE_REQUESTED; @@ -331,7 +331,7 @@ sp_canvas_item_invoke_point (SPCanvasItem *item, Geom::Point p, SPCanvasItem **a * @affine: An affine transformation matrix. */ void -sp_canvas_item_affine_absolute (SPCanvasItem *item, Geom::Matrix const &affine) +sp_canvas_item_affine_absolute (SPCanvasItem *item, Geom::Affine const &affine) { item->xform = affine; @@ -598,11 +598,11 @@ sp_canvas_item_ungrab (SPCanvasItem *item, guint32 etime) * Returns the product of all transformation matrices from the root item down * to the item. */ -Geom::Matrix sp_canvas_item_i2w_affine(SPCanvasItem const *item) +Geom::Affine sp_canvas_item_i2w_affine(SPCanvasItem const *item) { g_assert (SP_IS_CANVAS_ITEM (item)); // should we get this? - Geom::Matrix affine = Geom::identity(); + Geom::Affine affine = Geom::identity(); while (item) { affine *= item->xform; @@ -697,7 +697,7 @@ static void sp_canvas_group_class_init (SPCanvasGroupClass *klass); static void sp_canvas_group_init (SPCanvasGroup *group); static void sp_canvas_group_destroy (GtkObject *object); -static void sp_canvas_group_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); +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); @@ -782,7 +782,7 @@ sp_canvas_group_destroy (GtkObject *object) * Update handler for canvas groups */ static void -sp_canvas_group_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags) +sp_canvas_group_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags) { SPCanvasGroup const *group = SP_CANVAS_GROUP (item); Geom::RectHull corners(Geom::Point(0, 0)); diff --git a/src/display/sp-canvas.h b/src/display/sp-canvas.h index 9c8b19982..7ecbe0451 100644 --- a/src/display/sp-canvas.h +++ b/src/display/sp-canvas.h @@ -35,7 +35,7 @@ #include -#include <2geom/matrix.h> +#include <2geom/affine.h> #include #include <2geom/rect.h> diff --git a/src/display/sp-ctrlline.cpp b/src/display/sp-ctrlline.cpp index 0ef23812e..ef71c0a16 100644 --- a/src/display/sp-ctrlline.cpp +++ b/src/display/sp-ctrlline.cpp @@ -33,7 +33,7 @@ static void sp_ctrlline_class_init (SPCtrlLineClass *klass); static void sp_ctrlline_init (SPCtrlLine *ctrlline); static void sp_ctrlline_destroy (GtkObject *object); -static void sp_ctrlline_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); +static void sp_ctrlline_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); static void sp_ctrlline_render (SPCanvasItem *item, SPCanvasBuf *buf); static SPCanvasItemClass *parent_class; @@ -123,7 +123,7 @@ sp_ctrlline_render (SPCanvasItem *item, SPCanvasBuf *buf) } static void -sp_ctrlline_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags) +sp_ctrlline_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags) { SPCtrlLine *cl = SP_CTRLLINE (item); diff --git a/src/display/sp-ctrlline.h b/src/display/sp-ctrlline.h index a13907a70..e69c478fb 100644 --- a/src/display/sp-ctrlline.h +++ b/src/display/sp-ctrlline.h @@ -26,7 +26,7 @@ struct SPCtrlLine : public SPCanvasItem{ SPItem *item; // the item to which this line belongs in some sense; may be NULL for some users guint32 rgba; Geom::Point s, e; - Geom::Matrix affine; + Geom::Affine affine; }; struct SPCtrlLineClass : public SPCanvasItemClass{}; diff --git a/src/display/sp-ctrlpoint.cpp b/src/display/sp-ctrlpoint.cpp index ba40192a9..9f2ecb937 100644 --- a/src/display/sp-ctrlpoint.cpp +++ b/src/display/sp-ctrlpoint.cpp @@ -25,7 +25,7 @@ static void sp_ctrlpoint_class_init (SPCtrlPointClass *klass); static void sp_ctrlpoint_init (SPCtrlPoint *ctrlpoint); static void sp_ctrlpoint_destroy (GtkObject *object); -static void sp_ctrlpoint_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); +static void sp_ctrlpoint_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); static void sp_ctrlpoint_render (SPCanvasItem *item, SPCanvasBuf *buf); static SPCanvasItemClass *parent_class; @@ -110,7 +110,7 @@ sp_ctrlpoint_render (SPCanvasItem *item, SPCanvasBuf *buf) } static void -sp_ctrlpoint_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags) +sp_ctrlpoint_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags) { SPCtrlPoint *cp = SP_CTRLPOINT (item); diff --git a/src/display/sp-ctrlpoint.h b/src/display/sp-ctrlpoint.h index 1b7b7ba1e..b98d48f67 100644 --- a/src/display/sp-ctrlpoint.h +++ b/src/display/sp-ctrlpoint.h @@ -24,7 +24,7 @@ struct SPCtrlPoint : public SPCanvasItem { SPItem *item; // the item to which this line belongs in some sense; may be NULL for some users guint32 rgba; Geom::Point pt; - Geom::Matrix affine; + Geom::Affine affine; double radius; }; struct SPCtrlPointClass : public SPCanvasItemClass{}; diff --git a/src/display/sp-ctrlquadr.cpp b/src/display/sp-ctrlquadr.cpp index c29aecb96..1ed8d62b8 100644 --- a/src/display/sp-ctrlquadr.cpp +++ b/src/display/sp-ctrlquadr.cpp @@ -21,7 +21,7 @@ struct SPCtrlQuadr : public SPCanvasItem{ guint32 rgba; Geom::Point p1, p2, p3, p4; - Geom::Matrix affine; + Geom::Affine affine; }; struct SPCtrlQuadrClass : public SPCanvasItemClass{}; @@ -30,7 +30,7 @@ static void sp_ctrlquadr_class_init (SPCtrlQuadrClass *klass); static void sp_ctrlquadr_init (SPCtrlQuadr *ctrlquadr); static void sp_ctrlquadr_destroy (GtkObject *object); -static void sp_ctrlquadr_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags); +static void sp_ctrlquadr_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags); static void sp_ctrlquadr_render (SPCanvasItem *item, SPCanvasBuf *buf); static SPCanvasItemClass *parent_class; @@ -136,7 +136,7 @@ sp_ctrlquadr_render (SPCanvasItem *item, SPCanvasBuf *buf) static void -sp_ctrlquadr_update (SPCanvasItem *item, Geom::Matrix const &affine, unsigned int flags) +sp_ctrlquadr_update (SPCanvasItem *item, Geom::Affine const &affine, unsigned int flags) { SPCtrlQuadr *cq = SP_CTRLQUADR (item); diff --git a/src/draw-context.cpp b/src/draw-context.cpp index 62ae67336..182d4fca4 100644 --- a/src/draw-context.cpp +++ b/src/draw-context.cpp @@ -820,7 +820,7 @@ void spdc_create_single_dot(SPEventContext *ec, Geom::Point const &pt, char cons current stroke width, multiplied by the amount specified in the preferences */ Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Geom::Matrix const i2d (item->i2d_affine ()); + Geom::Affine const i2d (item->i2d_affine ()); Geom::Point pp = pt; double rad = 0.5 * prefs->getDouble(tool_path + "/dot-size", 3.0); if (event_state & GDK_MOD1_MASK) { diff --git a/src/dropper-context.cpp b/src/dropper-context.cpp index b7344889f..a2515c5f0 100644 --- a/src/dropper-context.cpp +++ b/src/dropper-context.cpp @@ -216,9 +216,9 @@ static gint sp_dropper_context_root_handler(SPEventContext *event_context, GdkEv } Geom::Point const cd = desktop->w2d(dc->centre); - Geom::Matrix const w2dt = desktop->w2d(); + Geom::Affine const w2dt = desktop->w2d(); const double scale = rw * w2dt.descrim(); - Geom::Matrix const sm( Geom::Scale(scale, scale) * Geom::Translate(cd) ); + Geom::Affine const sm( Geom::Scale(scale, scale) * Geom::Translate(cd) ); sp_canvas_item_affine_absolute(dc->area, sm); sp_canvas_item_show(dc->area); diff --git a/src/dyna-draw-context.cpp b/src/dyna-draw-context.cpp index 7d0c7ee91..6f0898d43 100644 --- a/src/dyna-draw-context.cpp +++ b/src/dyna-draw-context.cpp @@ -583,7 +583,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context, Geom::Point hatch_unit_vector(0,0); Geom::Point nearest(0,0); Geom::Point pointer(0,0); - Geom::Matrix motion_to_curve(Geom::identity()); + Geom::Affine motion_to_curve(Geom::identity()); if (event->motion.state & GDK_CONTROL_MASK) { // hatching - sense the item @@ -780,21 +780,21 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context, if (dc->hatch_spacing == 0 && hatch_dist != 0) { // Haven't set spacing yet: gray, center free, update radius live Geom::Point c = desktop->w2d(motion_w); - Geom::Matrix const sm (Geom::Scale(hatch_dist, hatch_dist) * Geom::Translate(c)); + Geom::Affine const sm (Geom::Scale(hatch_dist, hatch_dist) * Geom::Translate(c)); sp_canvas_item_affine_absolute(dc->hatch_area, sm); sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->hatch_area), 0x7f7f7fff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); sp_canvas_item_show(dc->hatch_area); } else if (dc->dragging && !dc->hatch_escaped) { // Tracking: green, center snapped, fixed radius Geom::Point c = motion_dt; - Geom::Matrix const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c)); + Geom::Affine const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c)); sp_canvas_item_affine_absolute(dc->hatch_area, sm); sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->hatch_area), 0x00FF00ff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); sp_canvas_item_show(dc->hatch_area); } else if (dc->dragging && dc->hatch_escaped) { // Tracking escaped: red, center free, fixed radius Geom::Point c = motion_dt; - Geom::Matrix const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c)); + Geom::Affine const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c)); sp_canvas_item_affine_absolute(dc->hatch_area, sm); sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->hatch_area), 0xFF0000ff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); @@ -803,7 +803,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context, // Not drawing but spacing set: gray, center snapped, fixed radius Geom::Point c = (nearest + dc->hatch_spacing * hatch_unit_vector) * motion_to_curve.inverse(); if (!IS_NAN(c[Geom::X]) && !IS_NAN(c[Geom::Y])) { - Geom::Matrix const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c)); + Geom::Affine const sm (Geom::Scale(dc->hatch_spacing, dc->hatch_spacing) * Geom::Translate(c)); sp_canvas_item_affine_absolute(dc->hatch_area, sm); sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(dc->hatch_area), 0x7f7f7fff, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT); sp_canvas_item_show(dc->hatch_area); diff --git a/src/extension/implementation/implementation.cpp b/src/extension/implementation/implementation.cpp index a8533a427..b1b671026 100644 --- a/src/extension/implementation/implementation.cpp +++ b/src/extension/implementation/implementation.cpp @@ -148,7 +148,7 @@ Implementation::finish(Inkscape::Extension::Print */*module*/) /* Rendering methods */ unsigned int -Implementation::bind(Inkscape::Extension::Print */*module*/, Geom::Matrix const */*transform*/, float /*opacity*/) +Implementation::bind(Inkscape::Extension::Print */*module*/, Geom::Affine const */*transform*/, float /*opacity*/) { return 0; } @@ -166,14 +166,14 @@ Implementation::comment(Inkscape::Extension::Print */*module*/, char const */*co } unsigned int -Implementation::fill(Inkscape::Extension::Print */*module*/, Geom::PathVector const &/*pathv*/, Geom::Matrix const */*ctm*/, SPStyle const */*style*/, +Implementation::fill(Inkscape::Extension::Print */*module*/, Geom::PathVector const &/*pathv*/, Geom::Affine const */*ctm*/, SPStyle const */*style*/, NRRect const */*pbox*/, NRRect const */*dbox*/, NRRect const */*bbox*/) { return 0; } unsigned int -Implementation::stroke(Inkscape::Extension::Print */*module*/, Geom::PathVector const &/*pathv*/, Geom::Matrix const */*transform*/, SPStyle const */*style*/, +Implementation::stroke(Inkscape::Extension::Print */*module*/, Geom::PathVector const &/*pathv*/, Geom::Affine const */*transform*/, SPStyle const */*style*/, NRRect const */*pbox*/, NRRect const */*dbox*/, NRRect const */*bbox*/) { return 0; @@ -181,7 +181,7 @@ Implementation::stroke(Inkscape::Extension::Print */*module*/, Geom::PathVector unsigned int Implementation::image(Inkscape::Extension::Print */*module*/, unsigned char */*px*/, unsigned int /*w*/, unsigned int /*h*/, unsigned int /*rs*/, - Geom::Matrix const */*transform*/, SPStyle const */*style*/) + Geom::Affine const */*transform*/, SPStyle const */*style*/) { return 0; } diff --git a/src/extension/implementation/implementation.h b/src/extension/implementation/implementation.h index 9de70dce7..bf584b401 100644 --- a/src/extension/implementation/implementation.h +++ b/src/extension/implementation/implementation.h @@ -100,20 +100,20 @@ public: /* ----- Rendering methods ----- */ virtual unsigned bind(Inkscape::Extension::Print *module, - Geom::Matrix const *transform, + Geom::Affine const *transform, float opacity); virtual unsigned release(Inkscape::Extension::Print *module); virtual unsigned comment(Inkscape::Extension::Print *module, const char * comment); virtual unsigned fill(Inkscape::Extension::Print *module, Geom::PathVector const &pathv, - Geom::Matrix const *ctm, + Geom::Affine const *ctm, SPStyle const *style, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox); virtual unsigned stroke(Inkscape::Extension::Print *module, Geom::PathVector const &pathv, - Geom::Matrix const *transform, + Geom::Affine const *transform, SPStyle const *style, NRRect const *pbox, NRRect const *dbox, @@ -123,7 +123,7 @@ public: unsigned int w, unsigned int h, unsigned int rs, - Geom::Matrix const *transform, + Geom::Affine const *transform, SPStyle const *style); virtual unsigned text(Inkscape::Extension::Print *module, char const *text, diff --git a/src/extension/internal/cairo-render-context.cpp b/src/extension/internal/cairo-render-context.cpp index b68105b30..cfbceab05 100644 --- a/src/extension/internal/cairo-render-context.cpp +++ b/src/extension/internal/cairo-render-context.cpp @@ -626,7 +626,7 @@ CairoRenderContext::popLayer(void) // copy over the correct CTM // It must be stored in item_transform of current state after pushState. - Geom::Matrix item_transform; + Geom::Affine item_transform; if (_state->parent_has_userspace) item_transform = getParentState()->transform * _state->item_transform; else @@ -908,7 +908,7 @@ CairoRenderContext::finish(void) } void -CairoRenderContext::transform(Geom::Matrix const *transform) +CairoRenderContext::transform(Geom::Affine const *transform) { g_assert( _is_valid ); @@ -921,7 +921,7 @@ CairoRenderContext::transform(Geom::Matrix const *transform) } void -CairoRenderContext::setTransform(Geom::Matrix const *transform) +CairoRenderContext::setTransform(Geom::Affine const *transform) { g_assert( _is_valid ); @@ -932,7 +932,7 @@ CairoRenderContext::setTransform(Geom::Matrix const *transform) } void -CairoRenderContext::getTransform(Geom::Matrix *copy) const +CairoRenderContext::getTransform(Geom::Affine *copy) const { g_assert( _is_valid ); @@ -947,12 +947,12 @@ CairoRenderContext::getTransform(Geom::Matrix *copy) const } void -CairoRenderContext::getParentTransform(Geom::Matrix *copy) const +CairoRenderContext::getParentTransform(Geom::Affine *copy) const { g_assert( _is_valid ); CairoRenderState *parent_state = getParentState(); - memcpy(copy, &parent_state->transform, sizeof(Geom::Matrix)); + memcpy(copy, &parent_state->transform, sizeof(Geom::Affine)); } void @@ -1001,7 +1001,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver SPPattern *pat = SP_PATTERN (paintserver); - Geom::Matrix ps2user, pcs2dev; + Geom::Affine ps2user, pcs2dev; ps2user = Geom::identity(); pcs2dev = Geom::identity(); @@ -1015,7 +1015,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver TRACE(("%f x %f pattern\n", width, height)); if (pbox && pattern_patternUnits(pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { - //Geom::Matrix bbox2user (pbox->x1 - pbox->x0, 0.0, 0.0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0); + //Geom::Affine bbox2user (pbox->x1 - pbox->x0, 0.0, 0.0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0); bbox_width_scaler = pbox->x1 - pbox->x0; bbox_height_scaler = pbox->y1 - pbox->y0; ps2user[4] = x * bbox_width_scaler + pbox->x0; @@ -1028,7 +1028,7 @@ CairoRenderContext::_createPatternPainter(SPPaintServer const *const paintserver } // apply pattern transformation - Geom::Matrix pattern_transform(pattern_patternTransform(pat)); + Geom::Affine pattern_transform(pattern_patternTransform(pat)); ps2user *= pattern_transform; Geom::Point ori (ps2user[4], ps2user[5]); @@ -1150,7 +1150,7 @@ CairoRenderContext::_createPatternForPaintServer(SPPaintServer const *const pain Geom::Point p2 (lg->x2.computed, lg->y2.computed); if (pbox && SP_GRADIENT(lg)->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { // convert to userspace - Geom::Matrix bbox2user(pbox->x1 - pbox->x0, 0, 0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0); + Geom::Affine bbox2user(pbox->x1 - pbox->x0, 0, 0, pbox->y1 - pbox->y0, pbox->x0, pbox->y0); p1 *= bbox2user; p2 *= bbox2user; } @@ -1413,7 +1413,7 @@ CairoRenderContext::renderPathVector(Geom::PathVector const & pathv, SPStyle con bool CairoRenderContext::renderImage(guchar *px, unsigned int w, unsigned int h, unsigned int rs, - Geom::Matrix const *image_transform, SPStyle const *style) + Geom::Affine const *image_transform, SPStyle const *style) { g_assert( _is_valid ); @@ -1550,7 +1550,7 @@ CairoRenderContext::_showGlyphs(cairo_t *cr, PangoFont *font, std::vector const &glyphtext, SPStyle const *style) { // create a cairo_font_face from PangoFont @@ -1668,7 +1668,7 @@ CairoRenderContext::_concatTransform(cairo_t *cr, double xx, double yx, double x } void -CairoRenderContext::_initCairoMatrix(cairo_matrix_t *matrix, Geom::Matrix const *transform) +CairoRenderContext::_initCairoMatrix(cairo_matrix_t *matrix, Geom::Affine const *transform) { matrix->xx = (*transform)[0]; matrix->yx = (*transform)[1]; @@ -1679,7 +1679,7 @@ CairoRenderContext::_initCairoMatrix(cairo_matrix_t *matrix, Geom::Matrix const } void -CairoRenderContext::_concatTransform(cairo_t *cr, Geom::Matrix const *transform) +CairoRenderContext::_concatTransform(cairo_t *cr, Geom::Affine const *transform) { _concatTransform(cr, (*transform)[0], (*transform)[1], (*transform)[2], (*transform)[3], diff --git a/src/extension/internal/cairo-render-context.h b/src/extension/internal/cairo-render-context.h index 73ee585ce..d663a82fd 100644 --- a/src/extension/internal/cairo-render-context.h +++ b/src/extension/internal/cairo-render-context.h @@ -53,12 +53,12 @@ struct CairoRenderState { unsigned int parent_has_userspace : 1; // whether the parent's ctm should be applied float opacity; bool has_filtereffect; - Geom::Matrix item_transform; // this item's item->transform, for correct clipping + Geom::Affine item_transform; // this item's item->transform, for correct clipping SPClipPath *clip_path; SPMask* mask; - Geom::Matrix transform; // the CTM + Geom::Affine transform; // the CTM }; class CairoRenderContext { @@ -127,10 +127,10 @@ public: CairoRenderState *getParentState(void) const; void setStateForStyle(SPStyle const *style); - void transform(Geom::Matrix const *transform); - void setTransform(Geom::Matrix const *transform); - void getTransform(Geom::Matrix *copy) const; - void getParentTransform(Geom::Matrix *copy) const; + void transform(Geom::Affine const *transform); + void setTransform(Geom::Affine const *transform); + void getTransform(Geom::Affine *copy) const; + void getParentTransform(Geom::Affine *copy) const; /* Clipping methods */ void addClipPath(Geom::PathVector const &pv, SPIEnum const *fill_rule); @@ -139,8 +139,8 @@ public: /* Rendering methods */ bool renderPathVector(Geom::PathVector const & pathv, SPStyle const *style, NRRect const *pbox); bool renderImage(unsigned char *px, unsigned int w, unsigned int h, unsigned int rs, - Geom::Matrix const *image_transform, SPStyle const *style); - bool renderGlyphtext(PangoFont *font, Geom::Matrix const *font_matrix, + Geom::Affine const *image_transform, SPStyle const *style); + bool renderGlyphtext(PangoFont *font, Geom::Affine const *font_matrix, std::vector const &glyphtext, SPStyle const *style); /* More general rendering methods will have to be added (like fill, stroke) */ @@ -191,9 +191,9 @@ protected: void _setFillStyle(SPStyle const *style, NRRect const *pbox); void _setStrokeStyle(SPStyle const *style, NRRect const *pbox); - void _initCairoMatrix(cairo_matrix_t *matrix, Geom::Matrix const *transform); + void _initCairoMatrix(cairo_matrix_t *matrix, Geom::Affine const *transform); void _concatTransform(cairo_t *cr, double xx, double yx, double xy, double yy, double x0, double y0); - void _concatTransform(cairo_t *cr, Geom::Matrix const *transform); + void _concatTransform(cairo_t *cr, Geom::Affine const *transform); GHashTable *font_table; static void font_data_free(gpointer data); diff --git a/src/extension/internal/cairo-renderer-pdf-out.cpp b/src/extension/internal/cairo-renderer-pdf-out.cpp index 8406e2a3b..6527a646b 100644 --- a/src/extension/internal/cairo-renderer-pdf-out.cpp +++ b/src/extension/internal/cairo-renderer-pdf-out.cpp @@ -37,7 +37,7 @@ #include "sp-item.h" #include "sp-root.h" -#include <2geom/matrix.h> +#include <2geom/affine.h> namespace Inkscape { namespace Extension { diff --git a/src/extension/internal/cairo-renderer.cpp b/src/extension/internal/cairo-renderer.cpp index bc3c6c484..015b3b2cb 100644 --- a/src/extension/internal/cairo-renderer.cpp +++ b/src/extension/internal/cairo-renderer.cpp @@ -157,7 +157,7 @@ static void sp_image_render(SPItem *item, CairoRenderContext *ctx); static void sp_symbol_render(SPItem *item, CairoRenderContext *ctx); static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx); -static void sp_shape_render_invoke_marker_rendering(SPMarker* marker, Geom::Matrix tr, SPStyle* style, CairoRenderContext *ctx) +static void sp_shape_render_invoke_marker_rendering(SPMarker* marker, Geom::Affine tr, SPStyle* style, CairoRenderContext *ctx) { bool render = true; if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { @@ -170,8 +170,8 @@ static void sp_shape_render_invoke_marker_rendering(SPMarker* marker, Geom::Matr if (render) { SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); - tr = (Geom::Matrix)marker_item->transform * (Geom::Matrix)marker->c2p * tr; - Geom::Matrix old_tr = marker_item->transform; + tr = (Geom::Affine)marker_item->transform * (Geom::Affine)marker->c2p * tr; + Geom::Affine old_tr = marker_item->transform; marker_item->transform = tr; ctx->getRenderer()->renderItem (ctx, marker_item); marker_item->transform = old_tr; @@ -199,7 +199,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx) for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START if ( shape->marker[i] ) { SPMarker* marker = SP_MARKER (shape->marker[i]); - Geom::Matrix tr; + Geom::Affine tr; if (marker->orient_auto) { tr = sp_shape_marker_get_transform_at_start(pathv.begin()->front()); } else { @@ -217,7 +217,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx) if ( path_it != pathv.begin() && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there { - Geom::Matrix tr; + Geom::Affine tr; if (marker->orient_auto) { tr = sp_shape_marker_get_transform_at_start(path_it->front()); } else { @@ -234,7 +234,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx) /* Put marker between curve_it1 and curve_it2. * Loop to end_default (so including closing segment), because when a path is closed, * there should be a midpoint marker between last segment and closing straight line segment */ - Geom::Matrix tr; + Geom::Affine tr; if (marker->orient_auto) { tr = sp_shape_marker_get_transform(*curve_it1, *curve_it2); } else { @@ -250,7 +250,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx) // END position if ( path_it != (pathv.end()-1) && !path_it->empty()) { Geom::Curve const &lastcurve = path_it->back_default(); - Geom::Matrix tr; + Geom::Affine tr; if (marker->orient_auto) { tr = sp_shape_marker_get_transform_at_end(lastcurve); } else { @@ -274,7 +274,7 @@ static void sp_shape_render (SPItem *item, CairoRenderContext *ctx) } Geom::Curve const &lastcurve = path_last[index]; - Geom::Matrix tr; + Geom::Affine tr; if (marker->orient_auto) { tr = sp_shape_marker_get_transform_at_end(lastcurve); } else { @@ -309,7 +309,7 @@ static void sp_use_render(SPItem *item, CairoRenderContext *ctx) CairoRenderer *renderer = ctx->getRenderer(); if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) { - Geom::Matrix tp(Geom::Translate(use->x.computed, use->y.computed)); + Geom::Affine tp(Geom::Translate(use->x.computed, use->y.computed)); ctx->pushState(); ctx->transform(&tp); translated = true; @@ -368,7 +368,7 @@ static void sp_image_render(SPItem *item, CairoRenderContext *ctx) Geom::Translate tp(x, y); Geom::Scale s(width / (double)w, height / (double)h); - Geom::Matrix t(s * tp); + Geom::Affine t(s * tp); ctx->renderImage (px, w, h, rs, &t, SP_OBJECT_STYLE (item)); } @@ -385,7 +385,7 @@ static void sp_symbol_render(SPItem *item, CairoRenderContext *ctx) // apply viewbox if set if (0 /*symbol->viewBox_set*/) { - Geom::Matrix vb2user; + Geom::Affine vb2user; double x, y, width, height; double view_width, view_height; x = 0.0; @@ -423,7 +423,7 @@ static void sp_root_render(SPItem *item, CairoRenderContext *ctx) ctx->pushState(); renderer->setStateForItem(ctx, item); - Geom::Matrix tempmat (root->c2p); + Geom::Affine tempmat (root->c2p); ctx->transform(&tempmat); sp_group_render(item, ctx); ctx->popState(); @@ -492,12 +492,12 @@ static void sp_asbitmap_render(SPItem *item, CairoRenderContext *ctx) // Calculate the matrix that will be applied to the image so that it exactly overlaps the source objects // Matix to put bitmap in correct place on document - Geom::Matrix t_on_document = (Geom::Matrix)(Geom::Scale (scale_x, -scale_y)) * - (Geom::Matrix)(Geom::Translate (shift_x, shift_y)); + Geom::Affine t_on_document = (Geom::Affine)(Geom::Scale (scale_x, -scale_y)) * + (Geom::Affine)(Geom::Translate (shift_x, shift_y)); // ctx matrix already includes item transformation. We must substract. - Geom::Matrix t_item = item->i2d_affine (); - Geom::Matrix t = t_on_document * t_item.inverse(); + Geom::Affine t_item = item->i2d_affine (); + Geom::Affine t = t_on_document * t_item.inverse(); // Do the export SPDocument *document = SP_OBJECT(item)->document; @@ -570,7 +570,7 @@ CairoRenderer::setStateForItem(CairoRenderContext *ctx, SPItem const *item) CairoRenderState *state = ctx->getCurrentState(); state->clip_path = item->clip_ref->getObject(); state->mask = item->mask_ref->getObject(); - state->item_transform = Geom::Matrix (item->transform); + state->item_transform = Geom::Affine (item->transform); // If parent_has_userspace is true the parent state's transform // has to be used for the mask's/clippath's context. @@ -601,7 +601,7 @@ CairoRenderer::renderItem(CairoRenderContext *ctx, SPItem *item) state->merge_opacity = FALSE; ctx->pushLayer(); } - Geom::Matrix tempmat (item->transform); + Geom::Affine tempmat (item->transform); ctx->transform(&tempmat); sp_item_invoke_render(item, ctx); @@ -652,7 +652,7 @@ CairoRenderer::setupDocument(CairoRenderContext *ctx, SPDocument *doc, bool page if (ctx->_vector_based_target) high *= PT_PER_PX; - Geom::Matrix tp(Geom::Translate(-d.x0 * (ctx->_vector_based_target ? PX_PER_PT : 1.0), + Geom::Affine tp(Geom::Translate(-d.x0 * (ctx->_vector_based_target ? PX_PER_PT : 1.0), (d.y1 - high) * (ctx->_vector_based_target ? PX_PER_PT : 1.0))); ctx->transform(&tp); } @@ -674,11 +674,11 @@ CairoRenderer::applyClipPath(CairoRenderContext *ctx, SPClipPath const *cp) CairoRenderContext::CairoRenderMode saved_mode = ctx->getRenderMode(); ctx->setRenderMode(CairoRenderContext::RENDER_MODE_CLIP); - Geom::Matrix saved_ctm; + Geom::Affine saved_ctm; if (cp->clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) { //SP_PRINT_DRECT("clipd", cp->display->bbox); NRRect clip_bbox(cp->display->bbox); - Geom::Matrix t(Geom::Scale(clip_bbox.x1 - clip_bbox.x0, clip_bbox.y1 - clip_bbox.y0)); + Geom::Affine t(Geom::Scale(clip_bbox.x1 - clip_bbox.x0, clip_bbox.y1 - clip_bbox.y0)); t[4] = clip_bbox.x0; t[5] = clip_bbox.y0; t *= ctx->getCurrentState()->transform; @@ -693,7 +693,7 @@ CairoRenderer::applyClipPath(CairoRenderContext *ctx, SPClipPath const *cp) SPItem *item = SP_ITEM(child); // combine transform of the item in clippath and the item using clippath: - Geom::Matrix tempmat (item->transform); + Geom::Affine tempmat (item->transform); tempmat = tempmat * (ctx->getCurrentState()->item_transform); // render this item in clippath @@ -730,7 +730,7 @@ CairoRenderer::applyMask(CairoRenderContext *ctx, SPMask const *mask) NRRect mask_bbox(mask->display->bbox); // TODO: should the bbox be transformed if maskUnits != userSpaceOnUse ? if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) { - Geom::Matrix t(Geom::Scale(mask_bbox.x1 - mask_bbox.x0, mask_bbox.y1 - mask_bbox.y0)); + Geom::Affine t(Geom::Scale(mask_bbox.x1 - mask_bbox.x0, mask_bbox.y1 - mask_bbox.y0)); t[4] = mask_bbox.x0; t[5] = mask_bbox.y0; t *= ctx->getCurrentState()->transform; diff --git a/src/extension/internal/emf-win32-print.cpp b/src/extension/internal/emf-win32-print.cpp index e1ef77ae5..503a13d09 100644 --- a/src/extension/internal/emf-win32-print.cpp +++ b/src/extension/internal/emf-win32-print.cpp @@ -310,7 +310,7 @@ PrintEmfWin32::destroy_brush() void -PrintEmfWin32::create_pen(SPStyle const *style, const Geom::Matrix &transform) +PrintEmfWin32::create_pen(SPStyle const *style, const Geom::Affine &transform) { if (style) { float rgb[3]; @@ -459,12 +459,12 @@ PrintEmfWin32::flush_fill() } unsigned int -PrintEmfWin32::bind(Inkscape::Extension::Print * /*mod*/, Geom::Matrix const *transform, float /*opacity*/) +PrintEmfWin32::bind(Inkscape::Extension::Print * /*mod*/, Geom::Affine const *transform, float /*opacity*/) { - Geom::Matrix tr = *transform; + Geom::Affine tr = *transform; if (m_tr_stack.size()) { - Geom::Matrix tr_top = m_tr_stack.top(); + Geom::Affine tr_top = m_tr_stack.top(); m_tr_stack.push(tr * tr_top); } else { m_tr_stack.push(tr); @@ -482,12 +482,12 @@ PrintEmfWin32::release(Inkscape::Extension::Print * /*mod*/) unsigned int PrintEmfWin32::fill(Inkscape::Extension::Print * /*mod*/, - Geom::PathVector const &pathv, Geom::Matrix const * /*transform*/, SPStyle const *style, + Geom::PathVector const &pathv, Geom::Affine const * /*transform*/, SPStyle const *style, NRRect const * /*pbox*/, NRRect const * /*dbox*/, NRRect const * /*bbox*/) { if (!hdc) return 0; - Geom::Matrix tf = m_tr_stack.top(); + Geom::Affine tf = m_tr_stack.top(); flush_fill(); // flush any pending fills @@ -511,12 +511,12 @@ PrintEmfWin32::fill(Inkscape::Extension::Print * /*mod*/, unsigned int PrintEmfWin32::stroke (Inkscape::Extension::Print * /*mod*/, - Geom::PathVector const &pathv, const Geom::Matrix * /*transform*/, const SPStyle *style, + Geom::PathVector const &pathv, const Geom::Affine * /*transform*/, const SPStyle *style, const NRRect * /*pbox*/, const NRRect * /*dbox*/, const NRRect * /*bbox*/) { if (!hdc) return 0; - Geom::Matrix tf = m_tr_stack.top(); + Geom::Affine tf = m_tr_stack.top(); stroke_and_fill = ( pathv == fill_pathv ); @@ -550,7 +550,7 @@ PrintEmfWin32::stroke (Inkscape::Extension::Print * /*mod*/, bool -PrintEmfWin32::print_simple_shape(Geom::PathVector const &pathv, const Geom::Matrix &transform) +PrintEmfWin32::print_simple_shape(Geom::PathVector const &pathv, const Geom::Affine &transform) { Geom::PathVector pv = pathv_to_linear_and_cubic_beziers( pathv * transform ); @@ -746,7 +746,7 @@ PrintEmfWin32::print_simple_shape(Geom::PathVector const &pathv, const Geom::Mat } unsigned int -PrintEmfWin32::print_pathv(Geom::PathVector const &pathv, const Geom::Matrix &transform) +PrintEmfWin32::print_pathv(Geom::PathVector const &pathv, const Geom::Affine &transform) { simple_shape = print_simple_shape(pathv, transform); @@ -863,7 +863,7 @@ PrintEmfWin32::text(Inkscape::Extension::Print * /*mod*/, char const *text, Geom if (!hdc) return 0; HFONT hfont = NULL; - Geom::Matrix tf = m_tr_stack.top(); + Geom::Affine tf = m_tr_stack.top(); double rot = 1800.0*std::atan2(tf[1], tf[0])/M_PI; // 0.1 degree rotation #ifdef USE_PANGO_WIN32 diff --git a/src/extension/internal/emf-win32-print.h b/src/extension/internal/emf-win32-print.h index a0f26abb5..a9f639bcd 100644 --- a/src/extension/internal/emf-win32-print.h +++ b/src/extension/internal/emf-win32-print.h @@ -38,15 +38,15 @@ class PrintEmfWin32 : public Inkscape::Extension::Implementation::Implementation HBRUSH hbrush, hbrushOld; HPEN hpen, hpenOld; - std::stack m_tr_stack; + std::stack m_tr_stack; Geom::PathVector fill_pathv; - Geom::Matrix fill_transform; + Geom::Affine fill_transform; bool stroke_and_fill; bool fill_only; bool simple_shape; - unsigned int print_pathv (Geom::PathVector const &pathv, const Geom::Matrix &transform); - bool print_simple_shape (Geom::PathVector const &pathv, const Geom::Matrix &transform); + unsigned int print_pathv (Geom::PathVector const &pathv, const Geom::Affine &transform); + bool print_simple_shape (Geom::PathVector const &pathv, const Geom::Affine &transform); public: PrintEmfWin32 (void); @@ -59,13 +59,13 @@ public: virtual unsigned int finish (Inkscape::Extension::Print * module); /* Rendering methods */ - virtual unsigned int bind(Inkscape::Extension::Print *module, Geom::Matrix const *transform, float opacity); + virtual unsigned int bind(Inkscape::Extension::Print *module, Geom::Affine const *transform, float opacity); virtual unsigned int release(Inkscape::Extension::Print *module); virtual unsigned int fill (Inkscape::Extension::Print * module, - Geom::PathVector const &pathv, const Geom::Matrix *ctm, const SPStyle *style, + Geom::PathVector const &pathv, const Geom::Affine *ctm, const SPStyle *style, const NRRect *pbox, const NRRect *dbox, const NRRect *bbox); virtual unsigned int stroke (Inkscape::Extension::Print * module, - Geom::PathVector const &pathv, const Geom::Matrix *transform, const SPStyle *style, + Geom::PathVector const &pathv, const Geom::Affine *transform, const SPStyle *style, const NRRect *pbox, const NRRect *dbox, const NRRect *bbox); virtual unsigned int comment(Inkscape::Extension::Print *module, const char * comment); virtual unsigned int text(Inkscape::Extension::Print *module, char const *text, @@ -79,7 +79,7 @@ protected: void destroy_brush(); - void create_pen(SPStyle const *style, const Geom::Matrix &transform); + void create_pen(SPStyle const *style, const Geom::Affine &transform); void destroy_pen(); diff --git a/src/extension/internal/javafx-out.cpp b/src/extension/internal/javafx-out.cpp index 7098027c7..5902c3ad0 100644 --- a/src/extension/internal/javafx-out.cpp +++ b/src/extension/internal/javafx-out.cpp @@ -494,7 +494,7 @@ bool JavaFXOutput::doCurve(SPItem *item, const String &id) // convert the path to only lineto's and cubic curveto's: Geom::Scale yflip(1.0, -1.0); - Geom::Matrix tf = item->i2d_affine() * yflip; + Geom::Affine tf = item->i2d_affine() * yflip; Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curve->get_pathvector() * tf ); //Count the NR_CURVETOs/LINETOs (including closing line segment) @@ -636,7 +636,7 @@ bool JavaFXOutput::doCurve(SPItem *item, const String &id) // convert the path to only lineto's and cubic curveto's: Geom::Scale yflip(1.0, -1.0); - Geom::Matrix tf = item->i2d_affine() * yflip; + Geom::Affine tf = item->i2d_affine() * yflip; Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curve->get_pathvector() * tf ); //Count the NR_CURVETOs/LINETOs (including closing line segment) diff --git a/src/extension/internal/latex-pstricks.cpp b/src/extension/internal/latex-pstricks.cpp index 44b64c5f8..e09e7c024 100644 --- a/src/extension/internal/latex-pstricks.cpp +++ b/src/extension/internal/latex-pstricks.cpp @@ -164,12 +164,12 @@ PrintLatex::finish (Inkscape::Extension::Print *mod) } unsigned int -PrintLatex::bind(Inkscape::Extension::Print *mod, Geom::Matrix const *transform, float opacity) +PrintLatex::bind(Inkscape::Extension::Print *mod, Geom::Affine const *transform, float opacity) { - Geom::Matrix tr = *transform; + Geom::Affine tr = *transform; if(m_tr_stack.size()){ - Geom::Matrix tr_top = m_tr_stack.top(); + Geom::Affine tr_top = m_tr_stack.top(); m_tr_stack.push(tr * tr_top); }else m_tr_stack.push(tr); @@ -194,7 +194,7 @@ unsigned int PrintLatex::comment (Inkscape::Extension::Print * module, unsigned int PrintLatex::fill(Inkscape::Extension::Print *mod, - Geom::PathVector const &pathv, Geom::Matrix const *transform, SPStyle const *style, + Geom::PathVector const &pathv, Geom::Affine const *transform, SPStyle const *style, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox) { if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned. @@ -227,7 +227,7 @@ PrintLatex::fill(Inkscape::Extension::Print *mod, } unsigned int -PrintLatex::stroke (Inkscape::Extension::Print *mod, Geom::PathVector const &pathv, const Geom::Matrix *transform, const SPStyle *style, +PrintLatex::stroke (Inkscape::Extension::Print *mod, Geom::PathVector const &pathv, const Geom::Affine *transform, const SPStyle *style, const NRRect *pbox, const NRRect *dbox, const NRRect *bbox) { if (!_stream) return 0; // XXX: fixme, returning -1 as unsigned. @@ -236,7 +236,7 @@ PrintLatex::stroke (Inkscape::Extension::Print *mod, Geom::PathVector const &pat Inkscape::SVGOStringStream os; float rgb[3]; float stroke_opacity; - Geom::Matrix tr_stack = m_tr_stack.top(); + Geom::Affine tr_stack = m_tr_stack.top(); double const scale = tr_stack.descrim(); os.setf(std::ios::fixed); @@ -277,13 +277,13 @@ PrintLatex::stroke (Inkscape::Extension::Print *mod, Geom::PathVector const &pat // FIXME: why is 'transform' argument not used? void -PrintLatex::print_pathvector(SVGOStringStream &os, Geom::PathVector const &pathv_in, const Geom::Matrix * /*transform*/) +PrintLatex::print_pathvector(SVGOStringStream &os, Geom::PathVector const &pathv_in, const Geom::Affine * /*transform*/) { if (pathv_in.empty()) return; -// Geom::Matrix tf=*transform; // why was this here? - Geom::Matrix tf_stack=m_tr_stack.top(); // and why is transform argument not used? +// Geom::Affine tf=*transform; // why was this here? + Geom::Affine tf_stack=m_tr_stack.top(); // and why is transform argument not used? Geom::PathVector pathv = pathv_in * tf_stack; // generates new path, which is a bit slow, but this doesn't have to be performance optimized os << "\\newpath\n"; diff --git a/src/extension/internal/latex-pstricks.h b/src/extension/internal/latex-pstricks.h index a33e169e8..64b0de474 100644 --- a/src/extension/internal/latex-pstricks.h +++ b/src/extension/internal/latex-pstricks.h @@ -31,9 +31,9 @@ class PrintLatex : public Inkscape::Extension::Implementation::Implementation { float _height; FILE * _stream; - std::stack m_tr_stack; + std::stack m_tr_stack; - void print_pathvector(SVGOStringStream &os, Geom::PathVector const &pathv_in, const Geom::Matrix * /*transform*/); + void print_pathvector(SVGOStringStream &os, Geom::PathVector const &pathv_in, const Geom::Affine * /*transform*/); void print_2geomcurve(SVGOStringStream &os, Geom::Curve const & c ); public: @@ -47,12 +47,12 @@ public: virtual unsigned int finish (Inkscape::Extension::Print * module); /* Rendering methods */ - virtual unsigned int bind(Inkscape::Extension::Print *module, Geom::Matrix const *transform, float opacity); + virtual unsigned int bind(Inkscape::Extension::Print *module, Geom::Affine const *transform, float opacity); virtual unsigned int release(Inkscape::Extension::Print *module); - virtual unsigned int fill (Inkscape::Extension::Print * module, Geom::PathVector const &pathv, const Geom::Matrix *ctm, const SPStyle *style, + virtual unsigned int fill (Inkscape::Extension::Print * module, Geom::PathVector const &pathv, const Geom::Affine *ctm, const SPStyle *style, const NRRect *pbox, const NRRect *dbox, const NRRect *bbox); - virtual unsigned int stroke (Inkscape::Extension::Print * module, Geom::PathVector const &pathv, const Geom::Matrix *transform, const SPStyle *style, + virtual unsigned int stroke (Inkscape::Extension::Print * module, Geom::PathVector const &pathv, const Geom::Affine *transform, const SPStyle *style, const NRRect *pbox, const NRRect *dbox, const NRRect *bbox); virtual unsigned int comment(Inkscape::Extension::Print *module, const char * comment); bool textToPath (Inkscape::Extension::Print * ext); diff --git a/src/extension/internal/latex-text-renderer.cpp b/src/extension/internal/latex-text-renderer.cpp index fd99afe31..3c4bb5c92 100644 --- a/src/extension/internal/latex-text-renderer.cpp +++ b/src/extension/internal/latex-text-renderer.cpp @@ -246,7 +246,7 @@ LaTeXTextRenderer::sp_use_render(SPItem *item) SPUse *use = SP_USE(item); if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) { - Geom::Matrix tp(Geom::Translate(use->x.computed, use->y.computed)); + Geom::Affine tp(Geom::Translate(use->x.computed, use->y.computed)); push_transform(tp); translated = true; } @@ -311,8 +311,8 @@ LaTeXTextRenderer::sp_text_render(SPItem *item) } // get rotation - Geom::Matrix i2doc = item->i2doc_affine(); - Geom::Matrix wotransl = i2doc.without_translation(); + Geom::Affine i2doc = item->i2doc_affine(); + Geom::Affine wotransl = i2doc.withoutTranslation(); double degrees = -180/M_PI * Geom::atan2(wotransl.xAxis()); bool has_rotation = !Geom::are_near(degrees,0.); @@ -412,8 +412,8 @@ Flowing in rectangle is possible, not in arb shape. } // get rotation - Geom::Matrix i2doc = item->i2doc_affine(); - Geom::Matrix wotransl = i2doc.without_translation(); + Geom::Affine i2doc = item->i2doc_affine(); + Geom::Affine wotransl = i2doc.withoutTranslation(); double degrees = -180/M_PI * Geom::atan2(wotransl.xAxis()); bool has_rotation = !Geom::are_near(degrees,0.); @@ -543,17 +543,17 @@ LaTeXTextRenderer::setupDocument(SPDocument *doc, bool pageBoundingBox, SPItem * return true; } -Geom::Matrix const & +Geom::Affine const & LaTeXTextRenderer::transform() { return _transform_stack.top(); } void -LaTeXTextRenderer::push_transform(Geom::Matrix const &tr) +LaTeXTextRenderer::push_transform(Geom::Affine const &tr) { if(_transform_stack.size()){ - Geom::Matrix tr_top = _transform_stack.top(); + Geom::Affine tr_top = _transform_stack.top(); _transform_stack.push(tr * tr_top); } else { _transform_stack.push(tr); diff --git a/src/extension/internal/latex-text-renderer.h b/src/extension/internal/latex-text-renderer.h index e4bbd94ed..2259427d6 100644 --- a/src/extension/internal/latex-text-renderer.h +++ b/src/extension/internal/latex-text-renderer.h @@ -18,7 +18,7 @@ #endif #include "extension/extension.h" -#include <2geom/matrix.h> +#include <2geom/affine.h> #include class SPItem; @@ -51,10 +51,10 @@ protected: bool _pdflatex; /** true if ouputting for pdfLaTeX*/ - void push_transform(Geom::Matrix const &transform); - Geom::Matrix const & transform(); + void push_transform(Geom::Affine const &transform); + Geom::Affine const & transform(); void pop_transform(); - std::stack _transform_stack; + std::stack _transform_stack; void writePreamble(); void writePostamble(); diff --git a/src/extension/internal/odf.cpp b/src/extension/internal/odf.cpp index b5c842a40..6a350ab48 100644 --- a/src/extension/internal/odf.cpp +++ b/src/extension/internal/odf.cpp @@ -259,7 +259,7 @@ private: * NOTE: * This class is ported almost verbatim from the public domain * JAMA Matrix package. It is modified to handle only 3x3 matrices - * and our Geom::Matrix affine transform class. We give full + * and our Geom::Affine affine transform class. We give full * attribution to them, along with many thanks. JAMA can be found at: * http://math.nist.gov/javanumerics/jama * @@ -921,7 +921,7 @@ static Glib::ustring getExtension(const Glib::ustring &fname) } -static Glib::ustring formatTransform(Geom::Matrix &tf) +static Glib::ustring formatTransform(Geom::Affine &tf) { Glib::ustring str; if (!tf.isIdentity()) @@ -943,16 +943,16 @@ static Glib::ustring formatTransform(Geom::Matrix &tf) * Get the general transform from SVG pixels to * ODF cm */ -static Geom::Matrix getODFTransform(const SPItem *item) +static Geom::Affine getODFTransform(const SPItem *item) { //### Get SVG-to-ODF transform - Geom::Matrix tf (item->i2d_affine()); + Geom::Affine tf (item->i2d_affine()); //Flip Y into document coordinates double doc_height = SP_ACTIVE_DOCUMENT->getHeight(); - Geom::Matrix doc2dt_tf = Geom::Matrix(Geom::Scale(1.0, -1.0)); - doc2dt_tf = doc2dt_tf * Geom::Matrix(Geom::Translate(0, doc_height)); + Geom::Affine doc2dt_tf = Geom::Affine(Geom::Scale(1.0, -1.0)); + doc2dt_tf = doc2dt_tf * Geom::Affine(Geom::Translate(0, doc_height)); tf = tf * doc2dt_tf; - tf = tf * Geom::Matrix(Geom::Scale(pxToCm)); + tf = tf * Geom::Affine(Geom::Scale(pxToCm)); return tf; } @@ -970,10 +970,10 @@ static Geom::OptRect getODFBoundingBox(const SPItem *item) if (bbox_temp) { bbox = *bbox_temp; double doc_height = SP_ACTIVE_DOCUMENT->getHeight(); - Geom::Matrix doc2dt_tf = Geom::Matrix(Geom::Scale(1.0, -1.0)); - doc2dt_tf = doc2dt_tf * Geom::Matrix(Geom::Translate(0, doc_height)); + Geom::Affine doc2dt_tf = Geom::Affine(Geom::Scale(1.0, -1.0)); + doc2dt_tf = doc2dt_tf * Geom::Affine(Geom::Translate(0, doc_height)); bbox = *bbox * doc2dt_tf; - bbox = *bbox * Geom::Matrix(Geom::Scale(pxToCm)); + bbox = *bbox * Geom::Affine(Geom::Scale(pxToCm)); } return bbox; } @@ -984,10 +984,10 @@ static Geom::OptRect getODFBoundingBox(const SPItem *item) * Get the transform for an item, correcting for * handedness reversal */ -static Geom::Matrix getODFItemTransform(const SPItem *item) +static Geom::Affine getODFItemTransform(const SPItem *item) { - Geom::Matrix itemTransform (Geom::Scale(1, -1)); - itemTransform = itemTransform * (Geom::Matrix)item->transform; + Geom::Affine itemTransform (Geom::Scale(1, -1)); + itemTransform = itemTransform * (Geom::Affine)item->transform; itemTransform = itemTransform * Geom::Scale(1, -1); return itemTransform; } @@ -997,7 +997,7 @@ static Geom::Matrix getODFItemTransform(const SPItem *item) /** * Get some fun facts from the transform */ -static void analyzeTransform(Geom::Matrix &tf, +static void analyzeTransform(Geom::Affine &tf, double &rotate, double &/*xskew*/, double &/*yskew*/, double &xscale, double &yscale) { @@ -1087,7 +1087,7 @@ OdfOutput::preprocess(ZipFile &zf, Inkscape::XML::Node *node) } SPItem *item = SP_ITEM(reprobj); //### Get SVG-to-ODF transform - Geom::Matrix tf = getODFTransform(item); + Geom::Affine tf = getODFTransform(item); if (nodeName == "image" || nodeName == "svg:image") { @@ -1487,7 +1487,7 @@ bool OdfOutput::writeStyle(ZipFile &zf) */ static int writePath(Writer &outs, Geom::PathVector const &pathv, - Geom::Matrix const &tf, double xoff, double yoff) + Geom::Affine const &tf, double xoff, double yoff) { using Geom::X; using Geom::Y; @@ -1638,7 +1638,7 @@ bool OdfOutput::processStyle(Writer &outs, SPItem *item, bool OdfOutput::processGradient(Writer &outs, SPItem *item, - const Glib::ustring &id, Geom::Matrix &/*tf*/) + const Glib::ustring &id, Geom::Affine &/*tf*/) { if (!item) return false; @@ -1864,7 +1864,7 @@ bool OdfOutput::writeTree(Writer &couts, Writer &souts, Glib::ustring id = getAttribute(node, "id"); //### Get SVG-to-ODF transform - Geom::Matrix tf = getODFTransform(item); + Geom::Affine tf = getODFTransform(item); //### Get ODF bounding box params for item Geom::OptRect bbox = getODFBoundingBox(item); @@ -1960,7 +1960,7 @@ bool OdfOutput::writeTree(Writer &couts, Writer &souts, iwidth = xscale * iwidth; iheight = yscale * iheight; - Geom::Matrix itemTransform = getODFItemTransform(item); + Geom::Affine itemTransform = getODFItemTransform(item); Glib::ustring itemTransformString = formatTransform(itemTransform); diff --git a/src/extension/internal/odf.h b/src/extension/internal/odf.h index 9ad261098..2a6f7799f 100644 --- a/src/extension/internal/odf.h +++ b/src/extension/internal/odf.h @@ -317,7 +317,7 @@ private: bool processStyle(Writer &outs, SPItem *item, const Glib::ustring &id); bool processGradient(Writer &outs, SPItem *item, - const Glib::ustring &id, Geom::Matrix &tf); + const Glib::ustring &id, Geom::Affine &tf); bool writeStyleHeader(Writer &outs); diff --git a/src/extension/internal/pdfinput/svg-builder.cpp b/src/extension/internal/pdfinput/svg-builder.cpp index 8b414239a..8d7c95560 100644 --- a/src/extension/internal/pdfinput/svg-builder.cpp +++ b/src/extension/internal/pdfinput/svg-builder.cpp @@ -247,7 +247,7 @@ static gchar *svgConvertGfxRGB(GfxRGB *color) { static void svgSetTransform(Inkscape::XML::Node *node, double c0, double c1, double c2, double c3, double c4, double c5) { - Geom::Matrix matrix(c0, c1, c2, c3, c4, c5); + Geom::Affine matrix(c0, c1, c2, c3, c4, c5); gchar *transform_text = sp_svg_transform_write(matrix); node->setAttribute("transform", transform_text); g_free(transform_text); @@ -544,7 +544,7 @@ void SvgBuilder::setClipPath(GfxState *state, bool even_odd) { * \return true on success; false on invalid transformation */ bool SvgBuilder::getTransform(double *transform) { - Geom::Matrix svd; + Geom::Affine svd; gchar const *tr = _container->attribute("transform"); bool valid = sp_svg_transform_read(tr, &svd); if (valid) { @@ -634,7 +634,7 @@ gchar *SvgBuilder::_createTilingPattern(GfxTilingPattern *tiling_pattern, Inkscape::XML::Node *pattern_node = _xml_doc->createElement("svg:pattern"); // Set pattern transform matrix double *p2u = tiling_pattern->getMatrix(); - Geom::Matrix pat_matrix(p2u[0], p2u[1], p2u[2], p2u[3], p2u[4], p2u[5]); + Geom::Affine pat_matrix(p2u[0], p2u[1], p2u[2], p2u[3], p2u[4], p2u[5]); gchar *transform_text = sp_svg_transform_write(pat_matrix); pattern_node->setAttribute("patternTransform", transform_text); g_free(transform_text); @@ -732,10 +732,10 @@ gchar *SvgBuilder::_createGradient(GfxShading *shading, double *matrix, bool for gradient->setAttribute("gradientUnits", "userSpaceOnUse"); // If needed, flip the gradient transform around the y axis if (matrix) { - Geom::Matrix pat_matrix(matrix[0], matrix[1], matrix[2], matrix[3], + Geom::Affine pat_matrix(matrix[0], matrix[1], matrix[2], matrix[3], matrix[4], matrix[5]); if ( !for_shading && _is_top_level ) { - Geom::Matrix flip(1.0, 0.0, 0.0, -1.0, 0.0, _height * PT_PER_PX); + Geom::Affine flip(1.0, 0.0, 0.0, -1.0, 0.0, _height * PT_PER_PX); pat_matrix *= flip; } gchar *transform_text = sp_svg_transform_write(pat_matrix); @@ -1149,7 +1149,7 @@ void SvgBuilder::updateTextMatrix(GfxState *state) { max_scale = h_scale; } // Calculate new text matrix - Geom::Matrix new_text_matrix(text_matrix[0] * state->getHorizScaling(), + Geom::Affine new_text_matrix(text_matrix[0] * state->getHorizScaling(), text_matrix[1] * state->getHorizScaling(), -text_matrix[2], -text_matrix[3], 0.0, 0.0); @@ -1184,7 +1184,7 @@ void SvgBuilder::_flushText() { Inkscape::XML::Node *text_node = _xml_doc->createElement("svg:text"); // Set text matrix - Geom::Matrix text_transform(_text_matrix); + Geom::Affine text_transform(_text_matrix); text_transform[4] = first_glyph.position[0]; text_transform[5] = first_glyph.position[1]; gchar *transform = sp_svg_transform_write(text_transform); @@ -1719,7 +1719,7 @@ void SvgBuilder::addMaskedImage(GfxState *state, Stream *str, int width, int hei mask_image_node->setAttribute("transform", NULL); mask_node->appendChild(mask_image_node); // Scale the mask to the size of the image - Geom::Matrix mask_transform((double)width, 0.0, 0.0, (double)height, 0.0, 0.0); + Geom::Affine mask_transform((double)width, 0.0, 0.0, (double)height, 0.0, 0.0); gchar *transform_text = sp_svg_transform_write(mask_transform); mask_node->setAttribute("maskTransform", transform_text); g_free(transform_text); diff --git a/src/extension/internal/pdfinput/svg-builder.h b/src/extension/internal/pdfinput/svg-builder.h index f0062bbe6..47e5d7735 100644 --- a/src/extension/internal/pdfinput/svg-builder.h +++ b/src/extension/internal/pdfinput/svg-builder.h @@ -27,7 +27,7 @@ namespace Inkscape { } #include <2geom/point.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> #include #include "CharTypes.h" @@ -212,7 +212,7 @@ private: char *_font_specification; double _font_scaling; bool _need_font_update; - Geom::Matrix _text_matrix; + Geom::Affine _text_matrix; Geom::Point _text_position; std::vector _glyphs; // Added characters bool _in_text_object; // Whether we are inside a text object diff --git a/src/extension/internal/pov-out.cpp b/src/extension/internal/pov-out.cpp index a130b6923..b5389bad3 100644 --- a/src/extension/internal/pov-out.cpp +++ b/src/extension/internal/pov-out.cpp @@ -301,7 +301,7 @@ bool PovOutput::doCurve(SPItem *item, const String &id) povShapes.push_back(shapeInfo); //passed all tests. save the info // convert the path to only lineto's and cubic curveto's: - Geom::Matrix tf = item->i2d_affine(); + Geom::Affine tf = item->i2d_affine(); Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers( curve->get_pathvector() * tf ); /* diff --git a/src/extension/internal/win32.cpp b/src/extension/internal/win32.cpp index 8b4ff13c8..537c91a2c 100644 --- a/src/extension/internal/win32.cpp +++ b/src/extension/internal/win32.cpp @@ -293,7 +293,7 @@ PrintWin32::finish (Inkscape::Extension::Print *mod) scaley = dpiY / 72.0; // We simply map document 0,0 to physical page 0,0 - Geom::Matrix affine = Geom::Scale(scalex / 1.25, scaley / 1.25); + Geom::Affine affine = Geom::Scale(scalex / 1.25, scaley / 1.25); nr_arena_item_set_transform (mod->root, affine); diff --git a/src/extension/internal/win32.h b/src/extension/internal/win32.h index 02790a231..4a913bb05 100644 --- a/src/extension/internal/win32.h +++ b/src/extension/internal/win32.h @@ -70,11 +70,11 @@ public: /* Rendering methods */ /* - virtual unsigned int bind (Inkscape::Extension::Print * module, const Geom::Matrix *transform, float opacity); + virtual unsigned int bind (Inkscape::Extension::Print * module, const Geom::Affine *transform, float opacity); virtual unsigned int release (Inkscape::Extension::Print * module); virtual unsigned int comment (Inkscape::Extension::Print * module, const char * comment); virtual unsigned int image (Inkscape::Extension::Print * module, unsigned char *px, unsigned int w, unsigned int h, unsigned int rs, - const Geom::Matrix *transform, const SPStyle *style); + const Geom::Affine *transform, const SPStyle *style); */ }; diff --git a/src/extension/print.cpp b/src/extension/print.cpp index 2d4177d60..ad8c4c38d 100644 --- a/src/extension/print.cpp +++ b/src/extension/print.cpp @@ -61,7 +61,7 @@ Print::finish (void) } unsigned int -Print::bind (const Geom::Matrix *transform, float opacity) +Print::bind (const Geom::Affine *transform, float opacity) { return imp->bind (this, transform, opacity); } @@ -79,14 +79,14 @@ Print::comment (const char * comment) } unsigned int -Print::fill (Geom::PathVector const &pathv, const Geom::Matrix *ctm, const SPStyle *style, +Print::fill (Geom::PathVector const &pathv, const Geom::Affine *ctm, const SPStyle *style, const NRRect *pbox, const NRRect *dbox, const NRRect *bbox) { return imp->fill (this, pathv, ctm, style, pbox, dbox, bbox); } unsigned int -Print::stroke (Geom::PathVector const &pathv, const Geom::Matrix *transform, const SPStyle *style, +Print::stroke (Geom::PathVector const &pathv, const Geom::Affine *transform, const SPStyle *style, const NRRect *pbox, const NRRect *dbox, const NRRect *bbox) { return imp->stroke (this, pathv, transform, style, pbox, dbox, bbox); @@ -94,7 +94,7 @@ Print::stroke (Geom::PathVector const &pathv, const Geom::Matrix *transform, con unsigned int Print::image (unsigned char *px, unsigned int w, unsigned int h, unsigned int rs, - const Geom::Matrix *transform, const SPStyle *style) + const Geom::Affine *transform, const SPStyle *style) { return imp->image (this, px, w, h, rs, transform, style); } diff --git a/src/extension/print.h b/src/extension/print.h index 0f0435c0f..d5218aed8 100644 --- a/src/extension/print.h +++ b/src/extension/print.h @@ -41,18 +41,18 @@ public: unsigned int finish (void); /* Rendering methods */ - unsigned int bind (Geom::Matrix const *transform, + unsigned int bind (Geom::Affine const *transform, float opacity); unsigned int release (void); unsigned int comment (const char * comment); unsigned int fill (Geom::PathVector const &pathv, - Geom::Matrix const *ctm, + Geom::Affine const *ctm, SPStyle const *style, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox); unsigned int stroke (Geom::PathVector const &pathv, - Geom::Matrix const *transform, + Geom::Affine const *transform, SPStyle const *style, NRRect const *pbox, NRRect const *dbox, @@ -61,7 +61,7 @@ public: unsigned int w, unsigned int h, unsigned int rs, - Geom::Matrix const *transform, + Geom::Affine const *transform, SPStyle const *style); unsigned int text (char const *text, Geom::Point p, diff --git a/src/file.cpp b/src/file.cpp index bde985ea5..c041cb262 100644 --- a/src/file.cpp +++ b/src/file.cpp @@ -1039,7 +1039,7 @@ file_import(SPDocument *in_doc, const Glib::ustring &uri, // preserve parent and viewBox transformations // c2p is identity matrix at this point unless ensureUpToDate is called doc->ensureUpToDate(); - Geom::Matrix affine = SP_ROOT(doc->getRoot())->c2p * SP_ITEM(place_to_insert)->i2doc_affine().inverse(); + Geom::Affine affine = SP_ROOT(doc->getRoot())->c2p * SP_ITEM(place_to_insert)->i2doc_affine().inverse(); sp_selection_apply_affine(selection, desktop->dt2doc() * affine * desktop->doc2dt(), true, false); // move to mouse pointer diff --git a/src/filter-chemistry.cpp b/src/filter-chemistry.cpp index d6900b1f6..742ac7261 100644 --- a/src/filter-chemistry.cpp +++ b/src/filter-chemistry.cpp @@ -329,7 +329,7 @@ new_filter_simple_from_item (SPDocument *document, SPItem *item, const char *mod width = height = 0; } - Geom::Matrix i2d (item->i2d_affine () ); + Geom::Affine i2d (item->i2d_affine () ); return (new_filter_blend_gaussian_blur (document, mode, radius, i2d.descrim(), i2d.expansionX(), i2d.expansionY(), width, height)); } @@ -364,7 +364,7 @@ SPFilter *modify_filter_gaussian_blur_from_item(SPDocument *document, SPItem *it } // Determine the required standard deviation value - Geom::Matrix i2d (item->i2d_affine ()); + Geom::Affine i2d (item->i2d_affine ()); double expansion = i2d.descrim(); double stdDeviation = radius; if (expansion != 0) diff --git a/src/flood-context.cpp b/src/flood-context.cpp index dd26782a3..4bec2f292 100644 --- a/src/flood-context.cpp +++ b/src/flood-context.cpp @@ -395,7 +395,7 @@ inline static bool check_if_pixel_is_paintable(guchar *px, unsigned char *trace_ * \param transform The transform to apply to the final SVG path. * \param union_with_selection If true, merge the final SVG path with the current selection. */ -static void do_trace(bitmap_coords_info bci, guchar *trace_px, SPDesktop *desktop, Geom::Matrix transform, unsigned int min_x, unsigned int max_x, unsigned int min_y, unsigned int max_y, bool union_with_selection) { +static void do_trace(bitmap_coords_info bci, guchar *trace_px, SPDesktop *desktop, Geom::Affine transform, unsigned int min_x, unsigned int max_x, unsigned int min_y, unsigned int max_y, bool union_with_selection) { SPDocument *document = sp_desktop_document(desktop); unsigned char *trace_t; @@ -490,10 +490,10 @@ static void do_trace(bitmap_coords_info bci, guchar *trace_px, SPDesktop *deskto SP_ITEM(reprobj)->doWriteTransform(pathRepr, transform, NULL); // premultiply the item transform by the accumulated parent transform in the paste layer - Geom::Matrix local (SP_GROUP(desktop->currentLayer())->i2doc_affine()); + Geom::Affine local (SP_GROUP(desktop->currentLayer())->i2doc_affine()); if (!local.isIdentity()) { gchar const *t_str = pathRepr->attribute("transform"); - Geom::Matrix item_t (Geom::identity()); + Geom::Affine item_t (Geom::identity()); if (t_str) sp_svg_transform_read(t_str, &item_t); item_t *= local.inverse(); @@ -806,7 +806,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even origin[Geom::Y] = origin[Geom::Y] + (screen.height() * ((1 - padding) / 2)); Geom::Scale scale(zoom_scale, zoom_scale); - Geom::Matrix affine = scale * Geom::Translate(-origin * scale); + Geom::Affine affine = scale * Geom::Translate(-origin * scale); /* Create ArenaItems and set transform */ NRArenaItem *root = SP_ITEM(document->getRoot())->invoke_show( arena, dkey, SP_ITEM_SHOW_DISPLAY); @@ -1115,7 +1115,7 @@ static void sp_flood_do_flood_fill(SPEventContext *event_context, GdkEvent *even Geom::Point min_start = Geom::Point(min_x, min_y); affine = scale * Geom::Translate(-origin * scale - min_start); - Geom::Matrix inverted_affine = Geom::Matrix(affine).inverse(); + Geom::Affine inverted_affine = Geom::Affine(affine).inverse(); do_trace(bci, trace_px, desktop, inverted_affine, min_x, max_x, min_y, max_y, union_with_selection); diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index fb5dab648..d99a57208 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -317,7 +317,7 @@ SPGradient *sp_gradient_reset_to_userspace(SPGradient *gr, SPItem *item) sp_repr_set_svg_double(repr, "r", width/2); // we want it to be elliptic, not circular - Geom::Matrix squeeze = Geom::Translate (-center) * + Geom::Affine squeeze = Geom::Translate (-center) * Geom::Scale(1, height/width) * Geom::Translate (center); @@ -365,10 +365,10 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar // calculate the bbox of the item SP_OBJECT_DOCUMENT(item)->ensureUpToDate(); - Geom::Matrix bbox2user; + Geom::Affine bbox2user; Geom::OptRect bbox = item->getBounds(Geom::identity()); // we need "true" bbox without item_i2d_affine if ( bbox ) { - bbox2user = Geom::Matrix(bbox->dimensions()[Geom::X], 0, + bbox2user = Geom::Affine(bbox->dimensions()[Geom::X], 0, 0, bbox->dimensions()[Geom::Y], bbox->min()[Geom::X], bbox->min()[Geom::Y]); } else { @@ -390,7 +390,7 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar * gradient vector in user space due to application of the non-uniform scaling * transformation from bounding box space to user space. */ - Geom::Matrix skew = bbox2user; + Geom::Affine skew = bbox2user; double exp = skew.descrim(); skew[0] /= exp; skew[1] /= exp; @@ -409,7 +409,7 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar // Matrix to convert points to userspace coords; postmultiply by inverse of skew so // as to cancel it out when it's applied to the gradient during rendering - Geom::Matrix point_convert = bbox2user * skew.inverse(); + Geom::Affine point_convert = bbox2user * skew.inverse(); if (SP_IS_RADIALGRADIENT(gr)) { SPRadialGradient *rg = SP_RADIALGRADIENT(gr); @@ -462,7 +462,7 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar return gr; } -void sp_gradient_transform_multiply(SPGradient *gradient, Geom::Matrix postmul, bool set) +void sp_gradient_transform_multiply(SPGradient *gradient, Geom::Affine postmul, bool set) { #ifdef SP_GR_VERBOSE g_message("sp_gradient_transform_multiply(%p, , %d)", gradient, set); @@ -791,7 +791,7 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i, gradient = sp_gradient_convert_to_userspace (gradient, item, fill_or_stroke? "fill" : "stroke"); - Geom::Matrix i2d (item->i2d_affine ()); + Geom::Affine i2d (item->i2d_affine ()); Geom::Point p = p_w * i2d.inverse(); p *= (gradient->gradientTransform).inverse(); // now p is in gradient's original coordinates @@ -864,7 +864,7 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i, // prevent setting a radius too close to the center return; } - Geom::Matrix new_transform; + Geom::Affine new_transform; bool transform_set = false; switch (point_type) { @@ -899,12 +899,12 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i, double move_angle = Geom::atan2(p_w - c_w) - r1_angle; double move_stretch = Geom::L2(p_w - c_w) / Geom::L2(r1_w - c_w); - Geom::Matrix move = Geom::Matrix (Geom::Translate (-c_w)) * - Geom::Matrix (Geom::Rotate(-r1_angle)) * - Geom::Matrix (Geom::Scale(move_stretch, scale? move_stretch : 1)) * - Geom::Matrix (Geom::Rotate(r1_angle)) * - Geom::Matrix (Geom::Rotate(move_angle)) * - Geom::Matrix (Geom::Translate (c_w)); + Geom::Affine move = Geom::Affine (Geom::Translate (-c_w)) * + Geom::Affine (Geom::Rotate(-r1_angle)) * + Geom::Affine (Geom::Scale(move_stretch, scale? move_stretch : 1)) * + Geom::Affine (Geom::Rotate(r1_angle)) * + Geom::Affine (Geom::Rotate(move_angle)) * + Geom::Affine (Geom::Translate (c_w)); new_transform = gradient->gradientTransform * i2d * move * i2d.inverse(); transform_set = true; @@ -918,12 +918,12 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i, double move_angle = Geom::atan2(p_w - c_w) - r2_angle; double move_stretch = Geom::L2(p_w - c_w) / Geom::L2(r2_w - c_w); - Geom::Matrix move = Geom::Matrix (Geom::Translate (-c_w)) * - Geom::Matrix (Geom::Rotate(-r2_angle)) * - Geom::Matrix (Geom::Scale(move_stretch, scale? move_stretch : 1)) * - Geom::Matrix (Geom::Rotate(r2_angle)) * - Geom::Matrix (Geom::Rotate(move_angle)) * - Geom::Matrix (Geom::Translate (c_w)); + Geom::Affine move = Geom::Affine (Geom::Translate (-c_w)) * + Geom::Affine (Geom::Rotate(-r2_angle)) * + Geom::Affine (Geom::Scale(move_stretch, scale? move_stretch : 1)) * + Geom::Affine (Geom::Rotate(r2_angle)) * + Geom::Affine (Geom::Rotate(move_angle)) * + Geom::Affine (Geom::Translate (c_w)); new_transform = gradient->gradientTransform * i2d * move * i2d.inverse(); transform_set = true; @@ -1067,12 +1067,12 @@ Geom::Point sp_item_gradient_get_coords(SPItem *item, guint point_type, guint po SP_OBJECT_DOCUMENT(item)->ensureUpToDate(); Geom::OptRect bbox = item->getBounds(Geom::identity()); // we need "true" bbox without item_i2d_affine if (bbox) { - p *= Geom::Matrix(bbox->dimensions()[Geom::X], 0, + p *= Geom::Affine(bbox->dimensions()[Geom::X], 0, 0, bbox->dimensions()[Geom::Y], bbox->min()[Geom::X], bbox->min()[Geom::Y]); } } - p *= Geom::Matrix(gradient->gradientTransform) * (Geom::Matrix)item->i2d_affine(); + p *= Geom::Affine(gradient->gradientTransform) * (Geom::Affine)item->i2d_affine(); return from_2geom(p); } diff --git a/src/gradient-chemistry.h b/src/gradient-chemistry.h index 5e4a7b337..e0d9a1f46 100644 --- a/src/gradient-chemistry.h +++ b/src/gradient-chemistry.h @@ -64,7 +64,7 @@ guint32 average_color (guint32 c1, guint32 c2, gdouble p = 0.5); SPStop *sp_vector_add_stop (SPGradient *vector, SPStop* prev_stop, SPStop* next_stop, gfloat offset); -void sp_gradient_transform_multiply (SPGradient *gradient, Geom::Matrix postmul, bool set); +void sp_gradient_transform_multiply (SPGradient *gradient, Geom::Affine postmul, bool set); SPGradient * sp_item_gradient (SPItem *item, bool fill_or_stroke); void sp_item_gradient_set_coords (SPItem *item, guint point_type, guint point_i, Geom::Point p_desk, bool fill_or_stroke, bool write_repr, bool scale); diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp index cc9064451..4bf56f6c1 100644 --- a/src/helper/geom.cpp +++ b/src/helper/geom.cpp @@ -40,8 +40,8 @@ cubic_bbox (Geom::Coord x000, Geom::Coord y000, Geom::Coord x001, Geom::Coord y0 { Geom::Coord a, b, c, D; - bbox[0].extendTo(x111); - bbox[1].extendTo(y111); + bbox[0].expandTo(x111); + bbox[1].expandTo(y111); // It already contains (x000,y000) and (x111,y111) // All points of the Bezier lie in the convex hull of (x000,y000), (x001,y001), (x011,y011) and (x111,y111) @@ -83,7 +83,7 @@ cubic_bbox (Geom::Coord x000, Geom::Coord y000, Geom::Coord x001, Geom::Coord y0 if ((s > 0.0) && (s < 1.0)) { t = 1.0 - s; xttt = s * s * s * x000 + 3 * s * s * t * x001 + 3 * s * t * t * x011 + t * t * t * x111; - bbox[0].extendTo(xttt); + bbox[0].expandTo(xttt); } } } else { @@ -97,13 +97,13 @@ cubic_bbox (Geom::Coord x000, Geom::Coord y000, Geom::Coord x001, Geom::Coord y0 if ((s > 0.0) && (s < 1.0)) { t = 1.0 - s; xttt = s * s * s * x000 + 3 * s * s * t * x001 + 3 * s * t * t * x011 + t * t * t * x111; - bbox[0].extendTo(xttt); + bbox[0].expandTo(xttt); } s = (-b - d) / (2 * a); if ((s > 0.0) && (s < 1.0)) { t = 1.0 - s; xttt = s * s * s * x000 + 3 * s * s * t * x001 + 3 * s * t * t * x011 + t * t * t * x111; - bbox[0].extendTo(xttt); + bbox[0].expandTo(xttt); } } } @@ -122,7 +122,7 @@ cubic_bbox (Geom::Coord x000, Geom::Coord y000, Geom::Coord x001, Geom::Coord y0 if ((s > 0.0) && (s < 1.0)) { t = 1.0 - s; yttt = s * s * s * y000 + 3 * s * s * t * y001 + 3 * s * t * t * y011 + t * t * t * y111; - bbox[1].extendTo(yttt); + bbox[1].expandTo(yttt); } } } else { @@ -136,13 +136,13 @@ cubic_bbox (Geom::Coord x000, Geom::Coord y000, Geom::Coord x001, Geom::Coord y0 if ((s > 0.0) && (s < 1.0)) { t = 1.0 - s; yttt = s * s * s * y000 + 3 * s * s * t * y001 + 3 * s * t * t * y011 + t * t * t * y111; - bbox[1].extendTo(yttt); + bbox[1].expandTo(yttt); } s = (-b - d) / (2 * a); if ((s > 0.0) && (s < 1.0)) { t = 1.0 - s; yttt = s * s * s * y000 + 3 * s * s * t * y001 + 3 * s * t * t * y011 + t * t * t * y111; - bbox[1].extendTo(yttt); + bbox[1].expandTo(yttt); } } } @@ -150,14 +150,14 @@ cubic_bbox (Geom::Coord x000, Geom::Coord y000, Geom::Coord x001, Geom::Coord y0 } Geom::OptRect -bounds_fast_transformed(Geom::PathVector const & pv, Geom::Matrix const & t) +bounds_fast_transformed(Geom::PathVector const & pv, Geom::Affine const & t) { return bounds_exact_transformed(pv, t); //use this as it is faster for now! :) // return Geom::bounds_fast(pv * t); } Geom::OptRect -bounds_exact_transformed(Geom::PathVector const & pv, Geom::Matrix const & t) +bounds_exact_transformed(Geom::PathVector const & pv, Geom::Affine const & t) { if (pv.empty()) return Geom::OptRect(); @@ -354,7 +354,7 @@ geom_cubic_bbox_wind_distance (Geom::Coord x000, Geom::Coord y000, } static void -geom_curve_bbox_wind_distance(Geom::Curve const & c, Geom::Matrix const &m, +geom_curve_bbox_wind_distance(Geom::Curve const & c, Geom::Affine const &m, Geom::Point const &pt, Geom::Rect *bbox, int *wind, Geom::Coord *dist, Geom::Coord tolerance, Geom::Rect const *viewbox, @@ -417,7 +417,7 @@ geom_curve_bbox_wind_distance(Geom::Curve const & c, Geom::Matrix const &m, Returns bounding box in *bbox if bbox!=NULL. */ void -pathv_matrix_point_bbox_wind_distance (Geom::PathVector const & pathv, Geom::Matrix const &m, Geom::Point const &pt, +pathv_matrix_point_bbox_wind_distance (Geom::PathVector const & pathv, Geom::Affine const &m, Geom::Point const &pt, Geom::Rect *bbox, int *wind, Geom::Coord *dist, Geom::Coord tolerance, Geom::Rect const *viewbox) { @@ -507,7 +507,7 @@ void round_rectangle_outwards(Geom::Rect & rect) { namespace Geom { -bool transform_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coord const epsilon) { +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) && @@ -516,12 +516,12 @@ bool transform_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coor } -bool translate_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coord const 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); } -bool matrix_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coord const epsilon) { +bool matrix_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon) { return transform_equalp(m0, m1, epsilon) && translate_equalp(m0, m1, epsilon); } @@ -530,7 +530,7 @@ bool matrix_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coord c The following predefined objects are for reference and comparison. */ -Geom::Matrix GEOM_MATRIX_IDENTITY = Geom::identity(); +Geom::Affine GEOM_MATRIX_IDENTITY = Geom::identity(); /* Local Variables: diff --git a/src/helper/geom.h b/src/helper/geom.h index 73f95794f..b1015b185 100644 --- a/src/helper/geom.h +++ b/src/helper/geom.h @@ -16,10 +16,10 @@ #include #include -Geom::OptRect bounds_fast_transformed(Geom::PathVector const & pv, Geom::Matrix const & t); -Geom::OptRect bounds_exact_transformed(Geom::PathVector const & pv, Geom::Matrix const & t); +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); -void pathv_matrix_point_bbox_wind_distance ( Geom::PathVector const & pathv, Geom::Matrix const &m, Geom::Point const &pt, +void pathv_matrix_point_bbox_wind_distance ( Geom::PathVector const & pathv, Geom::Affine const &m, Geom::Point const &pt, Geom::Rect *bbox, int *wind, Geom::Coord *dist, Geom::Coord tolerance, Geom::Rect const *viewbox); @@ -31,12 +31,12 @@ void round_rectangle_outwards(Geom::Rect & rect); The following predefined objects are for reference and comparison. They are defined in helper/geom.cpp */ -extern Geom::Matrix GEOM_MATRIX_IDENTITY; +extern Geom::Affine GEOM_MATRIX_IDENTITY; namespace Geom{ -bool transform_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coord const epsilon); -bool translate_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coord const epsilon); -bool matrix_equalp(Geom::Matrix const &m0, Geom::Matrix const &m1, Geom::Coord const epsilon); +bool transform_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon); +bool translate_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon); +bool matrix_equalp(Geom::Affine const &m0, Geom::Affine const &m1, Geom::Coord const epsilon); } #endif // INKSCAPE_HELPER_GEOM_H diff --git a/src/helper/pixbuf-ops.cpp b/src/helper/pixbuf-ops.cpp index 7ce5c7dd2..acd2568af 100644 --- a/src/helper/pixbuf-ops.cpp +++ b/src/helper/pixbuf-ops.cpp @@ -132,7 +132,7 @@ sp_generate_internal_bitmap(SPDocument *doc, gchar const */*filename*/, origin[Geom::Y] = origin[Geom::Y] + (screen[Geom::Y].extent() * ((1 - padding) / 2)); Geom::Scale scale( (xdpi / PX_PER_IN), (ydpi / PX_PER_IN)); - Geom::Matrix affine = scale * Geom::Translate(-origin * scale); + Geom::Affine affine = scale * Geom::Translate(-origin * scale); /* Create ArenaItems and set transform */ NRArenaItem *root = SP_ITEM(doc->getRoot())->invoke_show( arena, dkey, SP_ITEM_SHOW_DISPLAY); diff --git a/src/helper/png-write.cpp b/src/helper/png-write.cpp index d3fe2771f..2df543c6d 100644 --- a/src/helper/png-write.cpp +++ b/src/helper/png-write.cpp @@ -442,7 +442,7 @@ sp_export_png_file(SPDocument *doc, gchar const *filename, * (2) a[5] = -a[3] * y1 */ - Geom::Matrix const affine(Geom::Translate(translation) + Geom::Affine const affine(Geom::Translate(translation) * Geom::Scale(width / area.width(), height / area.height())); diff --git a/src/knot-holder-entity.cpp b/src/knot-holder-entity.cpp index 005ca24c7..81d845e99 100644 --- a/src/knot-holder-entity.cpp +++ b/src/knot-holder-entity.cpp @@ -25,7 +25,7 @@ #include "snap.h" #include "desktop.h" #include "sp-namedview.h" -#include <2geom/matrix.h> +#include <2geom/affine.h> #include <2geom/transforms.h> int KnotHolderEntity::counter = 0; @@ -76,7 +76,7 @@ KnotHolderEntity::~KnotHolderEntity() void KnotHolderEntity::update_knot() { - Geom::Matrix const i2d(item->i2d_affine()); + Geom::Affine const i2d(item->i2d_affine()); Geom::Point dp(knot_get() * i2d); @@ -88,7 +88,7 @@ KnotHolderEntity::update_knot() Geom::Point KnotHolderEntity::snap_knot_position(Geom::Point const &p) { - Geom::Matrix const i2d (item->i2d_affine()); + Geom::Affine const i2d (item->i2d_affine()); Geom::Point s = p * i2d; SnapManager &m = desktop->namedview->snap_manager; @@ -102,7 +102,7 @@ KnotHolderEntity::snap_knot_position(Geom::Point const &p) Geom::Point KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape::Snapper::SnapConstraint const &constraint) { - Geom::Matrix const i2d (item->i2d_affine()); + Geom::Affine const i2d (item->i2d_affine()); Geom::Point s = p * i2d; SnapManager &m = desktop->namedview->snap_manager; @@ -125,13 +125,13 @@ KnotHolderEntity::snap_knot_position_constrained(Geom::Point const &p, Inkscape: static gdouble sp_pattern_extract_theta(SPPattern *pat) { - Geom::Matrix transf = pat->patternTransform; + Geom::Affine transf = pat->patternTransform; return Geom::atan2(transf.xAxis()); } static Geom::Point sp_pattern_extract_scale(SPPattern *pat) { - Geom::Matrix transf = pat->patternTransform; + Geom::Affine transf = pat->patternTransform; return Geom::Point( transf.expansionX(), transf.expansionY() ); } @@ -158,7 +158,7 @@ PatternKnotHolderEntityXY::knot_set(Geom::Point const &p, Geom::Point const &ori if (state) { Geom::Point const q = p_snapped - sp_pattern_extract_trans(pat); - item->adjust_pattern(Geom::Matrix(Geom::Translate(q))); + item->adjust_pattern(Geom::Affine(Geom::Translate(q))); } item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); @@ -181,7 +181,7 @@ PatternKnotHolderEntityAngle::knot_get() Geom::Point delta = Geom::Point(x,y); Geom::Point scale = sp_pattern_extract_scale(pat); gdouble theta = sp_pattern_extract_theta(pat); - delta = delta * Geom::Matrix(Geom::Scale(scale))*Geom::Matrix(Geom::Rotate(theta)); + delta = delta * Geom::Affine(Geom::Scale(scale))*Geom::Affine(Geom::Rotate(theta)); delta = delta + sp_pattern_extract_trans(pat); return delta; } @@ -204,7 +204,7 @@ PatternKnotHolderEntityAngle::knot_set(Geom::Point const &p, Geom::Point const & // get the scale from the current transform so we can keep it. Geom::Point scl = sp_pattern_extract_scale(pat); - Geom::Matrix rot = Geom::Matrix(Geom::Scale(scl)) * Geom::Matrix(Geom::Rotate(theta)); + Geom::Affine rot = Geom::Affine(Geom::Scale(scl)) * Geom::Affine(Geom::Rotate(theta)); Geom::Point const t = sp_pattern_extract_trans(pat); rot[4] = t[Geom::X]; rot[5] = t[Geom::Y]; @@ -237,7 +237,7 @@ PatternKnotHolderEntityScale::knot_set(Geom::Point const &p, Geom::Point const & scl = Geom::Scale(d[Geom::X] / pat_x, d[Geom::Y] / pat_y); } - Geom::Matrix rot = (Geom::Matrix)scl * Geom::Rotate(theta); + Geom::Affine rot = (Geom::Affine)scl * Geom::Rotate(theta); Geom::Point const t = sp_pattern_extract_trans(pat); rot[4] = t[Geom::X]; @@ -255,7 +255,7 @@ PatternKnotHolderEntityScale::knot_get() gdouble x = pattern_width(pat); gdouble y = pattern_height(pat); Geom::Point delta = Geom::Point(x,y); - Geom::Matrix a = pat->patternTransform; + Geom::Affine a = pat->patternTransform; a[4] = 0; a[5] = 0; delta = delta * a; diff --git a/src/knotholder.cpp b/src/knotholder.cpp index f5e28618e..5ff42a7c6 100644 --- a/src/knotholder.cpp +++ b/src/knotholder.cpp @@ -85,7 +85,7 @@ KnotHolder::~KnotHolder() { void KnotHolder::update_knots() { - Geom::Matrix const i2d(item->i2d_affine()); + Geom::Affine const i2d(item->i2d_affine()); for(std::list::iterator i = entity.begin(); i != entity.end(); ++i) { KnotHolderEntity *e = *i; diff --git a/src/libnr/nr-convert2geom.h b/src/libnr/nr-convert2geom.h index b4bca3516..2f87632fb 100644 --- a/src/libnr/nr-convert2geom.h +++ b/src/libnr/nr-convert2geom.h @@ -12,7 +12,7 @@ #include #include #include -#include <2geom/matrix.h> +#include <2geom/affine.h> #include <2geom/d2.h> #include <2geom/transforms.h> #include <2geom/point.h> @@ -24,11 +24,11 @@ inline NR::Point from_2geom(Geom::Point const & _pt) { return NR::Point(_pt[0], _pt[1]); } -inline Geom::Matrix to_2geom(NR::Matrix const & mat) { - Geom::Matrix mat2geom(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); +inline Geom::Affine to_2geom(NR::Matrix const & mat) { + Geom::Affine mat2geom(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); return mat2geom; } -inline NR::Matrix from_2geom(Geom::Matrix const & mat) { +inline NR::Matrix from_2geom(Geom::Affine const & mat) { NR::Matrix mat2geom(mat[0], mat[1], mat[2], mat[3], mat[4], mat[5]); return mat2geom; } diff --git a/src/libnr/nr-matrix.h b/src/libnr/nr-matrix.h index 206ff18b6..5d62dfafe 100644 --- a/src/libnr/nr-matrix.h +++ b/src/libnr/nr-matrix.h @@ -25,7 +25,7 @@ #include #include #include -#include <2geom/matrix.h> +#include <2geom/affine.h> namespace NR { @@ -78,7 +78,7 @@ class Matrix { } - Matrix(Geom::Matrix const &m) { + Matrix(Geom::Affine const &m) { NR::Coord *dest = _c; *dest++ = m[0]; @@ -231,8 +231,8 @@ class Matrix { return _c[i]; } - inline operator Geom::Matrix() const { - return Geom::Matrix(_c[0], _c[1], _c[2], _c[3], _c[4], _c[5]); + inline operator Geom::Affine() const { + return Geom::Affine(_c[0], _c[1], _c[2], _c[3], _c[4], _c[5]); } /** diff --git a/src/libnrtype/FontInstance.cpp b/src/libnrtype/FontInstance.cpp index bdf700346..6ba6440de 100644 --- a/src/libnrtype/FontInstance.cpp +++ b/src/libnrtype/FontInstance.cpp @@ -794,7 +794,7 @@ double font_instance::Advance(int glyph_id,bool vertical) } -raster_font* font_instance::RasterFont(const Geom::Matrix &trs, double stroke_width, bool vertical, JoinType stroke_join, ButtType stroke_cap, float /*miter_limit*/) +raster_font* font_instance::RasterFont(const Geom::Affine &trs, double stroke_width, bool vertical, JoinType stroke_join, ButtType stroke_cap, float /*miter_limit*/) { font_style nStyle; nStyle.transform=trs; diff --git a/src/libnrtype/Layout-TNG-OutIter.cpp b/src/libnrtype/Layout-TNG-OutIter.cpp index 0682e3570..4d461a486 100644 --- a/src/libnrtype/Layout-TNG-OutIter.cpp +++ b/src/libnrtype/Layout-TNG-OutIter.cpp @@ -343,7 +343,7 @@ Geom::Rect Layout::characterBoundingBox(iterator const &it, double *rotation) co return Geom::Rect(top_left, bottom_right); } -std::vector Layout::createSelectionShape(iterator const &it_start, iterator const &it_end, Geom::Matrix const &transform) const +std::vector Layout::createSelectionShape(iterator const &it_start, iterator const &it_end, Geom::Affine const &transform) const { std::vector quads; unsigned char_index; @@ -398,7 +398,7 @@ std::vector Layout::createSelectionShape(iterator const &it_start, continue; Geom::Point center_of_rotation((top_left[Geom::X] + bottom_right[Geom::X]) * 0.5, top_left[Geom::Y] + _spans[span_index].line_height.ascent); - Geom::Matrix total_transform = Geom::Translate(-center_of_rotation) * Geom::Rotate(char_rotation) * Geom::Translate(center_of_rotation) * transform; + Geom::Affine total_transform = Geom::Translate(-center_of_rotation) * Geom::Rotate(char_rotation) * Geom::Translate(center_of_rotation) * transform; for(int i = 0; i < 4; i ++) quads.push_back(char_box.corner(i) * total_transform); } diff --git a/src/libnrtype/Layout-TNG-Output.cpp b/src/libnrtype/Layout-TNG-Output.cpp index 10be0fc51..0d4d19a42 100644 --- a/src/libnrtype/Layout-TNG-Output.cpp +++ b/src/libnrtype/Layout-TNG-Output.cpp @@ -66,7 +66,7 @@ void Layout::LineHeight::max(LineHeight const &other) if (other.leading > leading) leading = other.leading; } -void Layout::_getGlyphTransformMatrix(int glyph_index, Geom::Matrix *matrix) const +void Layout::_getGlyphTransformMatrix(int glyph_index, Geom::Affine *matrix) const { Span const &span = _glyphs[glyph_index].span(this); double sin_rotation = sin(_glyphs[glyph_index].rotation); @@ -97,7 +97,7 @@ void Layout::show(NRArenaGroup *in_arena, NRRect const *paintbox) const nr_arena_glyphs_group_set_style(nr_group, text_source->style); while (glyph_index < (int)_glyphs.size() && _characters[_glyphs[glyph_index].in_character].in_span == span_index) { if (_characters[_glyphs[glyph_index].in_character].in_glyph != -1) { - Geom::Matrix glyph_matrix; + Geom::Affine glyph_matrix; _getGlyphTransformMatrix(glyph_index, &glyph_matrix); nr_arena_glyphs_group_add_component(nr_group, _spans[span_index].font, _glyphs[glyph_index].glyph, glyph_matrix); } @@ -108,7 +108,7 @@ void Layout::show(NRArenaGroup *in_arena, NRRect const *paintbox) const nr_arena_item_request_update(NR_ARENA_ITEM(in_arena), NR_ARENA_ITEM_STATE_ALL, FALSE); } -void Layout::getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform, int start, int length) const +void Layout::getBoundingBox(NRRect *bounding_box, Geom::Affine const &transform, int start, int length) const { for (unsigned glyph_index = 0 ; glyph_index < _glyphs.size() ; glyph_index++) { if (_characters[_glyphs[glyph_index].in_character].in_glyph == -1) continue; @@ -119,9 +119,9 @@ void Layout::getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform, if ((int) _glyphs[glyph_index].in_character > start + length) continue; } // this could be faster - Geom::Matrix glyph_matrix; + Geom::Affine glyph_matrix; _getGlyphTransformMatrix(glyph_index, &glyph_matrix); - Geom::Matrix total_transform = glyph_matrix; + Geom::Affine total_transform = glyph_matrix; total_transform *= transform; if(_glyphs[glyph_index].span(this).font) { Geom::OptRect glyph_rect = _glyphs[glyph_index].span(this).font->BBox(_glyphs[glyph_index].glyph); @@ -146,11 +146,11 @@ void Layout::getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform, void Layout::print(SPPrintContext *ctx, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox, - Geom::Matrix const &ctm) const + Geom::Affine const &ctm) const { if (_input_stream.empty()) return; - Geom::Matrix ctm_2geom(ctm); + Geom::Affine ctm_2geom(ctm); Direction block_progression = _blockProgression(); bool text_to_path = ctx->module->textToPath(); for (unsigned glyph_index = 0 ; glyph_index < _glyphs.size() ; ) { @@ -161,7 +161,7 @@ void Layout::print(SPPrintContext *ctx, glyph_index++; continue; } - Geom::Matrix glyph_matrix; + Geom::Affine glyph_matrix; Span const &span = _spans[_characters[_glyphs[glyph_index].in_character].in_span]; InputStreamTextSource const *text_source = static_cast(_input_stream[span.in_input_stream_item]); if (text_to_path || _path_fitted) { @@ -177,7 +177,7 @@ void Layout::print(SPPrintContext *ctx, glyph_index++; } else { Geom::Point g_pos(0,0); // all strings are output at (0,0) because we do the translation using the matrix - glyph_matrix = Geom::Scale(1.0, -1.0) * (Geom::Matrix)Geom::Rotate(_glyphs[glyph_index].rotation); + glyph_matrix = Geom::Scale(1.0, -1.0) * (Geom::Affine)Geom::Rotate(_glyphs[glyph_index].rotation); if (block_progression == LEFT_TO_RIGHT || block_progression == RIGHT_TO_LEFT) { glyph_matrix[4] = span.line(this).baseline_y + span.baseline_shift; // since we're outputting character codes, not glyphs, we want the character x @@ -237,7 +237,7 @@ void Layout::showGlyphs(CairoRenderContext *ctx) const Span const &span = _spans[_characters[_glyphs[glyph_index].in_character].in_span]; InputStreamTextSource const *text_source = static_cast(_input_stream[span.in_input_stream_item]); - Geom::Matrix glyph_matrix; + Geom::Affine glyph_matrix; _getGlyphTransformMatrix(glyph_index, &glyph_matrix); if (clip_mode) { Geom::PathVector const *pathv = span.font->PathVector(_glyphs[glyph_index].glyph); @@ -250,7 +250,7 @@ void Layout::showGlyphs(CairoRenderContext *ctx) const continue; } - Geom::Matrix font_matrix = glyph_matrix; + Geom::Affine font_matrix = glyph_matrix; font_matrix[4] = 0; font_matrix[5] = 0; @@ -292,7 +292,7 @@ void Layout::showGlyphs(CairoRenderContext *ctx) const && _characters[_glyphs[glyph_index].in_character].in_span == this_span_index); // remove vertical flip - Geom::Matrix flip_matrix; + Geom::Affine flip_matrix; flip_matrix.setIdentity(); flip_matrix[3] = -1.0; font_matrix = flip_matrix * font_matrix; @@ -547,7 +547,7 @@ SPCurve *Layout::convertToCurves(iterator const &from_glyph, iterator const &to_ GSList *cc = NULL; for (int glyph_index = from_glyph._glyph_index ; glyph_index < to_glyph._glyph_index ; glyph_index++) { - Geom::Matrix glyph_matrix; + Geom::Affine glyph_matrix; Span const &span = _glyphs[glyph_index].span(this); _getGlyphTransformMatrix(glyph_index, &glyph_matrix); @@ -576,7 +576,7 @@ SPCurve *Layout::convertToCurves(iterator const &from_glyph, iterator const &to_ return curve; } -void Layout::transform(Geom::Matrix const &transform) +void Layout::transform(Geom::Affine const &transform) { // this is all massively oversimplified // I can't actually think of anybody who'll want to use it at the moment, so it'll stay simple diff --git a/src/libnrtype/Layout-TNG-Scanline-Makers.cpp b/src/libnrtype/Layout-TNG-Scanline-Makers.cpp index 1bfde1f2d..7144f3876 100644 --- a/src/libnrtype/Layout-TNG-Scanline-Makers.cpp +++ b/src/libnrtype/Layout-TNG-Scanline-Makers.cpp @@ -85,9 +85,9 @@ Layout::ShapeScanlineMaker::ShapeScanlineMaker(Shape const *shape, Layout::Direc _shape_needs_freeing = true; temp_rotated_shape->Copy(const_cast(shape)); switch (block_progression) { - case BOTTOM_TO_TOP: temp_rotated_shape->Transform(Geom::Matrix(1.0, 0.0, 0.0, -1.0, 0.0, 0.0)); break; // reflect about x axis - case LEFT_TO_RIGHT: temp_rotated_shape->Transform(Geom::Matrix(0.0, 1.0, 1.0, 0.0, 0.0, 0.0)); break; // reflect about y=x - case RIGHT_TO_LEFT: temp_rotated_shape->Transform(Geom::Matrix(0.0, -1.0, 1.0, 0.0, 0.0, 0.0)); break; // reflect about y=-x + case BOTTOM_TO_TOP: temp_rotated_shape->Transform(Geom::Affine(1.0, 0.0, 0.0, -1.0, 0.0, 0.0)); break; // reflect about x axis + case LEFT_TO_RIGHT: temp_rotated_shape->Transform(Geom::Affine(0.0, 1.0, 1.0, 0.0, 0.0, 0.0)); break; // reflect about y=x + case RIGHT_TO_LEFT: temp_rotated_shape->Transform(Geom::Affine(0.0, -1.0, 1.0, 0.0, 0.0, 0.0)); break; // reflect about y=-x default: break; } _rotated_shape = new Shape; diff --git a/src/libnrtype/Layout-TNG.h b/src/libnrtype/Layout-TNG.h index ae2b9ae9a..5ed922969 100644 --- a/src/libnrtype/Layout-TNG.h +++ b/src/libnrtype/Layout-TNG.h @@ -18,7 +18,7 @@ #include #include #include <2geom/d2.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> #include #include #include @@ -337,7 +337,7 @@ public: \param transform The transform to be applied to the entire object prior to calculating its bounds. */ - void getBoundingBox(NRRect *bounding_box, Geom::Matrix const &transform, int start = -1, int length = -1) const; + void getBoundingBox(NRRect *bounding_box, Geom::Affine const &transform, int start = -1, int length = -1) const; /** Sends all the glyphs to the given print context. \param ctx I have @@ -346,7 +346,7 @@ public: \param bbox parameters \param ctm do yet */ - void print(SPPrintContext *ctx, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox, Geom::Matrix const &ctm) const; + void print(SPPrintContext *ctx, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox, Geom::Affine const &ctm) const; #ifdef HAVE_CAIRO_PDF /** Renders all the glyphs to the given Cairo rendering context. @@ -380,7 +380,7 @@ public: /** Apply the given transform to all the output presently stored in this object. This only transforms the glyph positions, The glyphs themselves will not be transformed. */ - void transform(Geom::Matrix const &transform); + void transform(Geom::Affine const &transform); //@} @@ -501,7 +501,7 @@ public: \a start to \a end and returns the union of these boxes. The return value is a list of zero or more quadrilaterals specified by a group of four points for each, thus size() is always a multiple of four. */ - std::vector createSelectionShape(iterator const &it_start, iterator const &it_end, Geom::Matrix const &transform) const; + std::vector createSelectionShape(iterator const &it_start, iterator const &it_end, Geom::Affine const &transform) const; /** Returns true if \a it points to a character which is a valid cursor position, as defined by Pango. */ @@ -746,7 +746,7 @@ private: /** gets the overall matrix that transforms the given glyph from local space to world space. */ - void _getGlyphTransformMatrix(int glyph_index, Geom::Matrix *matrix) const; + void _getGlyphTransformMatrix(int glyph_index, Geom::Affine *matrix) const; // loads of functions to drill down the object tree, all of them // annoyingly similar and all of them requiring predicate functors. diff --git a/src/libnrtype/font-instance.h b/src/libnrtype/font-instance.h index d52bd723f..33085858b 100644 --- a/src/libnrtype/font-instance.h +++ b/src/libnrtype/font-instance.h @@ -68,7 +68,7 @@ public: Geom::OptRect BBox(int glyph_id); // creates a rasterfont for the given style - raster_font* RasterFont(Geom::Matrix const &trs, double stroke_width, + raster_font* RasterFont(Geom::Affine const &trs, double stroke_width, bool vertical = false, JoinType stroke_join = join_straight, ButtType stroke_cap = butt_straight, float miter_limit = 4.0); // the dashes array in iStyle is copied diff --git a/src/libnrtype/font-style.h b/src/libnrtype/font-style.h index 20f03df86..abfac2737 100644 --- a/src/libnrtype/font-style.h +++ b/src/libnrtype/font-style.h @@ -1,7 +1,7 @@ #ifndef SEEN_LIBNRTYPE_FONT_STYLE_H #define SEEN_LIBNRTYPE_FONT_STYLE_H -#include <2geom/matrix.h> +#include <2geom/affine.h> #include #include @@ -9,7 +9,7 @@ // Different raster styles. struct font_style { - Geom::Matrix transform; // the ctm. contains the font-size + Geom::Affine transform; // the ctm. contains the font-size bool vertical; // should be rendered vertically or not? // good font support would take the glyph alternates for vertical mode, when present double stroke_width; // if 0, the glyph is filled; otherwise stroked diff --git a/src/livarot/Path.cpp b/src/livarot/Path.cpp index 66ec87274..1c04dbfb1 100644 --- a/src/livarot/Path.cpp +++ b/src/livarot/Path.cpp @@ -700,7 +700,7 @@ void Path::PointAndTangentAt(int piece, double at, Geom::Point &pos, Geom::Point } } -void Path::Transform(const Geom::Matrix &trans) +void Path::Transform(const Geom::Affine &trans) { for (std::vector::iterator i = descr_cmd.begin(); i != descr_cmd.end(); i++) { (*i)->transform(trans); diff --git a/src/livarot/Path.h b/src/livarot/Path.h index 19b1ab48c..b8041c63a 100644 --- a/src/livarot/Path.h +++ b/src/livarot/Path.h @@ -178,12 +178,12 @@ public: void DashPolylineFromStyle(SPStyle *style, float scale, float min_len); //utilitaire pour inkscape - void LoadPath(Geom::Path const &path, Geom::Matrix const &tr, bool doTransformation, bool append = false); - void LoadPathVector(Geom::PathVector const &pv, Geom::Matrix const &tr, bool doTransformation); + void LoadPath(Geom::Path const &path, Geom::Affine const &tr, bool doTransformation, bool append = false); + void LoadPathVector(Geom::PathVector const &pv, Geom::Affine const &tr, bool doTransformation); void LoadPathVector(Geom::PathVector const &pv); Geom::PathVector* MakePathVector(); - void Transform(const Geom::Matrix &trans); + void Transform(const Geom::Affine &trans); // decompose le chemin en ses sous-chemin // killNoSurf=true -> oublie les chemins de surface nulle diff --git a/src/livarot/PathCutting.cpp b/src/livarot/PathCutting.cpp index c279eb449..ba81864a8 100644 --- a/src/livarot/PathCutting.cpp +++ b/src/livarot/PathCutting.cpp @@ -24,7 +24,7 @@ #include "libnr/nr-convert2geom.h" #include <2geom/pathvector.h> #include <2geom/point.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> #include <2geom/sbasis-to-bezier.h> #include <2geom/curves.h> #include "../display/canvas-bpath.h" @@ -400,9 +400,9 @@ void Path::AddCurve(Geom::Curve const &c) } else if(Geom::SVGEllipticalArc const *svg_elliptical_arc = dynamic_cast(&c)) { ArcTo( svg_elliptical_arc->finalPoint(), - svg_elliptical_arc->ray(0), svg_elliptical_arc->ray(1), - svg_elliptical_arc->rotation_angle(), /// \todo check that this parameter is in radians (rotation_angle returns the angle in radians!) - svg_elliptical_arc->large_arc_flag(), !svg_elliptical_arc->sweep_flag() ); + svg_elliptical_arc->ray(Geom::X), svg_elliptical_arc->ray(Geom::Y), + svg_elliptical_arc->rotationAngle(), /// \todo check that this parameter is in radians (rotation_angle returns the angle in radians!) + svg_elliptical_arc->largeArc(), !svg_elliptical_arc->sweep() ); } else { //this case handles sbasis as well as all other curve types Geom::Path sbasis_path = Geom::cubicbezierpath_from_sbasis(c.toSBasis(), 0.1); @@ -416,7 +416,7 @@ void Path::AddCurve(Geom::Curve const &c) /** append is false by default: it means that the path should be resetted. If it is true, the path is not resetted and Geom::Path will be appended as a new path */ -void Path::LoadPath(Geom::Path const &path, Geom::Matrix const &tr, bool doTransformation, bool append) +void Path::LoadPath(Geom::Path const &path, Geom::Affine const &tr, bool doTransformation, bool append) { if (!append) { SetBackData (false); @@ -449,10 +449,10 @@ void Path::LoadPath(Geom::Path const &path, Geom::Matrix const &tr, bool doTran void Path::LoadPathVector(Geom::PathVector const &pv) { - LoadPathVector(pv, Geom::Matrix(), false); + LoadPathVector(pv, Geom::Affine(), false); } -void Path::LoadPathVector(Geom::PathVector const &pv, Geom::Matrix const &tr, bool doTransformation) +void Path::LoadPathVector(Geom::PathVector const &pv, Geom::Affine const &tr, bool doTransformation) { SetBackData (false); Reset(); diff --git a/src/livarot/PathSimplify.cpp b/src/livarot/PathSimplify.cpp index c04979fe9..7b04f028a 100644 --- a/src/livarot/PathSimplify.cpp +++ b/src/livarot/PathSimplify.cpp @@ -252,7 +252,7 @@ bool Path::FitCubic(Geom::Point const &start, PathDescrCubicTo &res, Geom::Point const end = res.p; // la matrice tNN - Geom::Matrix M(0, 0, 0, 0, 0, 0); + Geom::Affine M(0, 0, 0, 0, 0, 0); for (int i = 1; i < nbPt - 1; i++) { M[0] += N13(tk[i]) * N13(tk[i]); M[1] += N23(tk[i]) * N13(tk[i]); @@ -267,7 +267,7 @@ bool Path::FitCubic(Geom::Point const &start, PathDescrCubicTo &res, return false; } - Geom::Matrix const iM = M.inverse(); + Geom::Affine const iM = M.inverse(); M = iM; // phase 1: abcisses diff --git a/src/livarot/Shape.h b/src/livarot/Shape.h index 44dd43a4a..5649ff9e4 100644 --- a/src/livarot/Shape.h +++ b/src/livarot/Shape.h @@ -288,9 +288,9 @@ public: // create a graph that is an offseted version of the graph "of" // the offset is dec, with joins between edges of type "join" (see LivarotDefs.h) // the result is NOT a polygon; you need a subsequent call to ConvertToShape to get a real polygon - int MakeOffset(Shape *of, double dec, JoinType join, double miter, bool do_profile=false, double cx = 0, double cy = 0, double radius = 0, Geom::Matrix *i2doc = NULL); + int MakeOffset(Shape *of, double dec, JoinType join, double miter, bool do_profile=false, double cx = 0, double cy = 0, double radius = 0, Geom::Affine *i2doc = NULL); - int MakeTweak (int mode, Shape *a, double dec, JoinType join, double miter, bool do_profile, Geom::Point c, Geom::Point vector, double radius, Geom::Matrix *i2doc); + int MakeTweak (int mode, Shape *a, double dec, JoinType join, double miter, bool do_profile, Geom::Point c, Geom::Point vector, double radius, Geom::Affine *i2doc); int PtWinding(const Geom::Point px) const; // plus rapide int Winding(const Geom::Point px) const; @@ -314,7 +314,7 @@ public: void QuickScan(float &pos, int &curP, float to, FillRule directed, BitLigne* line, float step); void QuickScan(float &pos, int &curP, float to, AlphaLigne* line, float step); - void Transform(Geom::Matrix const &tr) + void Transform(Geom::Affine const &tr) {for(std::vector::iterator it=_pts.begin();it!=_pts.end();it++) it->x*=tr;} std::vector ebData; diff --git a/src/livarot/ShapeMisc.cpp b/src/livarot/ShapeMisc.cpp index d6ca8c533..7d23913c3 100644 --- a/src/livarot/ShapeMisc.cpp +++ b/src/livarot/ShapeMisc.cpp @@ -528,7 +528,7 @@ Shape::ConvertToFormeNested (Path * dest, int nbP, Path * *orig, int wildPath,in int -Shape::MakeTweak (int mode, Shape *a, double power, JoinType join, double miter, bool do_profile, Geom::Point c, Geom::Point vector, double radius, Geom::Matrix *i2doc) +Shape::MakeTweak (int mode, Shape *a, double power, JoinType join, double miter, bool do_profile, Geom::Point c, Geom::Point vector, double radius, Geom::Affine *i2doc) { Reset (0, 0); MakeBackData(a->_has_back_data); @@ -639,7 +639,7 @@ Shape::MakeTweak (int mode, Shape *a, double power, JoinType join, double miter, Geom::Point this_vec(0,0); if (mode == tweak_mode_push) { - Geom::Matrix tovec (*i2doc); + Geom::Affine tovec (*i2doc); tovec[4] = tovec[5] = 0; tovec = tovec.inverse(); this_vec = this_power * (vector * tovec) ; @@ -718,7 +718,7 @@ Shape::MakeTweak (int mode, Shape *a, double power, JoinType join, double miter, // you gotta be very careful with the join, as anything but the right one will fuck everything up // see PathStroke.cpp for the "right" joins int -Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_profile, double cx, double cy, double radius, Geom::Matrix *i2doc) +Shape::MakeOffset (Shape * a, double dec, JoinType join, double miter, bool do_profile, double cx, double cy, double radius, Geom::Affine *i2doc) { Reset (0, 0); MakeBackData(a->_has_back_data); diff --git a/src/livarot/ShapeSweep.cpp b/src/livarot/ShapeSweep.cpp index 00a0dd9a0..a0b9dac1d 100644 --- a/src/livarot/ShapeSweep.cpp +++ b/src/livarot/ShapeSweep.cpp @@ -2605,7 +2605,7 @@ Shape::TesteIntersection (Shape * ils, Shape * irs, int ilb, int irb, usvs = irs->pData[rSt].rx - ils->pData[lSt].rx; // pas sur de l'ordre des coefs de m - Geom::Matrix m(ldir[0], ldir[1], + Geom::Affine m(ldir[0], ldir[1], rdir[0], rdir[1], 0, 0); double det = m.det(); diff --git a/src/livarot/path-description.cpp b/src/livarot/path-description.cpp index 9ecfb99d6..95bd192d5 100644 --- a/src/livarot/path-description.cpp +++ b/src/livarot/path-description.cpp @@ -11,7 +11,7 @@ void PathDescrMoveTo::dumpSVG(Inkscape::SVGOStringStream& s, Geom::Point const & s << "M " << p[Geom::X] << " " << p[Geom::Y] << " "; } -void PathDescrMoveTo::transform(Geom::Matrix const& t) +void PathDescrMoveTo::transform(Geom::Affine const& t) { p = p * t; } @@ -32,7 +32,7 @@ PathDescr *PathDescrLineTo::clone() const return new PathDescrLineTo(*this); } -void PathDescrLineTo::transform(Geom::Matrix const& t) +void PathDescrLineTo::transform(Geom::Affine const& t) { p = p * t; } @@ -48,7 +48,7 @@ PathDescr *PathDescrBezierTo::clone() const return new PathDescrBezierTo(*this); } -void PathDescrBezierTo::transform(Geom::Matrix const& t) +void PathDescrBezierTo::transform(Geom::Affine const& t) { p = p * t; } @@ -64,7 +64,7 @@ PathDescr *PathDescrIntermBezierTo::clone() const return new PathDescrIntermBezierTo(*this); } -void PathDescrIntermBezierTo::transform(Geom::Matrix const& t) +void PathDescrIntermBezierTo::transform(Geom::Affine const& t) { p = p * t; } @@ -100,9 +100,9 @@ void PathDescrCubicTo::dump(std::ostream &s) const << end[Geom::X] << " " << end[Geom::Y] << " "; } -void PathDescrCubicTo::transform(Geom::Matrix const& t) +void PathDescrCubicTo::transform(Geom::Affine const& t) { - Geom::Matrix tr = t; + Geom::Affine tr = t; tr[4] = tr[5] = 0; start = start * tr; end = end * tr; @@ -127,7 +127,7 @@ PathDescr *PathDescrArcTo::clone() const return new PathDescrArcTo(*this); } -void PathDescrArcTo::transform(Geom::Matrix const& t) +void PathDescrArcTo::transform(Geom::Affine const& t) { p = p * t; } diff --git a/src/livarot/path-description.h b/src/livarot/path-description.h index 68088c27c..1d0dfb57e 100644 --- a/src/livarot/path-description.h +++ b/src/livarot/path-description.h @@ -37,7 +37,7 @@ struct PathDescr virtual void dumpSVG(Inkscape::SVGOStringStream &/*s*/, Geom::Point const &/*last*/) const {} virtual PathDescr *clone() const = 0; - virtual void transform(Geom::Matrix const &/*t*/) {} + virtual void transform(Geom::Affine const &/*t*/) {} virtual void dump(std::ostream &/*s*/) const {} int flags; // most notably contains the path command no @@ -53,7 +53,7 @@ struct PathDescrMoveTo : public PathDescr void dumpSVG(Inkscape::SVGOStringStream &s, Geom::Point const &last) const; PathDescr *clone() const; - void transform(Geom::Matrix const &t); + void transform(Geom::Affine const &t); void dump(std::ostream &s) const; Geom::Point p; @@ -66,7 +66,7 @@ struct PathDescrLineTo : public PathDescr void dumpSVG(Inkscape::SVGOStringStream &s, Geom::Point const &last) const; PathDescr *clone() const; - void transform(Geom::Matrix const &t); + void transform(Geom::Affine const &t); void dump(std::ostream &s) const; Geom::Point p; @@ -79,7 +79,7 @@ struct PathDescrBezierTo : public PathDescr : PathDescr(descr_bezierto), p(pp), nb(n) {} PathDescr *clone() const; - void transform(Geom::Matrix const &t); + void transform(Geom::Affine const &t); void dump(std::ostream &s) const; Geom::Point p; // the endpoint's coordinates @@ -95,7 +95,7 @@ struct PathDescrIntermBezierTo : public PathDescr : PathDescr(descr_interm_bezier), p(pp) {} PathDescr *clone() const; - void transform(Geom::Matrix const &t); + void transform(Geom::Affine const &t); void dump(std::ostream &s) const; Geom::Point p; // control point coordinates @@ -109,7 +109,7 @@ struct PathDescrCubicTo : public PathDescr void dumpSVG(Inkscape::SVGOStringStream &s, Geom::Point const &last) const; PathDescr *clone() const; - void transform(Geom::Matrix const &t); + void transform(Geom::Affine const &t); void dump(std::ostream &s) const; Geom::Point p; @@ -125,7 +125,7 @@ struct PathDescrArcTo : public PathDescr void dumpSVG(Inkscape::SVGOStringStream &s, Geom::Point const &last) const; PathDescr *clone() const; - void transform(Geom::Matrix const &t); + void transform(Geom::Affine const &t); void dump(std::ostream &s) const; Geom::Point p; diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 3ea57de23..f59a38fac 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -38,7 +38,7 @@ #include #include <2geom/sbasis-to-bezier.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> #include <2geom/pathvector.h> // include effects: @@ -668,7 +668,7 @@ Effect::resetDefaults(SPItem * /*item*/) } void -Effect::transform_multiply(Geom::Matrix const& postmul, bool set) +Effect::transform_multiply(Geom::Affine const& postmul, bool set) { // cycle through all parameters. Most parameters will not need transformation, but path and point params do. for (std::vector::iterator it = param_vector.begin(); it != param_vector.end(); it++) { diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h index 6acba000c..7fe4e9348 100644 --- a/src/live_effects/effect.h +++ b/src/live_effects/effect.h @@ -92,7 +92,7 @@ public: virtual void resetDefaults(SPItem * item); /// /todo: is this method really necessary? it causes UI inconsistensies... (johan) - virtual void transform_multiply(Geom::Matrix const& postmul, bool set); + virtual void transform_multiply(Geom::Affine const& postmul, bool set); // /TODO: providesKnotholder() is currently used as an indicator of whether a nodepath is // created for an item or not. When we allow both at the same time, this needs rethinking! diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp index dac34c5d4..38869cb97 100644 --- a/src/live_effects/lpe-copy_rotate.cpp +++ b/src/live_effects/lpe-copy_rotate.cpp @@ -101,12 +101,12 @@ LPECopyRotate::doEffect_pwd2 (Geom::Piecewise > const & p Piecewise > output; - Matrix pre = Translate(-origin) * Rotate(-deg_to_rad(starting_angle)); + Affine pre = Translate(-origin) * Rotate(-deg_to_rad(starting_angle)); for (int i = 0; i < num_copies; ++i) { // I first suspected the minus sign to be a bug in 2geom but it is // likely due to SVG's choice of coordinate system orientation (max) Rotate rot(-deg_to_rad(rotation_angle * i)); - Matrix t = pre * rot * Translate(origin); + Affine t = pre * rot * Translate(origin); output.concat(pwd2_in * t); } diff --git a/src/live_effects/lpe-curvestitch.cpp b/src/live_effects/lpe-curvestitch.cpp index 75218705c..80221e7b8 100644 --- a/src/live_effects/lpe-curvestitch.cpp +++ b/src/live_effects/lpe-curvestitch.cpp @@ -27,7 +27,7 @@ #include <2geom/bezier-to-sbasis.h> #include <2geom/sbasis-to-bezier.h> #include <2geom/d2.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> #include "ui/widget/scalar.h" #include "libnr/nr-values.h" @@ -120,7 +120,7 @@ LPECurveStitch::doEffect_path (std::vector const & path_in) scaling_y = prop_scale; } - Matrix transform; + Affine transform; transform.setXAxis( (end-start) / scaling ); transform.setYAxis( rot90(unit_vector(end-start)) * scaling_y); transform.setTranslation( start ); @@ -195,7 +195,7 @@ LPECurveStitch::resetDefaults(SPItem * item) * special casing is probably needed, because rotation should not be propagated to the strokepath. */ void -LPECurveStitch::transform_multiply(Geom::Matrix const& postmul, bool set) +LPECurveStitch::transform_multiply(Geom::Affine const& postmul, bool set) { // only take translations into account if (postmul.isTranslation()) { @@ -203,7 +203,7 @@ LPECurveStitch::transform_multiply(Geom::Matrix const& postmul, bool set) } else if (!scale_y_rel.get_value()) { // this basically means that for this transformation, the result should be the same as normal scaling the result path // don't know how to do this yet. -// Geom::Matrix new_postmul; +// Geom::Affine new_postmul; //new_postmul.setIdentity(); // new_postmul.setTranslation(postmul.translation()); // Effect::transform_multiply(new_postmul, set); diff --git a/src/live_effects/lpe-curvestitch.h b/src/live_effects/lpe-curvestitch.h index 8a8e43f2c..f46f2a5d2 100644 --- a/src/live_effects/lpe-curvestitch.h +++ b/src/live_effects/lpe-curvestitch.h @@ -32,7 +32,7 @@ public: virtual void resetDefaults(SPItem * item); - virtual void transform_multiply(Geom::Matrix const& postmul, bool set); + virtual void transform_multiply(Geom::Affine const& postmul, bool set); private: PathParam strokepath; diff --git a/src/live_effects/lpe-dynastroke.cpp b/src/live_effects/lpe-dynastroke.cpp index 0c97d50f0..97d49d83d 100644 --- a/src/live_effects/lpe-dynastroke.cpp +++ b/src/live_effects/lpe-dynastroke.cpp @@ -166,12 +166,12 @@ LPEDynastroke::doEffect_pwd2 (Geom::Piecewise > const & p std::cout<<"ellptic pen\n"; //FIXME: roundness=0??? double c = cos(angle_rad), s = sin(angle_rad); - Matrix rot,slant; - rot = Matrix(c, -s, s, c, 0, 0 ); - slant = Matrix(double(width)*roundness, 0, 0, double(width), 0, 0 ); + Affine rot,slant; + rot = Affine(c, -s, s, c, 0, 0 ); + slant = Affine(double(width)*roundness, 0, 0, double(width), 0, 0 ); Piecewise > nn = unitVector(v * ( rot * slant ) ); - slant = Matrix( 0,-roundness, 1, 0, 0, 0 ); - rot = Matrix(-s, -c, c, -s, 0, 0 ); + slant = Affine( 0,-roundness, 1, 0, 0, 0 ); + rot = Affine(-s, -c, c, -s, 0, 0 ); nn = nn * (slant * rot ); n1 = nn*double(width); diff --git a/src/live_effects/lpe-knot.cpp b/src/live_effects/lpe-knot.cpp index fef4e1f87..e45515a8e 100644 --- a/src/live_effects/lpe-knot.cpp +++ b/src/live_effects/lpe-knot.cpp @@ -95,7 +95,7 @@ findShadowedTime(Geom::Path const &patha, std::vector const &pt_and Point N = T.cw(); Point A = pt_and_dir[0]-3*width*T, B = A+6*width*T; - Matrix mat = from_basis( T, N, pt_and_dir[0] ); + Affine mat = from_basis( T, N, pt_and_dir[0] ); mat = mat.inverse(); Path p = patha * mat; @@ -611,7 +611,7 @@ LPEKnot::addCanvasIndicators(SPLPEItem */*lpeitem*/, std::vector #include <2geom/transforms.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> namespace Inkscape { namespace LivePathEffect { @@ -46,7 +46,7 @@ LPEMirrorSymmetry::doOnApply (SPLPEItem *lpeitem) using namespace Geom; SPItem *item = SP_ITEM(lpeitem); - Geom::Matrix t = item->i2d_affine(); + Geom::Affine t = item->i2d_affine(); Geom::Rect bbox = *item->getBounds(t); // fixme: what happens if getBounds does not return a valid rect? Point A(bbox.left(), bbox.bottom()); @@ -74,15 +74,15 @@ LPEMirrorSymmetry::doEffect_path (std::vector const & path_in) Geom::Point A(mline.front().initialPoint()); Geom::Point B(mline.back().finalPoint()); - Geom::Matrix m1(1.0, 0.0, 0.0, 1.0, A[0], A[1]); + Geom::Affine m1(1.0, 0.0, 0.0, 1.0, A[0], A[1]); double hyp = Geom::distance(A, B); double c = (B[0] - A[0]) / hyp; // cos(alpha) double s = (B[1] - A[1]) / hyp; // sin(alpha) - Geom::Matrix m2(c, -s, s, c, 0.0, 0.0); - Geom::Matrix sca(1.0, 0.0, 0.0, -1.0, 0.0, 0.0); + Geom::Affine m2(c, -s, s, c, 0.0, 0.0); + Geom::Affine sca(1.0, 0.0, 0.0, -1.0, 0.0, 0.0); - Geom::Matrix m = m1.inverse() * m2; + Geom::Affine m = m1.inverse() * m2; m = m * sca; m = m * m2.inverse(); m = m * m1; diff --git a/src/live_effects/lpe-patternalongpath.cpp b/src/live_effects/lpe-patternalongpath.cpp index 36f257333..bbcf9b1c3 100644 --- a/src/live_effects/lpe-patternalongpath.cpp +++ b/src/live_effects/lpe-patternalongpath.cpp @@ -230,7 +230,7 @@ LPEPatternAlongPath::doEffect_pwd2 (Geom::Piecewise > con } void -LPEPatternAlongPath::transform_multiply(Geom::Matrix const& postmul, bool set) +LPEPatternAlongPath::transform_multiply(Geom::Affine const& postmul, bool set) { // overriding the Effect class default method, disabling transform forwarding to the parameters. diff --git a/src/live_effects/lpe-patternalongpath.h b/src/live_effects/lpe-patternalongpath.h index 1c02f2c08..f48281090 100644 --- a/src/live_effects/lpe-patternalongpath.h +++ b/src/live_effects/lpe-patternalongpath.h @@ -32,7 +32,7 @@ public: virtual Geom::Piecewise > doEffect_pwd2 (Geom::Piecewise > const & pwd2_in); - virtual void transform_multiply(Geom::Matrix const& postmul, bool set); + virtual void transform_multiply(Geom::Affine const& postmul, bool set); PathParam pattern; private: diff --git a/src/live_effects/lpe-rough-hatches.cpp b/src/live_effects/lpe-rough-hatches.cpp index 76456cd87..055b63661 100644 --- a/src/live_effects/lpe-rough-hatches.cpp +++ b/src/live_effects/lpe-rough-hatches.cpp @@ -28,7 +28,7 @@ #include <2geom/bezier-to-sbasis.h> #include <2geom/sbasis-to-bezier.h> #include <2geom/d2.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> #include "ui/widget/scalar.h" #include "libnr/nr-values.h" @@ -309,12 +309,12 @@ LPERoughHatches::doEffect_pwd2 (Geom::Piecewise > const & } Point transformed_org = direction.getOrigin(); Piecewise tilter;//used to bend the hatches - Matrix bend_mat;//used to bend the hatches + Affine bend_mat;//used to bend the hatches if (do_bend.get_value()){ Point bend_dir = -rot90(unit_vector(bender.getVector())); double bend_amount = L2(bender.getVector()); - bend_mat = Matrix(-bend_dir[Y], bend_dir[X], bend_dir[X], bend_dir[Y],0,0); + bend_mat = Affine(-bend_dir[Y], bend_dir[X], bend_dir[X], bend_dir[Y],0,0); transformed_pwd2_in = transformed_pwd2_in * bend_mat; tilter = Piecewise(shift(Linear(-bend_amount),1)); OptRect bbox = bounds_exact( transformed_pwd2_in ); @@ -325,7 +325,7 @@ LPERoughHatches::doEffect_pwd2 (Geom::Piecewise > const & } hatch_dist = Geom::L2(direction.getVector())/5; Point hatches_dir = rot90(unit_vector(direction.getVector())); - Matrix mat(-hatches_dir[Y], hatches_dir[X], hatches_dir[X], hatches_dir[Y],0,0); + Affine mat(-hatches_dir[Y], hatches_dir[X], hatches_dir[X], hatches_dir[Y],0,0); transformed_pwd2_in = transformed_pwd2_in * mat; transformed_org *= mat; diff --git a/src/live_effects/lpe-sketch.cpp b/src/live_effects/lpe-sketch.cpp index f03bac811..9488da84a 100644 --- a/src/live_effects/lpe-sketch.cpp +++ b/src/live_effects/lpe-sketch.cpp @@ -343,7 +343,7 @@ LPESketch::doEffect_pwd2 (Geom::Piecewise > const & pwd2_ //TODO: put this 4 as a parameter in the UI... //TODO: what if with v=0? double l = tgtlength*(1-tgtlength_rdm)/v_t.length(); - double r = pow(v_t.length(),3)/cross(a_t,v_t); + double r = std::pow(v_t.length(),3)/cross(a_t,v_t); r = sqrt((2*fabs(r)-tgtscale)*tgtscale)/v_t.length(); l=(r #include <2geom/pathvector.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> #include <2geom/bezier-curve.h> #include <2geom/hvlinesegment.h> #include <2geom/isnan.h> diff --git a/src/live_effects/lpe-vonkoch.cpp b/src/live_effects/lpe-vonkoch.cpp index f52ee9f69..56d66d137 100644 --- a/src/live_effects/lpe-vonkoch.cpp +++ b/src/live_effects/lpe-vonkoch.cpp @@ -88,25 +88,25 @@ LPEVonKoch::doEffect_path (std::vector const & path_in) } //Collect transform matrices. - Matrix m0; + Affine m0; Geom::Path refpath = ref_path.get_pathvector().front(); Point A = refpath.pointAt(0); Point B = refpath.pointAt(refpath.size()); Point u = B-A; - m0 = Matrix(u[X], u[Y],-u[Y], u[X], A[X], A[Y]); + m0 = Affine(u[X], u[Y],-u[Y], u[X], A[X], A[Y]); //FIXME: a path is used as ref instead of 2 points to work around path/point param incompatibility bug. //Point u = refB-refA; - //m0 = Matrix(u[X], u[Y],-u[Y], u[X], refA[X], refA[Y]); + //m0 = Affine(u[X], u[Y],-u[Y], u[X], refA[X], refA[Y]); m0 = m0.inverse(); - std::vector transforms; + std::vector transforms; for (unsigned i=0; i=2){ @@ -118,7 +118,7 @@ LPEVonKoch::doEffect_path (std::vector const & path_in) v[X] = -u[Y]*sign; v[Y] = u[X]*sign; } - m = Matrix(u[X], u[Y],v[X], v[Y], p[X], p[Y]); + m = Affine(u[X], u[Y],v[X], v[Y], p[X], p[Y]); m = m0*m; transforms.push_back(m); } @@ -133,16 +133,16 @@ LPEVonKoch::doEffect_path (std::vector const & path_in) for (unsigned k = 0; k < path_in.size(); k++){ path_in_complexity+=path_in[k].size(); } - double complexity = pow(transforms.size(),nbgenerations)*path_in_complexity; + double complexity = std::pow(transforms.size(),nbgenerations)*path_in_complexity; if (drawall.get_value()){ int k = transforms.size(); if(k>1){ - complexity = (pow(k,nbgenerations+1)-1)/(k-1)*path_in_complexity; + complexity = (std::pow(k,nbgenerations+1)-1)/(k-1)*path_in_complexity; }else{ complexity = nbgenerations*k*path_in_complexity; } }else{ - complexity = pow(transforms.size(),nbgenerations)*path_in_complexity; + complexity = std::pow(transforms.size(),nbgenerations)*path_in_complexity; } if (complexity > double(maxComplexity)){ g_warning("VonKoch lpe's output too complex. Effect bypassed."); @@ -288,8 +288,8 @@ LPEVonKoch::resetDefaults(SPItem * item) refpaths.push_back(path); ref_path.set_new_value(refpaths, true); - paths.push_back(path * Matrix(1./3,0,0,1./3, A[X]*2./3, A[Y]*2./3 + boundingbox_Y.extent()/2)); - paths.push_back(path * Matrix(1./3,0,0,1./3, B[X]*2./3, B[Y]*2./3 + boundingbox_Y.extent()/2)); + paths.push_back(path * Affine(1./3,0,0,1./3, A[X]*2./3, A[Y]*2./3 + boundingbox_Y.extent()/2)); + paths.push_back(path * Affine(1./3,0,0,1./3, B[X]*2./3, B[Y]*2./3 + boundingbox_Y.extent()/2)); generator.set_new_value(paths, true); //FIXME: a path is used as ref instead of 2 points to work around path/point param incompatibility bug. @@ -300,8 +300,8 @@ LPEVonKoch::resetDefaults(SPItem * item) //std::vector paths; //Geom::Path path = Geom::Path( (Point) refA); //path.appendNew( (Point) refB ); - //paths.push_back(path * Matrix(1./3,0,0,1./3, refA[X]*2./3, refA[Y]*2./3 + boundingbox_Y.extent()/2)); - //paths.push_back(path * Matrix(1./3,0,0,1./3, refB[X]*2./3, refB[Y]*2./3 + boundingbox_Y.extent()/2)); + //paths.push_back(path * Affine(1./3,0,0,1./3, refA[X]*2./3, refA[Y]*2./3 + boundingbox_Y.extent()/2)); + //paths.push_back(path * Affine(1./3,0,0,1./3, refB[X]*2./3, refB[Y]*2./3 + boundingbox_Y.extent()/2)); //paths.push_back(path); //generator.set_new_value(paths, true); } diff --git a/src/live_effects/lpegroupbbox.cpp b/src/live_effects/lpegroupbbox.cpp index e6fc95f86..2678509a4 100644 --- a/src/live_effects/lpegroupbbox.cpp +++ b/src/live_effects/lpegroupbbox.cpp @@ -28,7 +28,7 @@ GroupBBoxEffect::original_bbox(SPLPEItem *lpeitem, bool absolute) // Get item bounding box SPItem* item = SP_ITEM(lpeitem); - Geom::Matrix transform; + Geom::Affine transform; if (absolute) { transform = item->i2doc_affine(); } diff --git a/src/live_effects/parameter/parameter.h b/src/live_effects/parameter/parameter.h index ff878e717..cee10bc70 100644 --- a/src/live_effects/parameter/parameter.h +++ b/src/live_effects/parameter/parameter.h @@ -67,7 +67,7 @@ public: virtual void param_editOncanvas(SPItem * /*item*/, SPDesktop * /*dt*/) {}; virtual void param_setup_nodepath(Inkscape::NodePath::Path */*np*/) {}; - virtual void param_transform_multiply(Geom::Matrix const& /*postmul*/, bool /*set*/) {}; + virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/) {}; Glib::ustring param_key; Inkscape::UI::Widget::Registry * param_wr; diff --git a/src/live_effects/parameter/path.cpp b/src/live_effects/parameter/path.cpp index 8d9b2376f..d652dfd0c 100644 --- a/src/live_effects/parameter/path.cpp +++ b/src/live_effects/parameter/path.cpp @@ -235,7 +235,7 @@ PathParam::addCanvasIndicators(SPLPEItem */*lpeitem*/, std::vector &hp_vec); - virtual void param_transform_multiply(Geom::Matrix const& /*postmul*/, bool /*set*/); + virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/); sigc::signal signal_path_pasted; sigc::signal signal_path_changed; diff --git a/src/live_effects/parameter/point.cpp b/src/live_effects/parameter/point.cpp index e7abb70ea..550a8517c 100644 --- a/src/live_effects/parameter/point.cpp +++ b/src/live_effects/parameter/point.cpp @@ -84,7 +84,7 @@ PointParam::param_newWidget(Gtk::Tooltips * /*tooltips*/) param_effect->getSPDoc() ) ); // TODO: fix to get correct desktop (don't use SP_ACTIVE_DESKTOP) SPDesktop *desktop = SP_ACTIVE_DESKTOP; - Geom::Matrix transf = desktop->doc2dt(); + Geom::Affine transf = desktop->doc2dt(); pointwdg->setTransform(transf); pointwdg->setValue( *this ); pointwdg->clearProgrammatically(); @@ -114,7 +114,7 @@ PointParam::param_set_and_write_new_value (Geom::Point newpoint) } void -PointParam::param_transform_multiply(Geom::Matrix const& postmul, bool /*set*/) +PointParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/) { param_set_and_write_new_value( (*this) * postmul ); } diff --git a/src/live_effects/parameter/point.h b/src/live_effects/parameter/point.h index ec61fcd88..2d4e942c0 100644 --- a/src/live_effects/parameter/point.h +++ b/src/live_effects/parameter/point.h @@ -45,7 +45,7 @@ public: void param_set_and_write_new_value(Geom::Point newpoint); - virtual void param_transform_multiply(Geom::Matrix const& /*postmul*/, bool /*set*/); + virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/); void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color); diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp index c20980193..9d43e8447 100644 --- a/src/live_effects/parameter/powerstrokepointarray.cpp +++ b/src/live_effects/parameter/powerstrokepointarray.cpp @@ -55,7 +55,7 @@ PowerStrokePointArrayParam::param_newWidget(Gtk::Tooltips * /*tooltips*/) param_effect->getSPDoc() ) ); // TODO: fix to get correct desktop (don't use SP_ACTIVE_DESKTOP) SPDesktop *desktop = SP_ACTIVE_DESKTOP; - Geom::Matrix transf = desktop->doc2dt(); + Geom::Affine transf = desktop->doc2dt(); pointwdg->setTransform(transf); pointwdg->setValue( *this ); pointwdg->clearProgrammatically(); @@ -71,7 +71,7 @@ PowerStrokePointArrayParam::param_newWidget(Gtk::Tooltips * /*tooltips*/) void -PowerStrokePointArrayParam::param_transform_multiply(Geom::Matrix const& postmul, bool /*set*/) +PowerStrokePointArrayParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/) { // param_set_and_write_new_value( (*this) * postmul ); } diff --git a/src/live_effects/parameter/powerstrokepointarray.h b/src/live_effects/parameter/powerstrokepointarray.h index 06d406dfe..d984a7de5 100644 --- a/src/live_effects/parameter/powerstrokepointarray.h +++ b/src/live_effects/parameter/powerstrokepointarray.h @@ -36,7 +36,7 @@ public: virtual Gtk::Widget * param_newWidget(Gtk::Tooltips * tooltips); - virtual void param_transform_multiply(Geom::Matrix const& /*postmul*/, bool /*set*/); + virtual void param_transform_multiply(Geom::Affine const& /*postmul*/, bool /*set*/); void set_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color); diff --git a/src/live_effects/parameter/vector.cpp b/src/live_effects/parameter/vector.cpp index 5496b52f2..9086ab376 100644 --- a/src/live_effects/parameter/vector.cpp +++ b/src/live_effects/parameter/vector.cpp @@ -112,9 +112,9 @@ VectorParam::set_and_write_new_values(Geom::Point const &new_origin, Geom::Point } void -VectorParam::param_transform_multiply(Geom::Matrix const& postmul, bool /*set*/) +VectorParam::param_transform_multiply(Geom::Affine const& postmul, bool /*set*/) { - set_and_write_new_values( origin * postmul, vector * postmul.without_translation() ); + set_and_write_new_values( origin * postmul, vector * postmul.withoutTranslation() ); } diff --git a/src/live_effects/parameter/vector.h b/src/live_effects/parameter/vector.h index a4c29d317..cb7094b7f 100644 --- a/src/live_effects/parameter/vector.h +++ b/src/live_effects/parameter/vector.h @@ -48,7 +48,7 @@ public: void set_and_write_new_values(Geom::Point const &new_origin, Geom::Point const &new_vector); - virtual void param_transform_multiply(Geom::Matrix const &postmul, bool set); + virtual void param_transform_multiply(Geom::Affine const &postmul, bool set); void set_vector_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color); void set_origin_oncanvas_looks(SPKnotShapeType shape, SPKnotModeType mode, guint32 color); diff --git a/src/lpe-tool-context.cpp b/src/lpe-tool-context.cpp index f25949296..d4c795656 100644 --- a/src/lpe-tool-context.cpp +++ b/src/lpe-tool-context.cpp @@ -426,7 +426,7 @@ lpetool_context_reset_limiting_bbox(SPLPEToolContext *lc) Geom::Point A, B; lpetool_get_limiting_bbox_corners(document, A, B); - Geom::Matrix doc2dt(lc->desktop->doc2dt()); + Geom::Affine doc2dt(lc->desktop->doc2dt()); A *= doc2dt; B *= doc2dt; diff --git a/src/marker.cpp b/src/marker.cpp index 0ec92a1ff..efbe27680 100644 --- a/src/marker.cpp +++ b/src/marker.cpp @@ -24,7 +24,7 @@ #include "libnr/nr-scale-matrix-ops.h" #include "libnr/nr-translate-matrix-ops.h" #include "libnr/nr-convert2geom.h" -#include <2geom/matrix.h> +#include <2geom/affine.h> #include "svg/svg.h" #include "display/nr-arena-group.h" #include "xml/repr.h" @@ -50,7 +50,7 @@ static Inkscape::XML::Node *sp_marker_write (SPObject *object, Inkscape::XML::Do static NRArenaItem *sp_marker_private_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags); static void sp_marker_private_hide (SPItem *item, unsigned int key); -static void sp_marker_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); +static void sp_marker_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); static void sp_marker_print (SPItem *item, SPPrintContext *ctx); static void sp_marker_view_remove (SPMarker *marker, SPMarkerView *view, unsigned int destroyitems); @@ -463,7 +463,7 @@ sp_marker_update (SPObject *object, SPCtx *ctx, guint flags) for (v = marker->views; v != NULL; v = v->next) { for (unsigned i = 0 ; i < v->items.size() ; i++) { if (v->items[i]) { - Geom::Matrix tmp = marker->c2p; + Geom::Affine tmp = marker->c2p; nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->items[i]), &tmp); } } @@ -557,7 +557,7 @@ sp_marker_private_hide (SPItem */*item*/, unsigned int /*key*/) * This routine is disabled to break propagation. */ static void -sp_marker_bbox(SPItem const *, NRRect *, Geom::Matrix const &, unsigned const) +sp_marker_bbox(SPItem const *, NRRect *, Geom::Affine const &, unsigned const) { /* Break propagation */ } @@ -619,7 +619,7 @@ sp_marker_show_dimension (SPMarker *marker, unsigned int key, unsigned int size) NRArenaItem * sp_marker_show_instance ( SPMarker *marker, NRArenaItem *parent, unsigned int key, unsigned int pos, - Geom::Matrix const &base, float linewidth) + Geom::Affine const &base, float linewidth) { for (SPMarkerView *v = marker->views; v != NULL; v = v->next) { if (v->key == key) { @@ -635,12 +635,12 @@ sp_marker_show_instance ( SPMarker *marker, NRArenaItem *parent, /* fixme: Position (Lauris) */ nr_arena_item_add_child (parent, v->items[pos], NULL); /* nr_arena_item_unref (v->items[pos]); */ - Geom::Matrix tmp = marker->c2p; + Geom::Affine tmp = marker->c2p; nr_arena_group_set_child_transform((NRArenaGroup *) v->items[pos], &tmp); } } if (v->items[pos]) { - Geom::Matrix m; + Geom::Affine m; if (marker->orient_auto) { m = base; } else { @@ -710,7 +710,7 @@ sp_marker_view_remove (SPMarker *marker, SPMarkerView *view, unsigned int destro delete view; } -const gchar *generate_marker(GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Matrix /*transform*/, Geom::Matrix move) +const gchar *generate_marker(GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine /*transform*/, Geom::Affine move) { Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *defsrepr = SP_DOCUMENT_DEFS(document)->getRepr(); @@ -735,7 +735,7 @@ const gchar *generate_marker(GSList *reprs, Geom::Rect bounds, SPDocument *docum Inkscape::XML::Node *node = (Inkscape::XML::Node *)(i->data); SPItem *copy = SP_ITEM(mark_object->appendChildRepr(node)); - Geom::Matrix dup_transform; + Geom::Affine dup_transform; if (!sp_svg_transform_read (node->attribute("transform"), &dup_transform)) dup_transform = Geom::identity(); dup_transform *= move; diff --git a/src/marker.h b/src/marker.h index f2d74a3a6..09461b3a1 100644 --- a/src/marker.h +++ b/src/marker.h @@ -27,7 +27,7 @@ class SPMarkerClass; class SPMarkerView; #include <2geom/rect.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> #include "svg/svg-length.h" #include "enums.h" #include "sp-item-group.h" @@ -61,7 +61,7 @@ struct SPMarker : public SPGroup { unsigned int aspect_clip : 1; /* Child to parent additional transform */ - Geom::Matrix c2p; + Geom::Affine c2p; /* Private views */ SPMarkerView *views; @@ -87,9 +87,9 @@ protected: void sp_marker_show_dimension (SPMarker *marker, unsigned int key, unsigned int size); NRArenaItem *sp_marker_show_instance (SPMarker *marker, NRArenaItem *parent, unsigned int key, unsigned int pos, - Geom::Matrix const &base, float linewidth); + Geom::Affine const &base, float linewidth); void sp_marker_hide (SPMarker *marker, unsigned int key); -const gchar *generate_marker (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Matrix transform, Geom::Matrix move); +const gchar *generate_marker (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move); #endif diff --git a/src/object-edit.cpp b/src/object-edit.cpp index 27e75afab..a683500c0 100644 --- a/src/object-edit.cpp +++ b/src/object-edit.cpp @@ -481,7 +481,7 @@ Box3DKnotHolderEntity::knot_set_generic(SPItem *item, unsigned int knot_id, Geom g_assert(item != NULL); SPBox3D *box = SP_BOX3D(item); - Geom::Matrix const i2d (item->i2d_affine ()); + Geom::Affine const i2d (item->i2d_affine ()); Box3D::Axis movement; if ((knot_id < 4) != (state & GDK_SHIFT_MASK)) { @@ -657,7 +657,7 @@ Box3DKnotHolderEntityCenter::knot_set(Geom::Point const &new_pos, Geom::Point co Geom::Point const s = snap_knot_position(new_pos); SPBox3D *box = SP_BOX3D(item); - Geom::Matrix const i2d (item->i2d_affine ()); + Geom::Affine const i2d (item->i2d_affine ()); box3d_set_center (SP_BOX3D(item), s * i2d, origin * i2d, !(state & GDK_SHIFT_MASK) ? Box3D::XY : Box3D::Z, state & GDK_CONTROL_MASK); diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index 43651f002..e123173a5 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -84,7 +84,7 @@ void Inkscape::ObjectSnapper::_findCandidates(SPObject* parent, bool const &first_point, Geom::Rect const &bbox_to_snap, bool const clip_or_mask, - Geom::Matrix const additional_affine) const // transformation of the item being clipped / masked + Geom::Affine const additional_affine) const // transformation of the item being clipped / masked { if (!ThisSnapperMightSnap()) { return; @@ -198,7 +198,7 @@ void Inkscape::ObjectSnapper::_collectNodes(Inkscape::SnapSourceType const &t, } for (std::vector::const_iterator i = _candidates->begin(); i != _candidates->end(); i++) { - //Geom::Matrix i2doc(Geom::identity()); + //Geom::Affine i2doc(Geom::identity()); SPItem *root_item = (*i).item; if (SP_IS_USE((*i).item)) { root_item = sp_use_root(SP_USE((*i).item)); @@ -378,7 +378,7 @@ void Inkscape::ObjectSnapper::_collectPaths(Geom::Point /*p*/, for (std::vector::const_iterator i = _candidates->begin(); i != _candidates->end(); i++) { /* Transform the requested snap point to this item's coordinates */ - Geom::Matrix i2doc(Geom::identity()); + Geom::Affine i2doc(Geom::identity()); SPItem *root_item = NULL; /* We might have a clone at hand, so make sure we get the root item */ if (SP_IS_USE((*i).item)) { diff --git a/src/object-snapper.h b/src/object-snapper.h index 6bde3dd39..6e3cc620f 100644 --- a/src/object-snapper.h +++ b/src/object-snapper.h @@ -71,7 +71,7 @@ private: bool const &first_point, Geom::Rect const &bbox_to_snap, bool const _clip_or_mask, - Geom::Matrix const additional_affine) const; + Geom::Affine const additional_affine) const; void _snapNodes(SnappedConstraints &sc, Inkscape::SnapCandidatePoint const &p, // in desktop coordinates diff --git a/src/persp3d.cpp b/src/persp3d.cpp index 74208444b..fbd782294 100644 --- a/src/persp3d.cpp +++ b/src/persp3d.cpp @@ -385,7 +385,7 @@ persp3d_update_with_point (Persp3DImpl *persp_impl, Proj::Axis const axis, Proj: } void -persp3d_apply_affine_transformation (Persp3D *persp, Geom::Matrix const &xform) { +persp3d_apply_affine_transformation (Persp3D *persp, Geom::Affine const &xform) { persp->perspective_impl->tmat *= xform; persp3d_update_box_reprs(persp); SP_OBJECT(persp)->updateRepr(SP_OBJECT_WRITE_EXT); diff --git a/src/persp3d.h b/src/persp3d.h index 44b6d2435..db4971635 100644 --- a/src/persp3d.h +++ b/src/persp3d.h @@ -74,7 +74,7 @@ void persp3d_toggle_VP (Persp3D *persp, Proj::Axis axis, bool set_undo = true); void persp3d_toggle_VPs (std::list, Proj::Axis axis); void persp3d_set_VP_state (Persp3D *persp, Proj::Axis axis, Proj::VPState state); void persp3d_rotate_VP (Persp3D *persp, Proj::Axis axis, double angle, bool alt_pressed); // angle is in degrees -void persp3d_apply_affine_transformation (Persp3D *persp, Geom::Matrix const &xform); +void persp3d_apply_affine_transformation (Persp3D *persp, Geom::Affine const &xform); void persp3d_add_box (Persp3D *persp, SPBox3D *box); void persp3d_remove_box (Persp3D *persp, SPBox3D *box); diff --git a/src/print.cpp b/src/print.cpp index e0601aa33..fe52ea6dd 100644 --- a/src/print.cpp +++ b/src/print.cpp @@ -27,14 +27,14 @@ /* Identity typedef */ -unsigned int sp_print_bind(SPPrintContext *ctx, Geom::Matrix const &transform, float opacity) +unsigned int sp_print_bind(SPPrintContext *ctx, Geom::Affine const &transform, float opacity) { - Geom::Matrix const ntransform(transform); + Geom::Affine const ntransform(transform); return sp_print_bind(ctx, &ntransform, opacity); } unsigned int -sp_print_bind(SPPrintContext *ctx, Geom::Matrix const *transform, float opacity) +sp_print_bind(SPPrintContext *ctx, Geom::Affine const *transform, float opacity) { return ctx->module->bind(transform, opacity); } @@ -52,14 +52,14 @@ sp_print_comment(SPPrintContext *ctx, char const *comment) } unsigned int -sp_print_fill(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Matrix const *ctm, SPStyle const *style, +sp_print_fill(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Affine const *ctm, SPStyle const *style, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox) { return ctx->module->fill(pathv, ctm, style, pbox, dbox, bbox); } unsigned int -sp_print_stroke(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Matrix const *ctm, SPStyle const *style, +sp_print_stroke(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Affine const *ctm, SPStyle const *style, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox) { return ctx->module->stroke(pathv, ctm, style, pbox, dbox, bbox); @@ -68,7 +68,7 @@ sp_print_stroke(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Matrix unsigned int sp_print_image_R8G8B8A8_N(SPPrintContext *ctx, guchar *px, unsigned int w, unsigned int h, unsigned int rs, - Geom::Matrix const *transform, SPStyle const *style) + Geom::Affine const *transform, SPStyle const *style) { return ctx->module->image(px, w, h, rs, transform, style); } diff --git a/src/print.h b/src/print.h index f566d4e31..70361fb14 100644 --- a/src/print.h +++ b/src/print.h @@ -21,18 +21,18 @@ struct SPPrintContext { Inkscape::Extension::Print *module; }; -unsigned int sp_print_bind(SPPrintContext *ctx, Geom::Matrix const &transform, float opacity); -unsigned int sp_print_bind(SPPrintContext *ctx, Geom::Matrix const *transform, float opacity); +unsigned int sp_print_bind(SPPrintContext *ctx, Geom::Affine const &transform, float opacity); +unsigned int sp_print_bind(SPPrintContext *ctx, Geom::Affine const *transform, float opacity); unsigned int sp_print_release(SPPrintContext *ctx); unsigned int sp_print_comment(SPPrintContext *ctx, char const *comment); -unsigned int sp_print_fill(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Matrix const *ctm, SPStyle const *style, +unsigned int sp_print_fill(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Affine const *ctm, SPStyle const *style, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox); -unsigned int sp_print_stroke(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Matrix const *transform, SPStyle const *style, +unsigned int sp_print_stroke(SPPrintContext *ctx, Geom::PathVector const &pathv, Geom::Affine const *transform, SPStyle const *style, NRRect const *pbox, NRRect const *dbox, NRRect const *bbox); unsigned int sp_print_image_R8G8B8A8_N(SPPrintContext *ctx, guchar *px, unsigned int w, unsigned int h, unsigned int rs, - Geom::Matrix const *transform, SPStyle const *style); + Geom::Affine const *transform, SPStyle const *style); unsigned int sp_print_text(SPPrintContext *ctx, char const *text, Geom::Point p, SPStyle const *style); diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index d63ee7e83..9acacf7d5 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -216,7 +216,7 @@ void SelectionHelper::selectPrev(SPDesktop *dt) * Copies repr and its inherited css style elements, along with the accumulated transform 'full_t', * then prepends the copy to 'clip'. */ -void sp_selection_copy_one(Inkscape::XML::Node *repr, Geom::Matrix full_t, GSList **clip, Inkscape::XML::Document* xml_doc) +void sp_selection_copy_one(Inkscape::XML::Node *repr, Geom::Affine full_t, GSList **clip, Inkscape::XML::Document* xml_doc) { Inkscape::XML::Node *copy = repr->duplicate(xml_doc); @@ -261,10 +261,10 @@ GSList *sp_selection_paste_impl(SPDocument *doc, SPObject *parent, GSList **clip Inkscape::XML::Node *copy = repr->duplicate(xml_doc); // premultiply the item transform by the accumulated parent transform in the paste layer - Geom::Matrix local(SP_ITEM(parent)->i2doc_affine()); + Geom::Affine local(SP_ITEM(parent)->i2doc_affine()); if (!local.isIdentity()) { gchar const *t_str = copy->attribute("transform"); - Geom::Matrix item_t(Geom::identity()); + Geom::Affine item_t(Geom::identity()); if (t_str) sp_svg_transform_read(t_str, &item_t); item_t *= local.inverse(); @@ -591,7 +591,7 @@ void sp_selection_group_impl(GSList *p, Inkscape::XML::Node *group, Inkscape::XM // At this point, current may already have no item, due to its being a clone whose original is already moved away // So we copy it artificially calculating the transform from its repr->attr("transform") and the parent transform gchar const *t_str = current->attribute("transform"); - Geom::Matrix item_t(Geom::identity()); + Geom::Affine item_t(Geom::identity()); if (t_str) sp_svg_transform_read(t_str, &item_t); item_t *= SP_ITEM(doc->getObjectByRepr(current->parent()))->i2doc_affine(); @@ -1303,7 +1303,7 @@ value of set_i2d==false is only used by seltrans when it's dragging objects live that case, items are already in the new position, but the repr is in the old, and this function then simply updates the repr from item->transform. */ -void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix const &affine, bool set_i2d, bool compensate) +void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine const &affine, bool set_i2d, bool compensate) { if (selection->isEmpty()) return; @@ -1403,26 +1403,26 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix cons SP_OBJECT(item)->readAttr( "transform" ); // calculate the matrix we need to apply to the clone to cancel its induced transform from its original - Geom::Matrix parent2dt = SP_ITEM(SP_OBJECT_PARENT(item))->i2d_affine(); - Geom::Matrix t = parent2dt * affine * parent2dt.inverse(); - Geom::Matrix t_inv = t.inverse(); - Geom::Matrix result = t_inv * item->transform * t; + Geom::Affine parent2dt = SP_ITEM(SP_OBJECT_PARENT(item))->i2d_affine(); + Geom::Affine t = parent2dt * affine * parent2dt.inverse(); + Geom::Affine t_inv = t.inverse(); + Geom::Affine result = t_inv * item->transform * t; if ((prefs_parallel || prefs_unmoved) && affine.isTranslation()) { // we need to cancel out the move compensation, too // find out the clone move, same as in sp_use_move_compensate - Geom::Matrix parent = sp_use_get_parent_transform(SP_USE(item)); - Geom::Matrix clone_move = parent.inverse() * t * parent; + Geom::Affine parent = sp_use_get_parent_transform(SP_USE(item)); + Geom::Affine clone_move = parent.inverse() * t * parent; if (prefs_parallel) { - Geom::Matrix move = result * clone_move * t_inv; + Geom::Affine move = result * clone_move * t_inv; item->doWriteTransform(SP_OBJECT_REPR(item), move, &move, compensate); } else if (prefs_unmoved) { //if (SP_IS_USE(sp_use_get_original(SP_USE(item)))) // clone_move = Geom::identity(); - Geom::Matrix move = result * clone_move; + Geom::Affine move = result * clone_move; item->doWriteTransform(SP_OBJECT_REPR(item), move, &t, compensate); } @@ -1433,7 +1433,7 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix cons } else { if (set_i2d) { - item->set_i2d_affine(item->i2d_affine() * (Geom::Matrix)affine); + item->set_i2d_affine(item->i2d_affine() * (Geom::Affine)affine); } item->doWriteTransform(SP_OBJECT_REPR(item), item->transform, NULL, compensate); } @@ -1483,7 +1483,7 @@ sp_selection_scale_absolute(Inkscape::Selection *selection, y1 - y0); Geom::Scale const scale( newSize * Geom::Scale(bbox->dimensions()).inverse() ); Geom::Translate const o2n(x0, y0); - Geom::Matrix const final( p2o * scale * o2n ); + Geom::Affine const final( p2o * scale * o2n ); sp_selection_apply_affine(selection, final); } @@ -1509,7 +1509,7 @@ void sp_selection_scale_relative(Inkscape::Selection *selection, Geom::Point con Geom::Translate const n2d(-align); Geom::Translate const d2n(align); - Geom::Matrix const final( n2d * scale * d2n ); + Geom::Affine const final( n2d * scale * d2n ); sp_selection_apply_affine(selection, final); } @@ -1519,7 +1519,7 @@ sp_selection_rotate_relative(Inkscape::Selection *selection, Geom::Point const & Geom::Translate const d2n(center); Geom::Translate const n2d(-center); Geom::Rotate const rotate(Geom::Rotate::from_degrees(angle_degrees)); - Geom::Matrix const final( Geom::Matrix(n2d) * rotate * d2n ); + Geom::Affine const final( Geom::Affine(n2d) * rotate * d2n ); sp_selection_apply_affine(selection, final); } @@ -1528,21 +1528,21 @@ sp_selection_skew_relative(Inkscape::Selection *selection, Geom::Point const &al { Geom::Translate const d2n(align); Geom::Translate const n2d(-align); - Geom::Matrix const skew(1, dy, + Geom::Affine const skew(1, dy, dx, 1, 0, 0); - Geom::Matrix const final( n2d * skew * d2n ); + Geom::Affine const final( n2d * skew * d2n ); sp_selection_apply_affine(selection, final); } void sp_selection_move_relative(Inkscape::Selection *selection, Geom::Point const &move, bool compensate) { - sp_selection_apply_affine(selection, Geom::Matrix(Geom::Translate(move)), true, compensate); + sp_selection_apply_affine(selection, Geom::Affine(Geom::Translate(move)), true, compensate); } void sp_selection_move_relative(Inkscape::Selection *selection, double dx, double dy) { - sp_selection_apply_affine(selection, Geom::Matrix(Geom::Translate(dx, dy))); + sp_selection_apply_affine(selection, Geom::Affine(Geom::Translate(dx, dy))); } /** @@ -2291,7 +2291,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply) // calculate the transform to be applied to objects to move them to 0,0 Geom::Point move_p = Geom::Point(0, doc->getHeight()) - *c; move_p[Geom::Y] = -move_p[Geom::Y]; - Geom::Matrix move = Geom::Matrix(Geom::Translate(move_p)); + Geom::Affine move = Geom::Affine(Geom::Translate(move_p)); GSList *items = g_slist_copy((GSList *) selection->itemList()); @@ -2300,7 +2300,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply) // bottommost object, after sorting SPObject *parent = SP_OBJECT_PARENT(items->data); - Geom::Matrix parent_transform(SP_ITEM(parent)->i2doc_affine()); + Geom::Affine parent_transform(SP_ITEM(parent)->i2doc_affine()); // remember the position of the first item gint pos = SP_OBJECT_REPR(items->data)->position(); @@ -2331,7 +2331,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply) prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); gchar const *mark_id = generate_marker(repr_copies, bounds, doc, - ( Geom::Matrix(Geom::Translate(desktop->dt2doc( + ( Geom::Affine(Geom::Translate(desktop->dt2doc( Geom::Point(r->min()[Geom::X], r->max()[Geom::Y])))) * parent_transform.inverse() ), @@ -2415,7 +2415,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply) // calculate the transform to be applied to objects to move them to 0,0 Geom::Point move_p = Geom::Point(0, doc->getHeight()) - (r->min() + Geom::Point(0, r->dimensions()[Geom::Y])); move_p[Geom::Y] = -move_p[Geom::Y]; - Geom::Matrix move = Geom::Matrix(Geom::Translate(move_p)); + Geom::Affine move = Geom::Affine(Geom::Translate(move_p)); GSList *items = g_slist_copy((GSList *) selection->itemList()); @@ -2424,7 +2424,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply) // bottommost object, after sorting SPObject *parent = SP_OBJECT_PARENT(items->data); - Geom::Matrix parent_transform(SP_ITEM(parent)->i2doc_affine()); + Geom::Affine parent_transform(SP_ITEM(parent)->i2doc_affine()); // remember the position of the first item gint pos = SP_OBJECT_REPR(items->data)->position(); @@ -2456,7 +2456,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply) prefs->setInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_UNMOVED); gchar const *pat_id = pattern_tile(repr_copies, bounds, doc, - ( Geom::Matrix(Geom::Translate(desktop->dt2doc(Geom::Point(r->min()[Geom::X], + ( Geom::Affine(Geom::Translate(desktop->dt2doc(Geom::Point(r->min()[Geom::X], r->max()[Geom::Y])))) * to_2geom(parent_transform.inverse()) ), parent_transform * move); @@ -2534,7 +2534,7 @@ void sp_selection_untile(SPDesktop *desktop) SPPattern *pattern = pattern_getroot(SP_PATTERN(server)); - Geom::Matrix pat_transform = to_2geom(pattern_patternTransform(SP_PATTERN(server))); + Geom::Affine pat_transform = to_2geom(pattern_patternTransform(SP_PATTERN(server))); pat_transform *= item->transform; for (SPObject *child = pattern->firstChild() ; child != NULL; child = child->next ) { @@ -2547,7 +2547,7 @@ void sp_selection_untile(SPDesktop *desktop) // this is needed to make sure the new item has curve (simply requestDisplayUpdate does not work) doc->ensureUpToDate(); - Geom::Matrix transform( i->transform * pat_transform ); + Geom::Affine transform( i->transform * pat_transform ); i->doWriteTransform(SP_OBJECT_REPR(i), transform); new_select = g_slist_prepend(new_select, i); @@ -2758,8 +2758,8 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop) } // Calculate the matrix that will be applied to the image so that it exactly overlaps the source objects - Geom::Matrix eek(SP_ITEM(parent_object)->i2d_affine()); - Geom::Matrix t; + Geom::Affine eek(SP_ITEM(parent_object)->i2d_affine()); + Geom::Affine t; double shift_x = bbox.x0; double shift_y = bbox.y1; @@ -2974,7 +2974,7 @@ void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_ SPItem *item = reinterpret_cast(i->data); // inverted object transform should be applied to a mask object, // as mask is calculated in user space (after applying transform) - Geom::Matrix maskTransform(item->transform.inverse()); + Geom::Affine maskTransform(item->transform.inverse()); GSList *mask_items_dup = NULL; for (GSList *mask_item = mask_items; NULL != mask_item; mask_item = mask_item->next) { @@ -3142,7 +3142,7 @@ void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) { items_to_select = g_slist_prepend(items_to_select, mask_item); // transform mask, so it is moved the same spot where mask was applied - Geom::Matrix transform(mask_item->transform); + Geom::Affine transform(mask_item->transform); transform *= (*it).second->transform; mask_item->doWriteTransform(SP_OBJECT_REPR(mask_item), transform); } diff --git a/src/selection-chemistry.h b/src/selection-chemistry.h index 65d1ba296..b3d64ae8e 100644 --- a/src/selection-chemistry.h +++ b/src/selection-chemistry.h @@ -93,7 +93,7 @@ void sp_selection_paste_size_separately(SPDesktop *desktop, bool apply_x, bool a void sp_selection_to_next_layer( SPDesktop *desktop, bool suppressDone = false ); void sp_selection_to_prev_layer( SPDesktop *desktop, bool suppressDone = false ); -void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix const &affine, bool set_i2d = true, bool compensate = true); +void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine const &affine, bool set_i2d = true, bool compensate = true); void sp_selection_remove_transform (SPDesktop *desktop); void sp_selection_scale_absolute (Inkscape::Selection *selection, double x0, double x1, double y0, double y1); void sp_selection_scale_relative(Inkscape::Selection *selection, Geom::Point const &align, Geom::Scale const &scale); diff --git a/src/selection.cpp b/src/selection.cpp index 9cef87076..79a71afbd 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -394,7 +394,7 @@ NRRect *Selection::boundsInDocument(NRRect *bbox, SPItem::BBoxType type) const { for ( GSList const *iter=items ; iter != NULL ; iter = iter->next ) { SPItem *item=SP_ITEM(iter->data); - Geom::Matrix i2doc(item->i2doc_affine()); + Geom::Affine i2doc(item->i2doc_affine()); item->invoke_bbox( bbox, i2doc, FALSE, type); } diff --git a/src/seltrans.cpp b/src/seltrans.cpp index b1d184986..848c0836a 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -419,18 +419,18 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s g_return_if_fail(_stamp_cache == NULL); } -void Inkscape::SelTrans::transform(Geom::Matrix const &rel_affine, Geom::Point const &norm) +void Inkscape::SelTrans::transform(Geom::Affine const &rel_affine, Geom::Point const &norm) { g_return_if_fail(_grabbed); g_return_if_fail(!_empty); - Geom::Matrix const affine( Geom::Translate(-norm) * rel_affine * Geom::Translate(norm) ); + Geom::Affine const affine( Geom::Translate(-norm) * rel_affine * Geom::Translate(norm) ); if (_show == SHOW_CONTENT) { // update the content for (unsigned i = 0; i < _items.size(); i++) { SPItem &item = *_items[i]; - Geom::Matrix const &prev_transform = _items_affines[i]; + Geom::Affine const &prev_transform = _items_affines[i]; item.set_i2d_affine(prev_transform * affine); } } else { @@ -509,10 +509,10 @@ void Inkscape::SelTrans::ungrab() if (_current_relative_affine.isTranslation()) { DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT, _("Move")); - } else if (_current_relative_affine.without_translation().isScale()) { + } else if (_current_relative_affine.withoutTranslation().isScale()) { DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT, _("Scale")); - } else if (_current_relative_affine.without_translation().isRotation()) { + } else if (_current_relative_affine.withoutTranslation().isRotation()) { DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT, _("Rotate")); } else { @@ -584,10 +584,10 @@ void Inkscape::SelTrans::stamp() SPItem *copy_item = (SPItem *) sp_desktop_document(_desktop)->getObjectByRepr(copy_repr); - Geom::Matrix const *new_affine; + Geom::Affine const *new_affine; if (_show == SHOW_OUTLINE) { - Geom::Matrix const i2d(original_item->i2d_affine()); - Geom::Matrix const i2dnew( i2d * _current_relative_affine ); + Geom::Affine const i2d(original_item->i2d_affine()); + Geom::Affine const i2dnew( i2d * _current_relative_affine ); copy_item->set_i2d_affine(i2dnew); new_affine = ©_item->transform; } else { @@ -1520,7 +1520,7 @@ void Inkscape::SelTrans::moveTo(Geom::Point const &xy, guint state) } } - Geom::Matrix const move((Geom::Translate(dxy))); + Geom::Affine const move((Geom::Translate(dxy))); Geom::Point const norm(0, 0); transform(move, norm); @@ -1557,7 +1557,7 @@ Geom::Point Inkscape::SelTrans::_getGeomHandlePos(Geom::Point const &visual_hand // Calculate the absolute affine while taking into account the scaling of the stroke width Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool transform_stroke = prefs->getBool("/options/transform/stroke", true); - Geom::Matrix abs_affine = get_scale_transform_with_stroke (*_bbox, _strokewidth, transform_stroke, + Geom::Affine abs_affine = get_scale_transform_with_stroke (*_bbox, _strokewidth, transform_stroke, new_bbox.min()[Geom::X], new_bbox.min()[Geom::Y], new_bbox.max()[Geom::X], new_bbox.max()[Geom::Y]); // Calculate the scaled geometrical bbox @@ -1591,7 +1591,7 @@ Geom::Scale Inkscape::calcScaleFactors(Geom::Point const &initial_point, Geom::P // Only for scaling/stretching Geom::Point Inkscape::SelTrans::_calcAbsAffineDefault(Geom::Scale const default_scale) { - Geom::Matrix abs_affine = Geom::Translate(-_origin) * Geom::Matrix(default_scale) * Geom::Translate(_origin); + Geom::Affine abs_affine = Geom::Translate(-_origin) * Geom::Affine(default_scale) * Geom::Translate(_origin); Geom::Point new_bbox_min = _approximate_bbox->min() * abs_affine; Geom::Point new_bbox_max = _approximate_bbox->max() * abs_affine; @@ -1614,7 +1614,7 @@ Geom::Point Inkscape::SelTrans::_calcAbsAffineDefault(Geom::Scale const default_ // Only for scaling/stretching Geom::Point Inkscape::SelTrans::_calcAbsAffineGeom(Geom::Scale const geom_scale) { - _relative_affine = Geom::Matrix(geom_scale); + _relative_affine = Geom::Affine(geom_scale); _absolute_affine = Geom::Translate(-_origin_for_specpoints) * _relative_affine * Geom::Translate(_origin_for_specpoints); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); diff --git a/src/seltrans.h b/src/seltrans.h index bb26aa2cb..d1a99f9d3 100644 --- a/src/seltrans.h +++ b/src/seltrans.h @@ -17,7 +17,7 @@ #include #include <2geom/point.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> #include <2geom/rect.h> #include "knot.h" #include "forward.h" @@ -55,7 +55,7 @@ public: void resetState(); void setCenter(Geom::Point const &p); void grab(Geom::Point const &p, gdouble x, gdouble y, bool show_handles, bool translating); - void transform(Geom::Matrix const &rel_affine, Geom::Point const &norm); + void transform(Geom::Affine const &rel_affine, Geom::Point const &norm); void ungrab(); void stamp(); void moveTo(Geom::Point const &xy, guint state); @@ -114,7 +114,7 @@ private: std::vector _items; std::vector _items_const; - std::vector _items_affines; + std::vector _items_affines; std::vector _items_centers; std::vector _snap_points; @@ -139,9 +139,9 @@ private: Geom::OptRect _geometric_bbox; gdouble _strokewidth; - Geom::Matrix _current_relative_affine; - Geom::Matrix _absolute_affine; - Geom::Matrix _relative_affine; + Geom::Affine _current_relative_affine; + Geom::Affine _absolute_affine; + Geom::Affine _relative_affine; /* According to Merriam - Webster's online dictionary * Affine: a transformation (as a translation, a rotation, or a uniform stretching) that carries straight * lines into straight lines and parallel lines into parallel lines but may alter distance between points diff --git a/src/snap-candidate.h b/src/snap-candidate.h index 772800be5..236f2497d 100644 --- a/src/snap-candidate.h +++ b/src/snap-candidate.h @@ -82,7 +82,7 @@ private: class SnapCandidateItem { public: - SnapCandidateItem(SPItem* item, bool clip_or_mask, Geom::Matrix additional_affine) + SnapCandidateItem(SPItem* item, bool clip_or_mask, Geom::Affine additional_affine) : item(item), clip_or_mask(clip_or_mask), additional_affine(additional_affine) {} ~SnapCandidateItem() {}; @@ -93,7 +93,7 @@ public: * 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 */ - Geom::Matrix additional_affine; + Geom::Affine additional_affine; } ; diff --git a/src/snapped-curve.cpp b/src/snapped-curve.cpp index 5deb4c449..25bde8105 100644 --- a/src/snapped-curve.cpp +++ b/src/snapped-curve.cpp @@ -56,7 +56,7 @@ Inkscape::SnappedCurve::~SnappedCurve() { } -Inkscape::SnappedPoint Inkscape::SnappedCurve::intersect(SnappedCurve const &curve, Geom::Point const &p, Geom::Matrix dt2doc) const +Inkscape::SnappedPoint Inkscape::SnappedCurve::intersect(SnappedCurve const &curve, Geom::Point const &p, Geom::Affine dt2doc) const { // Calculate the intersections of two curves, which are both within snapping range, and // return only the closest intersection @@ -125,7 +125,7 @@ bool getClosestCurve(std::list const &list, Inkscape::Sn } // search for the closest intersection of two snapped curves, which are both member of the same collection -bool getClosestIntersectionCS(std::list const &list, Geom::Point const &p, Inkscape::SnappedPoint &result, Geom::Matrix dt2doc) +bool getClosestIntersectionCS(std::list const &list, Geom::Point const &p, Inkscape::SnappedPoint &result, Geom::Affine dt2doc) { bool success = false; diff --git a/src/snapped-curve.h b/src/snapped-curve.h index 595f84411..ed04576df 100644 --- a/src/snapped-curve.h +++ b/src/snapped-curve.h @@ -26,7 +26,7 @@ public: SnappedCurve(); SnappedCurve(Geom::Point const &snapped_point, int num_path, int num_segm, Geom::Coord const &snapped_distance, Geom::Coord const &snapped_tolerance, bool const &always_snap, bool const &fully_constrained, Geom::Curve const *curve, SnapSourceType source, long source_num, SnapTargetType target, Geom::OptRect target_bbox); ~SnappedCurve(); - Inkscape::SnappedPoint intersect(SnappedCurve const &curve, Geom::Point const &p, Geom::Matrix dt2doc) const; //intersect with another SnappedCurve + Inkscape::SnappedPoint intersect(SnappedCurve const &curve, Geom::Point const &p, Geom::Affine dt2doc) const; //intersect with another SnappedCurve private: Geom::Curve const *_curve; @@ -37,7 +37,7 @@ private: } bool getClosestCurve(std::list const &list, Inkscape::SnappedCurve &result); -bool getClosestIntersectionCS(std::list const &list, Geom::Point const &p, Inkscape::SnappedPoint &result, Geom::Matrix dt2doc); +bool getClosestIntersectionCS(std::list const &list, Geom::Point const &p, Inkscape::SnappedPoint &result, Geom::Affine dt2doc); #endif /* !SEEN_SNAPPEDCURVE_H */ diff --git a/src/sp-clippath.cpp b/src/sp-clippath.cpp index 16368b9c6..4e6f41a70 100644 --- a/src/sp-clippath.cpp +++ b/src/sp-clippath.cpp @@ -187,7 +187,7 @@ void SPClipPath::update(SPObject *object, SPCtx *ctx, guint flags) SPClipPath *cp = SP_CLIPPATH(object); for (SPClipPathView *v = cp->display; v != NULL; v = v->next) { if (cp->clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) { - Geom::Matrix t(Geom::Scale(v->bbox.x1 - v->bbox.x0, v->bbox.y1 - v->bbox.y0)); + Geom::Affine t(Geom::Scale(v->bbox.x1 - v->bbox.x0, v->bbox.y1 - v->bbox.y0)); t[4] = v->bbox.x0; t[5] = v->bbox.y0; nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), &t); @@ -254,7 +254,7 @@ NRArenaItem *SPClipPath::show(NRArena *arena, unsigned int key) } if (clipPathUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) { - Geom::Matrix t(Geom::Scale(display->bbox.x1 - display->bbox.x0, display->bbox.y1 - display->bbox.y0)); + Geom::Affine t(Geom::Scale(display->bbox.x1 - display->bbox.x0, display->bbox.y1 - display->bbox.y0)); t[4] = display->bbox.x0; t[5] = display->bbox.y0; nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), &t); @@ -297,7 +297,7 @@ void SPClipPath::setBBox(unsigned int key, NRRect *bbox) } } -void SPClipPath::getBBox(NRRect *bbox, Geom::Matrix const &transform, unsigned const /*flags*/) +void SPClipPath::getBBox(NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/) { SPObject *i = 0; for (i = firstChild(); i && !SP_IS_ITEM(i); i = i->getNext()) { @@ -306,13 +306,13 @@ void SPClipPath::getBBox(NRRect *bbox, Geom::Matrix const &transform, unsigned c return; } - SP_ITEM(i)->invoke_bbox_full( bbox, Geom::Matrix(SP_ITEM(i)->transform) * transform, SPItem::GEOMETRIC_BBOX, FALSE); + SP_ITEM(i)->invoke_bbox_full( bbox, Geom::Affine(SP_ITEM(i)->transform) * transform, SPItem::GEOMETRIC_BBOX, FALSE); SPObject *i_start = i; while (i != NULL) { if (i != i_start) { NRRect i_box; - SP_ITEM(i)->invoke_bbox_full( &i_box, Geom::Matrix(SP_ITEM(i)->transform) * transform, SPItem::GEOMETRIC_BBOX, FALSE); + SP_ITEM(i)->invoke_bbox_full( &i_box, Geom::Affine(SP_ITEM(i)->transform) * transform, SPItem::GEOMETRIC_BBOX, FALSE); nr_rect_d_union (bbox, bbox, &i_box); } i = i->getNext(); @@ -355,7 +355,7 @@ sp_clippath_view_list_remove(SPClipPathView *list, SPClipPathView *view) } // Create a mask element (using passed elements), add it to -const gchar *SPClipPath::create (GSList *reprs, SPDocument *document, Geom::Matrix const* applyTransform) +const gchar *SPClipPath::create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform) { Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document)); @@ -372,7 +372,7 @@ const gchar *SPClipPath::create (GSList *reprs, SPDocument *document, Geom::Matr SPItem *item = SP_ITEM(clip_path_object->appendChildRepr(node)); if (NULL != applyTransform) { - Geom::Matrix transform (item->transform); + Geom::Affine transform (item->transform); transform *= (*applyTransform); item->doWriteTransform(SP_OBJECT_REPR(item), transform); } diff --git a/src/sp-clippath.h b/src/sp-clippath.h index a622df1f6..d3c650ca6 100644 --- a/src/sp-clippath.h +++ b/src/sp-clippath.h @@ -37,14 +37,14 @@ public: unsigned int clipPathUnits : 1; SPClipPathView *display; - static const gchar *create(GSList *reprs, SPDocument *document, Geom::Matrix const* applyTransform); + static const gchar *create(GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform); static GType sp_clippath_get_type(void); NRArenaItem *show(NRArena *arena, unsigned int key); void hide(unsigned int key); void setBBox(unsigned int key, NRRect *bbox); - void getBBox(NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); + void getBBox(NRRect *bbox, Geom::Affine const &transform, unsigned const flags); private: static void init(SPClipPath *clippath); diff --git a/src/sp-conn-end-pair.cpp b/src/sp-conn-end-pair.cpp index 5bce1a4f8..3cc022c39 100644 --- a/src/sp-conn-end-pair.cpp +++ b/src/sp-conn-end-pair.cpp @@ -90,7 +90,7 @@ sp_conn_end_pair_build(SPObject *object) static void -avoid_conn_transformed(Geom::Matrix const */*mp*/, SPItem *moved_item) +avoid_conn_transformed(Geom::Affine const */*mp*/, SPItem *moved_item) { SPPath *path = SP_PATH(moved_item); if (path->connEndPair.isAutoRoutingConn()) { @@ -217,7 +217,7 @@ SPConnEndPair::getEndpoints(Geom::Point endPts[]) const { SPCurve *curve = _path->original_curve ? _path->original_curve : _path->curve; SPItem *h2attItem[2]; getAttachedItems(h2attItem); - Geom::Matrix i2d = SP_ITEM(_path)->i2doc_affine(); + Geom::Affine i2d = SP_ITEM(_path)->i2doc_affine(); for (unsigned h = 0; h < 2; ++h) { if ( h2attItem[h] ) { @@ -407,7 +407,7 @@ SPConnEndPair::reroutePathFromLibavoid(void) recreateCurve( curve, _connRef, _connCurvature ); - Geom::Matrix doc2item = SP_ITEM(_path)->i2doc_affine().inverse(); + Geom::Affine doc2item = SP_ITEM(_path)->i2doc_affine().inverse(); curve->transform(doc2item); return true; diff --git a/src/sp-conn-end.cpp b/src/sp-conn-end.cpp index 07dd852f2..3cea95cc5 100644 --- a/src/sp-conn-end.cpp +++ b/src/sp-conn-end.cpp @@ -43,7 +43,7 @@ get_nearest_common_ancestor(SPObject const *const obj, SPItem const *const objs[ static bool try_get_intersect_point_with_item_recursive(Geom::PathVector& conn_pv, SPItem* item, - const Geom::Matrix& item_transform, double& intersect_pos) { + const Geom::Affine& item_transform, double& intersect_pos) { double initial_pos = intersect_pos; // if this is a group... @@ -96,7 +96,7 @@ static bool try_get_intersect_point_with_item_recursive(Geom::PathVector& conn_p // The transforms given should be to a common ancestor of both the path and item. // static bool try_get_intersect_point_with_item(SPPath* conn, SPItem* item, - const Geom::Matrix& item_transform, const Geom::Matrix& conn_transform, + const Geom::Affine& item_transform, const Geom::Affine& conn_transform, const bool at_start, double& intersect_pos) { // Copy the curve and apply transformations up to common ancestor. @@ -147,7 +147,7 @@ sp_conn_get_route_and_redraw(SPPath *const path, SPItem const *const path_item = SP_ITEM(path); SPObject const *const ancestor = get_nearest_common_ancestor(path_item, h2attItem); - Geom::Matrix const path2anc(i2anc_affine(path_item, ancestor)); + Geom::Affine const path2anc(i2anc_affine(path_item, ancestor)); // Set sensible values incase there the connector ends are not // attached to any shapes. @@ -157,7 +157,7 @@ sp_conn_get_route_and_redraw(SPPath *const path, SPConnEnd** _connEnd = path->connEndPair.getConnEnds(); for (unsigned h = 0; h < 2; ++h) { if (h2attItem[h] && _connEnd[h]->type == ConnPointDefault && _connEnd[h]->id == ConnPointPosCC) { - Geom::Matrix h2i2anc = i2anc_affine(h2attItem[h], ancestor); + Geom::Affine h2i2anc = i2anc_affine(h2attItem[h], ancestor); try_get_intersect_point_with_item(path, h2attItem[h], h2i2anc, path2anc, (h == 0), endPos[h]); } @@ -171,7 +171,7 @@ sp_conn_get_route_and_redraw(SPPath *const path, static void -sp_conn_end_shape_move(Geom::Matrix const */*mp*/, SPItem */*moved_item*/, +sp_conn_end_shape_move(Geom::Affine const */*mp*/, SPItem */*moved_item*/, SPPath *const path) { if (path->connEndPair.isAutoRoutingConn()) { diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp index ef58e4d6e..722271fda 100644 --- a/src/sp-ellipse.cpp +++ b/src/sp-ellipse.cpp @@ -253,7 +253,7 @@ static void sp_genericellipse_set_shape(SPShape *shape) curve->closepath(); } - Geom::Matrix aff = Geom::Scale(rx, ry) * Geom::Translate(ellipse->cx.computed, ellipse->cy.computed); + Geom::Affine aff = Geom::Scale(rx, ry) * Geom::Translate(ellipse->cx.computed, ellipse->cy.computed); curve->transform(aff); /* Reset the shape'scurve to the "original_curve" @@ -282,7 +282,7 @@ static void sp_genericellipse_snappoints(SPItem const *item, std::vectori2d_affine(); + Geom::Affine const i2d = item->i2d_affine(); // figure out if we have a slice, while guarding against rounding errors bool slice = false; diff --git a/src/sp-flowregion.cpp b/src/sp-flowregion.cpp index 680589b55..210f350b8 100644 --- a/src/sp-flowregion.cpp +++ b/src/sp-flowregion.cpp @@ -502,7 +502,7 @@ static void GetDest(SPObject* child,Shape **computed) if ( child == NULL ) return; SPCurve *curve=NULL; - Geom::Matrix tr_mat; + Geom::Affine tr_mat; SPObject* u_child=child; if ( SP_IS_USE(u_child) ) { diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp index 3af12064f..2db1d8787 100644 --- a/src/sp-flowtext.cpp +++ b/src/sp-flowtext.cpp @@ -46,7 +46,7 @@ static Inkscape::XML::Node *sp_flowtext_write(SPObject *object, Inkscape::XML::D static void sp_flowtext_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr); static void sp_flowtext_set(SPObject *object, unsigned key, gchar const *value); -static void sp_flowtext_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); +static void sp_flowtext_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); static void sp_flowtext_print(SPItem *item, SPPrintContext *ctx); static gchar *sp_flowtext_description(SPItem *item); static void sp_flowtext_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs); @@ -328,7 +328,7 @@ static Inkscape::XML::Node *sp_flowtext_write(SPObject *object, Inkscape::XML::D } static void -sp_flowtext_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const /*flags*/) +sp_flowtext_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/) { SPFlowtext *group = SP_FLOWTEXT(item); group->layout.getBoundingBox(bbox, transform); @@ -368,7 +368,7 @@ sp_flowtext_print(SPItem *item, SPPrintContext *ctx) dbox.y0 = 0.0; dbox.x1 = SP_OBJECT_DOCUMENT(item)->getWidth(); dbox.y1 = SP_OBJECT_DOCUMENT(item)->getHeight(); - Geom::Matrix const ctm (item->i2d_affine()); + Geom::Affine const ctm (item->i2d_affine()); group->layout.print(ctx, &pbox, &dbox, &bbox, ctm); } diff --git a/src/sp-gradient-fns.h b/src/sp-gradient-fns.h index 5e7e1d387..be2caf5b0 100644 --- a/src/sp-gradient-fns.h +++ b/src/sp-gradient-fns.h @@ -23,12 +23,12 @@ void sp_gradient_render_vector_block_rgba(SPGradient *gr, guchar *px, gint w, gi void sp_gradient_render_vector_block_rgb(SPGradient *gr, guchar *px, gint w, gint h, gint rs, gint pos, gint span, bool horizontal); /** Transforms to/from gradient position space in given environment */ -Geom::Matrix sp_gradient_get_g2d_matrix(SPGradient const *gr, Geom::Matrix const &ctm, +Geom::Affine sp_gradient_get_g2d_matrix(SPGradient const *gr, Geom::Affine const &ctm, Geom::Rect const &bbox); -Geom::Matrix sp_gradient_get_gs2d_matrix(SPGradient const *gr, Geom::Matrix const &ctm, +Geom::Affine sp_gradient_get_gs2d_matrix(SPGradient const *gr, Geom::Affine const &ctm, Geom::Rect const &bbox); -void sp_gradient_set_gs2d_matrix(SPGradient *gr, Geom::Matrix const &ctm, Geom::Rect const &bbox, - Geom::Matrix const &gs2d); +void sp_gradient_set_gs2d_matrix(SPGradient *gr, Geom::Affine const &ctm, Geom::Rect const &bbox, + Geom::Affine const &gs2d); #endif /* !SEEN_SP_GRADIENT_FNS_H */ diff --git a/src/sp-gradient-test.h b/src/sp-gradient-test.h index 5ab08467d..696072929 100644 --- a/src/sp-gradient-test.h +++ b/src/sp-gradient-test.h @@ -56,13 +56,13 @@ public: SP_OBJECT(gr)->document = _doc; SP_OBJECT(gr)->setKeyValue( SP_ATTR_GRADIENTTRANSFORM, "translate(5, 8)"); - TS_ASSERT_EQUALS( gr->gradientTransform, Geom::Matrix(Geom::Translate(5, 8)) ); + TS_ASSERT_EQUALS( gr->gradientTransform, Geom::Affine(Geom::Translate(5, 8)) ); SP_OBJECT(gr)->setKeyValue( SP_ATTR_GRADIENTTRANSFORM, ""); TS_ASSERT_EQUALS( gr->gradientTransform, Geom::identity() ); SP_OBJECT(gr)->setKeyValue( SP_ATTR_GRADIENTTRANSFORM, "rotate(90)"); - TS_ASSERT_EQUALS( gr->gradientTransform, Geom::Matrix(rotate_degrees(90)) ); + TS_ASSERT_EQUALS( gr->gradientTransform, Geom::Affine(rotate_degrees(90)) ); g_object_unref(gr); } @@ -79,10 +79,10 @@ public: SP_OBJECT(gr)->updateRepr(repr, SP_OBJECT_WRITE_ALL); { gchar const *tr = repr->attribute("gradientTransform"); - Geom::Matrix svd; + Geom::Affine svd; bool const valid = sp_svg_transform_read(tr, &svd); TS_ASSERT( valid ); - TS_ASSERT_EQUALS( svd, Geom::Matrix(rotate_degrees(90)) ); + TS_ASSERT_EQUALS( svd, Geom::Affine(rotate_degrees(90)) ); } g_object_unref(gr); @@ -93,14 +93,14 @@ public: { SPGradient *gr = static_cast(g_object_new(SP_TYPE_GRADIENT, NULL)); SP_OBJECT(gr)->document = _doc; - Geom::Matrix const grXform(2, 1, + Geom::Affine const grXform(2, 1, 1, 3, 4, 6); gr->gradientTransform = grXform; Geom::Rect const unit_rect(Geom::Point(0, 0), Geom::Point(1, 1)); { - Geom::Matrix const g2d(sp_gradient_get_g2d_matrix(gr, Geom::identity(), unit_rect)); - Geom::Matrix const gs2d(sp_gradient_get_gs2d_matrix(gr, Geom::identity(), unit_rect)); + Geom::Affine const g2d(sp_gradient_get_g2d_matrix(gr, Geom::identity(), unit_rect)); + Geom::Affine const gs2d(sp_gradient_get_gs2d_matrix(gr, Geom::identity(), unit_rect)); TS_ASSERT_EQUALS( g2d, Geom::identity() ); TS_ASSERT( Geom::matrix_equalp(gs2d, gr->gradientTransform * g2d, 1e-12) ); @@ -109,12 +109,12 @@ public: } gr->gradientTransform = grXform; - Geom::Matrix const funny(2, 3, + Geom::Affine const funny(2, 3, 4, 5, 6, 7); { - Geom::Matrix const g2d(sp_gradient_get_g2d_matrix(gr, funny, unit_rect)); - Geom::Matrix const gs2d(sp_gradient_get_gs2d_matrix(gr, funny, unit_rect)); + Geom::Affine const g2d(sp_gradient_get_g2d_matrix(gr, funny, unit_rect)); + Geom::Affine const gs2d(sp_gradient_get_gs2d_matrix(gr, funny, unit_rect)); TS_ASSERT_EQUALS( g2d, funny ); TS_ASSERT( Geom::matrix_equalp(gs2d, gr->gradientTransform * g2d, 1e-12) ); @@ -125,9 +125,9 @@ public: gr->gradientTransform = grXform; Geom::Rect const larger_rect(Geom::Point(5, 6), Geom::Point(8, 10)); { - Geom::Matrix const g2d(sp_gradient_get_g2d_matrix(gr, funny, larger_rect)); - Geom::Matrix const gs2d(sp_gradient_get_gs2d_matrix(gr, funny, larger_rect)); - TS_ASSERT_EQUALS( g2d, Geom::Matrix(3, 0, + Geom::Affine const g2d(sp_gradient_get_g2d_matrix(gr, funny, larger_rect)); + Geom::Affine const gs2d(sp_gradient_get_gs2d_matrix(gr, funny, larger_rect)); + TS_ASSERT_EQUALS( g2d, Geom::Affine(3, 0, 0, 4, 5, 6) * funny ); TS_ASSERT( Geom::matrix_equalp(gs2d, gr->gradientTransform * g2d, 1e-12) ); @@ -136,8 +136,8 @@ public: TS_ASSERT( Geom::matrix_equalp(gr->gradientTransform, grXform, 1e-12) ); SP_OBJECT(gr)->setKeyValue( SP_ATTR_GRADIENTUNITS, "userSpaceOnUse"); - Geom::Matrix const user_g2d(sp_gradient_get_g2d_matrix(gr, funny, larger_rect)); - Geom::Matrix const user_gs2d(sp_gradient_get_gs2d_matrix(gr, funny, larger_rect)); + Geom::Affine const user_g2d(sp_gradient_get_g2d_matrix(gr, funny, larger_rect)); + Geom::Affine const user_gs2d(sp_gradient_get_gs2d_matrix(gr, funny, larger_rect)); TS_ASSERT_EQUALS( user_g2d, funny ); TS_ASSERT( Geom::matrix_equalp(user_gs2d, gr->gradientTransform * user_g2d, 1e-12) ); } diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index 1b8f9a111..06008c083 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -493,7 +493,7 @@ void SPGradientImpl::setGradientAttr(SPObject *object, unsigned key, gchar const object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; case SP_ATTR_GRADIENTTRANSFORM: { - Geom::Matrix t; + Geom::Affine t; if (value && sp_svg_transform_read(value, &t)) { gr->gradientTransform = t; gr->gradientTransform_set = TRUE; @@ -1390,34 +1390,34 @@ sp_gradient_render_vector_block_rgb(SPGradient *gradient, guchar *buf, } } -Geom::Matrix -sp_gradient_get_g2d_matrix(SPGradient const *gr, Geom::Matrix const &ctm, Geom::Rect const &bbox) +Geom::Affine +sp_gradient_get_g2d_matrix(SPGradient const *gr, Geom::Affine const &ctm, Geom::Rect const &bbox) { if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { return ( Geom::Scale(bbox.dimensions()) * Geom::Translate(bbox.min()) - * Geom::Matrix(ctm) ); + * Geom::Affine(ctm) ); } else { return ctm; } } -Geom::Matrix -sp_gradient_get_gs2d_matrix(SPGradient const *gr, Geom::Matrix const &ctm, Geom::Rect const &bbox) +Geom::Affine +sp_gradient_get_gs2d_matrix(SPGradient const *gr, Geom::Affine const &ctm, Geom::Rect const &bbox) { if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { return ( gr->gradientTransform * Geom::Scale(bbox.dimensions()) * Geom::Translate(bbox.min()) - * Geom::Matrix(ctm) ); + * Geom::Affine(ctm) ); } else { return gr->gradientTransform * ctm; } } void -sp_gradient_set_gs2d_matrix(SPGradient *gr, Geom::Matrix const &ctm, - Geom::Rect const &bbox, Geom::Matrix const &gs2d) +sp_gradient_set_gs2d_matrix(SPGradient *gr, Geom::Affine const &ctm, + Geom::Rect const &bbox, Geom::Affine const &gs2d) { gr->gradientTransform = gs2d * ctm.inverse(); if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX ) { @@ -1444,8 +1444,8 @@ struct SPLGPainter { NRLGradientRenderer lgr; static SPPainter * painter_new(SPPaintServer *ps, - Geom::Matrix const &full_transform, - Geom::Matrix const &parent_transform, + Geom::Affine const &full_transform, + Geom::Affine const &parent_transform, NRRect const *bbox); }; @@ -1609,8 +1609,8 @@ sp_lineargradient_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inks * and end < 1. */ SPPainter * SPLGPainter::painter_new(SPPaintServer *ps, - Geom::Matrix const &full_transform, - Geom::Matrix const &/*parent_transform*/, + Geom::Affine const &full_transform, + Geom::Affine const &/*parent_transform*/, NRRect const *bbox) { SPLinearGradient *lg = SP_LINEARGRADIENT(ps); @@ -1634,26 +1634,26 @@ SPPainter * SPLGPainter::painter_new(SPPaintServer *ps, * or something similar. Originally I had 1023.9999 here - not sure * whether we have really to cut out ceil int (Lauris). */ - Geom::Matrix color2norm(Geom::identity()); - Geom::Matrix color2px; + Geom::Affine color2norm(Geom::identity()); + Geom::Affine color2px; if (gr->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { - Geom::Matrix norm2pos(Geom::identity()); + Geom::Affine norm2pos(Geom::identity()); /* BBox to user coordinate system */ - Geom::Matrix bbox2user(bbox->x1 - bbox->x0, 0, 0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); + Geom::Affine bbox2user(bbox->x1 - bbox->x0, 0, 0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); - Geom::Matrix color2pos = color2norm * norm2pos; - Geom::Matrix color2tpos = color2pos * gr->gradientTransform; - Geom::Matrix color2user = color2tpos * bbox2user; + Geom::Affine color2pos = color2norm * norm2pos; + Geom::Affine color2tpos = color2pos * gr->gradientTransform; + Geom::Affine color2user = color2tpos * bbox2user; color2px = color2user * full_transform; } else { /* Problem: What to do, if we have mixed lengths and percentages? */ /* Currently we do ignore percentages at all, but that is not good (lauris) */ - Geom::Matrix norm2pos(Geom::identity()); - Geom::Matrix color2pos = color2norm * norm2pos; - Geom::Matrix color2tpos = color2pos * gr->gradientTransform; + Geom::Affine norm2pos(Geom::identity()); + Geom::Affine color2pos = color2norm * norm2pos; + Geom::Affine color2tpos = color2pos * gr->gradientTransform; color2px = color2tpos * full_transform; } @@ -1721,8 +1721,8 @@ struct SPRGPainter { NRRGradientRenderer rgr; static SPPainter *painter_new(SPPaintServer *ps, - Geom::Matrix const &full_transform, - Geom::Matrix const &parent_transform, + Geom::Affine const &full_transform, + Geom::Affine const &parent_transform, NRRect const *bbox); }; @@ -1893,8 +1893,8 @@ sp_radialgradient_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inks * Create radial gradient context. */ SPPainter *SPRGPainter::painter_new(SPPaintServer *ps, - Geom::Matrix const &full_transform, - Geom::Matrix const &/*parent_transform*/, + Geom::Affine const &full_transform, + Geom::Affine const &/*parent_transform*/, NRRect const *bbox) { SPRadialGradient *rg = SP_RADIALGRADIENT(ps); @@ -1911,7 +1911,7 @@ SPPainter *SPRGPainter::painter_new(SPPaintServer *ps, rgp->rg = rg; - Geom::Matrix gs2px; + Geom::Affine gs2px; if (gr->units == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { /** \todo @@ -1920,9 +1920,9 @@ SPPainter *SPRGPainter::painter_new(SPPaintServer *ps, */ /* BBox to user coordinate system */ - Geom::Matrix bbox2user(bbox->x1 - bbox->x0, 0, 0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); + Geom::Affine bbox2user(bbox->x1 - bbox->x0, 0, 0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); - Geom::Matrix gs2user = gr->gradientTransform * bbox2user; + Geom::Affine gs2user = gr->gradientTransform * bbox2user; gs2px = gs2user * full_transform; } else { diff --git a/src/sp-gradient.h b/src/sp-gradient.h index fbcc4934e..b727c38ac 100644 --- a/src/sp-gradient.h +++ b/src/sp-gradient.h @@ -84,7 +84,7 @@ private: public: /** gradientTransform attribute */ - Geom::Matrix gradientTransform; + Geom::Affine gradientTransform; guint gradientTransform_set : 1; private: diff --git a/src/sp-image.cpp b/src/sp-image.cpp index ad9e79de2..b23c2e161 100644 --- a/src/sp-image.cpp +++ b/src/sp-image.cpp @@ -84,12 +84,12 @@ static void sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags); static void sp_image_modified (SPObject *object, unsigned int flags); static Inkscape::XML::Node *sp_image_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); -static void sp_image_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); +static void sp_image_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); static void sp_image_print (SPItem * item, SPPrintContext *ctx); static gchar * sp_image_description (SPItem * item); static void sp_image_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs); static NRArenaItem *sp_image_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags); -static Geom::Matrix sp_image_set_transform (SPItem *item, Geom::Matrix const &xform); +static Geom::Affine sp_image_set_transform (SPItem *item, Geom::Affine const &xform); static void sp_image_set_curve(SPImage *image); @@ -1078,7 +1078,7 @@ sp_image_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XM } static void -sp_image_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const /*flags*/) +sp_image_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/) { SPImage const &image = *SP_IMAGE(item); @@ -1107,7 +1107,7 @@ sp_image_print (SPItem *item, SPPrintContext *ctx) int rs = gdk_pixbuf_get_rowstride(image->pixbuf); int pixskip = gdk_pixbuf_get_n_channels(image->pixbuf) * gdk_pixbuf_get_bits_per_sample(image->pixbuf) / 8; - Geom::Matrix t; + Geom::Affine t; if (image->aspect_align == SP_ASPECT_NONE) { /* fixme: (Lauris) */ Geom::Translate tp(image->x.computed, image->y.computed); @@ -1359,7 +1359,7 @@ static void sp_image_snappoints(SPItem const *item, std::vectori2d_affine ()); + Geom::Affine const i2d (item->i2d_affine ()); p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x0, y0) * i2d, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER)); p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x0, y1) * i2d, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER)); p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(x1, y1) * i2d, Inkscape::SNAPSOURCE_CORNER, Inkscape::SNAPTARGET_CORNER)); @@ -1372,8 +1372,8 @@ static void sp_image_snappoints(SPItem const *item, std::vector MAGIC_EPSILON ) { diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index 30d085584..bdc9400cf 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -66,7 +66,7 @@ static void sp_group_modified (SPObject *object, guint flags); static Inkscape::XML::Node *sp_group_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); static void sp_group_set(SPObject *object, unsigned key, char const *value); -static void sp_group_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); +static void sp_group_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); static void sp_group_print (SPItem * item, SPPrintContext *ctx); static gchar * sp_group_description (SPItem * item); static NRArenaItem *sp_group_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags); @@ -278,7 +278,7 @@ static Inkscape::XML::Node * sp_group_write(SPObject *object, Inkscape::XML::Doc } static void -sp_group_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags) +sp_group_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags) { SP_GROUP(item)->group->calculateBBox(bbox, transform, flags); } @@ -408,8 +408,8 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) Inkscape::XML::Node *nrepr = SP_OBJECT_REPR (child)->duplicate(prepr->document()); // Merging transform - Geom::Matrix ctrans; - Geom::Matrix const g(gitem->transform); + Geom::Affine ctrans; + Geom::Affine const g(gitem->transform); if (SP_IS_USE(citem) && sp_use_get_original (SP_USE(citem)) && SP_OBJECT_PARENT (sp_use_get_original (SP_USE(citem))) == SP_OBJECT(group)) { // make sure a clone's effective transform is the same as was under group @@ -696,7 +696,7 @@ void CGroup::onModified(guint flags) { } } -void CGroup::calculateBBox(NRRect *bbox, Geom::Matrix const &transform, unsigned const flags) { +void CGroup::calculateBBox(NRRect *bbox, Geom::Affine const &transform, unsigned const flags) { Geom::OptRect dummy_bbox; @@ -705,7 +705,7 @@ void CGroup::calculateBBox(NRRect *bbox, Geom::Matrix const &transform, unsigned SPObject *o = SP_OBJECT (l->data); if (SP_IS_ITEM(o) && !SP_ITEM(o)->isHidden()) { SPItem *child = SP_ITEM(o); - Geom::Matrix const ct(to_2geom(child->transform) * transform); + Geom::Affine const ct(to_2geom(child->transform) * transform); child->invoke_bbox_full( dummy_bbox, ct, flags, FALSE); } l = g_slist_remove (l, o); diff --git a/src/sp-item-group.h b/src/sp-item-group.h index 932241a42..e2aeb8bc5 100644 --- a/src/sp-item-group.h +++ b/src/sp-item-group.h @@ -69,7 +69,7 @@ public: virtual void onChildRemoved(Inkscape::XML::Node *child); virtual void onUpdate(SPCtx *ctx, unsigned int flags); virtual void onModified(guint flags); - virtual void calculateBBox(NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); + virtual void calculateBBox(NRRect *bbox, Geom::Affine const &transform, unsigned const flags); virtual void onPrint(SPPrintContext *ctx); virtual void onOrderChanged(Inkscape::XML::Node *child, Inkscape::XML::Node *old_ref, Inkscape::XML::Node *new_ref); virtual gchar *getDescription(); diff --git a/src/sp-item-transform.cpp b/src/sp-item-transform.cpp index 81780220c..c3a95dc0f 100644 --- a/src/sp-item-transform.cpp +++ b/src/sp-item-transform.cpp @@ -21,10 +21,10 @@ sp_item_rotate_rel(SPItem *item, Geom::Rotate const &rotation) { Geom::Point center = item->getCenter(); Geom::Translate const s(item->getCenter()); - Geom::Matrix affine = Geom::Matrix(s).inverse() * Geom::Matrix(rotation) * Geom::Matrix(s); + Geom::Affine affine = Geom::Affine(s).inverse() * Geom::Affine(rotation) * Geom::Affine(s); // Rotate item. - item->set_i2d_affine(item->i2d_affine() * (Geom::Matrix)affine); + item->set_i2d_affine(item->i2d_affine() * (Geom::Affine)affine); // Use each item's own transform writer, consistent with sp_selection_apply_affine() item->doWriteTransform(SP_OBJECT_REPR(item), item->transform); @@ -52,8 +52,8 @@ sp_item_skew_rel (SPItem *item, double skewX, double skewY) Geom::Point center = item->getCenter(); Geom::Translate const s(item->getCenter()); - Geom::Matrix const skew(1, skewY, skewX, 1, 0, 0); - Geom::Matrix affine = Geom::Matrix(s).inverse() * skew * Geom::Matrix(s); + Geom::Affine const skew(1, skewY, skewX, 1, 0, 0); + Geom::Affine affine = Geom::Affine(s).inverse() * skew * Geom::Affine(s); item->set_i2d_affine(item->i2d_affine() * affine); item->doWriteTransform(SP_OBJECT_REPR(item), item->transform); @@ -79,16 +79,16 @@ preference value passed to it. Has to solve a quadratic equation to make sure the goal is met exactly and the stroke scaling is obeyed. */ -Geom::Matrix +Geom::Affine get_scale_transform_with_stroke (Geom::Rect const &bbox_param, gdouble strokewidth, bool transform_stroke, gdouble x0, gdouble y0, gdouble x1, gdouble y1) { Geom::Rect bbox (bbox_param); - Geom::Matrix p2o = Geom::Translate (-bbox.min()); - Geom::Matrix o2n = Geom::Translate (x0, y0); + Geom::Affine p2o = Geom::Translate (-bbox.min()); + Geom::Affine o2n = Geom::Translate (x0, y0); - Geom::Matrix scale = Geom::Scale (1, 1); // scale component - Geom::Matrix unbudge = Geom::Translate (0, 0); // move component to compensate for the drift caused by stroke width change + Geom::Affine scale = Geom::Scale (1, 1); // scale component + Geom::Affine unbudge = Geom::Translate (0, 0); // move component to compensate for the drift caused by stroke width change gdouble w0 = bbox[Geom::X].extent(); // will return a value >= 0, as required further down the road gdouble h0 = bbox[Geom::Y].extent(); @@ -97,11 +97,11 @@ get_scale_transform_with_stroke (Geom::Rect const &bbox_param, gdouble strokewid gdouble r0 = strokewidth; if (bbox.hasZeroArea()) { - Geom::Matrix move = Geom::Translate(x0 - bbox.min()[Geom::X], y0 - bbox.min()[Geom::Y]); + Geom::Affine move = Geom::Translate(x0 - bbox.min()[Geom::X], y0 - bbox.min()[Geom::Y]); return (move); // cannot scale from empty boxes at all, so only translate } - Geom::Matrix direct = Geom::Scale(w1 / w0, h1 / h0); + Geom::Affine direct = Geom::Scale(w1 / w0, h1 / h0); if (fabs(w0 - r0) < 1e-6 || fabs(h0 - r0) < 1e-6 || (!transform_stroke && (fabs(w1 - r0) < 1e-6 || fabs(h1 - r0) < 1e-6))) { return (p2o * direct * o2n); // can't solve the equation: one of the dimensions is equal to stroke width, so return the straightforward scaler @@ -120,7 +120,7 @@ get_scale_transform_with_stroke (Geom::Rect const &bbox_param, gdouble strokewid gdouble ratio_x = (w1 - r0) / (w0 - r0); gdouble ratio_y = (h1 - r0) / (h0 - r0); - Geom::Matrix direct_constant_r = Geom::Scale(flip_x * ratio_x, flip_y * ratio_y); + Geom::Affine direct_constant_r = Geom::Scale(flip_x * ratio_x, flip_y * ratio_y); if (transform_stroke && r0 != 0 && r0 != NR_HUGE) { // there's stroke, and we need to scale it // These coefficients are obtained from the assumption that scaling applies to the @@ -159,7 +159,7 @@ get_scale_transform_with_stroke (Geom::Rect const &bbox_param, gdouble strokewid } Geom::Rect -get_visual_bbox (Geom::OptRect const &initial_geom_bbox, Geom::Matrix const &abs_affine, gdouble const initial_strokewidth, bool const transform_stroke) +get_visual_bbox (Geom::OptRect const &initial_geom_bbox, Geom::Affine const &abs_affine, gdouble const initial_strokewidth, bool const transform_stroke) { g_assert(initial_geom_bbox); diff --git a/src/sp-item-transform.h b/src/sp-item-transform.h index 893ab5822..552b23e2f 100644 --- a/src/sp-item-transform.h +++ b/src/sp-item-transform.h @@ -9,8 +9,8 @@ void sp_item_scale_rel (SPItem *item, Geom::Scale const &scale); void sp_item_skew_rel (SPItem *item, double skewX, double skewY); void sp_item_move_rel(SPItem *item, Geom::Translate const &tr); -Geom::Matrix get_scale_transform_with_stroke (Geom::Rect const &bbox, gdouble strokewidth, bool transform_stroke, gdouble x0, gdouble y0, gdouble x1, gdouble y1); -Geom::Rect get_visual_bbox (Geom::OptRect const &initial_geom_bbox, Geom::Matrix const &abs_affine, gdouble const initial_strokewidth, bool const transform_stroke); +Geom::Affine get_scale_transform_with_stroke (Geom::Rect const &bbox, gdouble strokewidth, bool transform_stroke, gdouble x0, gdouble y0, gdouble x1, gdouble y1); +Geom::Rect get_visual_bbox (Geom::OptRect const &initial_geom_bbox, Geom::Affine const &abs_affine, gdouble const initial_strokewidth, bool const transform_stroke); #endif /* !SP_ITEM_TRANSFORM_H */ diff --git a/src/sp-item.cpp b/src/sp-item.cpp index 755ee0bf4..37bd0b19b 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -70,7 +70,7 @@ #include "util/find-last-if.h" #include "util/reverse-list.h" #include <2geom/rect.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> #include <2geom/transforms.h> #include "xml/repr.h" @@ -163,7 +163,7 @@ void SPItem::init() { new (&constraints) std::vector(); - new (&_transformed_signal) sigc::signal(); + new (&_transformed_signal) sigc::signal(); } bool SPItem::isVisibleAndUnlocked() const { @@ -440,7 +440,7 @@ void SPItem::sp_item_set(SPObject *object, unsigned key, gchar const *value) switch (key) { case SP_ATTR_TRANSFORM: { - Geom::Matrix t; + Geom::Affine t; if (value && sp_svg_transform_read(value, &t)) { item->set_item_transform(t); } else { @@ -707,7 +707,7 @@ Inkscape::XML::Node *SPItem::sp_item_write(SPObject *const object, Inkscape::XML * \return There is no guarantee that the return value will contain a rectangle. If this item does not have a boundingbox, it might well be empty. */ -Geom::OptRect SPItem::getBounds(Geom::Matrix const &transform, +Geom::OptRect SPItem::getBounds(Geom::Affine const &transform, SPItem::BBoxType type, unsigned int /*dkey*/) const { @@ -716,13 +716,13 @@ Geom::OptRect SPItem::getBounds(Geom::Matrix const &transform, return r; } -void SPItem::invoke_bbox( Geom::OptRect &bbox, Geom::Matrix const &transform, unsigned const clear, SPItem::BBoxType type) +void SPItem::invoke_bbox( Geom::OptRect &bbox, Geom::Affine const &transform, unsigned const clear, SPItem::BBoxType type) { invoke_bbox_full( bbox, transform, type, clear); } // DEPRECATED to phase out the use of NRRect in favor of Geom::OptRect -void SPItem::invoke_bbox( NRRect *bbox, Geom::Matrix const &transform, unsigned const clear, SPItem::BBoxType type) +void SPItem::invoke_bbox( NRRect *bbox, Geom::Affine const &transform, unsigned const clear, SPItem::BBoxType type) { invoke_bbox_full( bbox, transform, type, clear); } @@ -734,7 +734,7 @@ void SPItem::invoke_bbox( NRRect *bbox, Geom::Matrix const &transform, unsigned * \retval bbox Note that there is no guarantee that bbox will contain a rectangle when the * function returns. If this item does not have a boundingbox, this might well be empty. */ -void SPItem::invoke_bbox_full( Geom::OptRect &bbox, Geom::Matrix const &transform, unsigned const flags, unsigned const clear) const +void SPItem::invoke_bbox_full( Geom::OptRect &bbox, Geom::Affine const &transform, unsigned const flags, unsigned const clear) const { if (clear) { bbox = Geom::OptRect(); @@ -794,7 +794,7 @@ void SPItem::invoke_bbox_full( Geom::OptRect &bbox, Geom::Matrix const &transfor } // transform the expansions by the item's transform: - Geom::Matrix i2d(i2d_affine ()); + Geom::Affine i2d(i2d_affine ()); dx0 *= i2d.expansionX(); dx1 *= i2d.expansionX(); dy0 *= i2d.expansionY(); @@ -838,7 +838,7 @@ void SPItem::invoke_bbox_full( Geom::OptRect &bbox, Geom::Matrix const &transfor * unions the resulting bbox with \a bbox. If \a clear is true, empties \a bbox first. Passes the * transform and the flags to the actual bbox methods. Note that many of subclasses (e.g. groups, * clones), in turn, call this function in their bbox methods. */ -void SPItem::invoke_bbox_full( NRRect *bbox, Geom::Matrix const &transform, unsigned const flags, unsigned const clear) +void SPItem::invoke_bbox_full( NRRect *bbox, Geom::Affine const &transform, unsigned const flags, unsigned const clear) { g_assert(bbox != NULL); @@ -1139,7 +1139,7 @@ void SPItem::invoke_hide(unsigned key) // Adjusters -void SPItem::adjust_pattern (Geom::Matrix const &postmul, bool set) +void SPItem::adjust_pattern (Geom::Affine const &postmul, bool set) { if (style && (style->fill.isPaintserver())) { SPObject *server = style->getFillPaintServer(); @@ -1158,7 +1158,7 @@ void SPItem::adjust_pattern (Geom::Matrix const &postmul, bool set) } } -void SPItem::adjust_gradient( Geom::Matrix const &postmul, bool set ) +void SPItem::adjust_gradient( Geom::Affine const &postmul, bool set ) { if ( style && style->fill.isPaintserver() ) { SPPaintServer *server = style->getFillPaintServer(); @@ -1208,12 +1208,12 @@ void SPItem::adjust_stroke( gdouble ex ) /** * Find out the inverse of previous transform of an item (from its repr) */ -Geom::Matrix sp_item_transform_repr (SPItem *item) +Geom::Affine sp_item_transform_repr (SPItem *item) { - Geom::Matrix t_old(Geom::identity()); + Geom::Affine t_old(Geom::identity()); gchar const *t_attr = item->getRepr()->attribute("transform"); if (t_attr) { - Geom::Matrix t; + Geom::Affine t; if (sp_svg_transform_read(t_attr, &t)) { t_old = t; } @@ -1244,7 +1244,7 @@ void SPItem::adjust_stroke_width_recursive(double expansion) * Recursively adjust rx and ry of rects. */ void -sp_item_adjust_rects_recursive(SPItem *item, Geom::Matrix advertized_transform) +sp_item_adjust_rects_recursive(SPItem *item, Geom::Affine advertized_transform) { if (SP_IS_RECT (item)) { sp_rect_compensate_rxry (SP_RECT(item), advertized_transform); @@ -1259,13 +1259,13 @@ sp_item_adjust_rects_recursive(SPItem *item, Geom::Matrix advertized_transform) /** * Recursively compensate pattern or gradient transform. */ -void SPItem::adjust_paint_recursive (Geom::Matrix advertized_transform, Geom::Matrix t_ancestors, bool is_pattern) +void SPItem::adjust_paint_recursive (Geom::Affine advertized_transform, Geom::Affine t_ancestors, bool is_pattern) { // _Before_ full pattern/gradient transform: t_paint * t_item * t_ancestors // _After_ full pattern/gradient transform: t_paint_new * t_item * t_ancestors * advertised_transform // By equating these two expressions we get t_paint_new = t_paint * paint_delta, where: - Geom::Matrix t_item = sp_item_transform_repr (this); - Geom::Matrix paint_delta = t_item * t_ancestors * advertized_transform * t_ancestors.inverse() * t_item.inverse(); + Geom::Affine t_item = sp_item_transform_repr (this); + Geom::Affine paint_delta = t_item * t_ancestors * advertized_transform * t_ancestors.inverse() * t_item.inverse(); // Within text, we do not fork gradients, and so must not recurse to avoid double compensation; // also we do not recurse into clones, because a clone's child is the ghost of its original - @@ -1292,7 +1292,7 @@ void SPItem::adjust_paint_recursive (Geom::Matrix advertized_transform, Geom::Ma } } -void SPItem::adjust_livepatheffect (Geom::Matrix const &postmul, bool set) +void SPItem::adjust_livepatheffect (Geom::Affine const &postmul, bool set) { if ( SP_IS_LPE_ITEM(this) ) { SPLPEItem *lpeitem = SP_LPE_ITEM (this); @@ -1321,12 +1321,12 @@ void SPItem::adjust_livepatheffect (Geom::Matrix const &postmul, bool set) * stored optimized. Send _transformed_signal. Invoke _write method so that * the repr is updated with the new transform. */ -void SPItem::doWriteTransform(Inkscape::XML::Node *repr, Geom::Matrix const &transform, Geom::Matrix const *adv, bool compensate) +void SPItem::doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &transform, Geom::Affine const *adv, bool compensate) { g_return_if_fail(repr != NULL); // calculate the relative transform, if not given by the adv attribute - Geom::Matrix advertized_transform; + Geom::Affine advertized_transform; if (adv != NULL) { advertized_transform = *adv; } else { @@ -1364,7 +1364,7 @@ void SPItem::doWriteTransform(Inkscape::XML::Node *repr, Geom::Matrix const &tra } // endif(compensate) gint preserve = prefs->getBool("/options/preservetransform/value", 0); - Geom::Matrix transform_attr (transform); + Geom::Affine transform_attr (transform); if ( // run the object's set_transform (i.e. embed transform) only if: ((SPItemClass *) G_OBJECT_GET_CLASS(this))->set_transform && // it does have a set_transform method !preserve && // user did not chose to preserve all transforms @@ -1400,7 +1400,7 @@ gint SPItem::emitEvent(SPEvent &event) * Sets item private transform (not propagated to repr), without compensating stroke widths, * gradients, patterns as sp_item_write_transform does. */ -void SPItem::set_item_transform(Geom::Matrix const &transform_matrix) +void SPItem::set_item_transform(Geom::Affine const &transform_matrix) { if (!matrix_equalp(transform_matrix, transform, NR_EPSILON)) { transform = transform_matrix; @@ -1427,9 +1427,9 @@ void SPItem::convert_item_to_guides() { * \pre \a ancestor really is an ancestor (\>=) of \a object, or NULL. * ("Ancestor (\>=)" here includes as far as \a object itself.) */ -Geom::Matrix +Geom::Affine i2anc_affine(SPObject const *object, SPObject const *const ancestor) { - Geom::Matrix ret(Geom::identity()); + Geom::Affine ret(Geom::identity()); g_return_val_if_fail(object != NULL, ret); /* stop at first non-renderable ancestor */ @@ -1444,14 +1444,14 @@ i2anc_affine(SPObject const *object, SPObject const *const ancestor) { return ret; } -Geom::Matrix +Geom::Affine i2i_affine(SPObject const *src, SPObject const *dest) { g_return_val_if_fail(src != NULL && dest != NULL, Geom::identity()); SPObject const *ancestor = src->nearestCommonAncestor(dest); return i2anc_affine(src, ancestor) * i2anc_affine(dest, ancestor).inverse(); } -Geom::Matrix SPItem::getRelativeTransform(SPObject const *dest) const { +Geom::Affine SPItem::getRelativeTransform(SPObject const *dest) const { return i2i_affine(this, dest); } @@ -1459,7 +1459,7 @@ Geom::Matrix SPItem::getRelativeTransform(SPObject const *dest) const { * Returns the accumulated transformation of the item and all its ancestors, including root's viewport. * \pre (item != NULL) and SP_IS_ITEM(item). */ -Geom::Matrix SPItem::i2doc_affine() const +Geom::Affine SPItem::i2doc_affine() const { return i2anc_affine(this, NULL); } @@ -1467,17 +1467,17 @@ Geom::Matrix SPItem::i2doc_affine() const /** * Returns the transformation from item to desktop coords */ -Geom::Matrix SPItem::i2d_affine() const +Geom::Affine SPItem::i2d_affine() const { - Geom::Matrix const ret( i2doc_affine() + Geom::Affine const ret( i2doc_affine() * Geom::Scale(1, -1) * Geom::Translate(0, document->getHeight()) ); return ret; } -void SPItem::set_i2d_affine(Geom::Matrix const &i2dt) +void SPItem::set_i2d_affine(Geom::Affine const &i2dt) { - Geom::Matrix dt2p; /* desktop to item parent transform */ + Geom::Affine dt2p; /* desktop to item parent transform */ if (parent) { dt2p = static_cast(parent)->i2d_affine().inverse(); } else { @@ -1485,7 +1485,7 @@ void SPItem::set_i2d_affine(Geom::Matrix const &i2dt) * Geom::Scale(1, -1) ); } - Geom::Matrix const i2p( i2dt * dt2p ); + Geom::Affine const i2p( i2dt * dt2p ); set_item_transform(i2p); } @@ -1493,7 +1493,7 @@ void SPItem::set_i2d_affine(Geom::Matrix const &i2dt) /** * should rather be named "sp_item_d2i_affine" to match "sp_item_i2d_affine" (or vice versa) */ -Geom::Matrix SPItem::dt2i_affine() const +Geom::Affine SPItem::dt2i_affine() const { /* fixme: Implement the right way (Lauris) */ return i2d_affine().inverse(); diff --git a/src/sp-item.h b/src/sp-item.h index 4ba3dc7a4..dc440b397 100644 --- a/src/sp-item.h +++ b/src/sp-item.h @@ -22,7 +22,7 @@ #include "display/nr-arena-forward.h" #include "sp-object.h" -#include <2geom/matrix.h> +#include <2geom/affine.h> #include #include <2geom/forward.h> #include @@ -86,11 +86,11 @@ class SPItemCtx { public: SPCtx ctx; /** Item to document transformation */ - Geom::Matrix i2doc; + Geom::Affine i2doc; /** Viewport size */ NRRect vp; /** Item to viewport transformation */ - Geom::Matrix i2vp; + Geom::Affine i2vp; }; class SPItem; @@ -120,7 +120,7 @@ public: double transform_center_x; double transform_center_y; - Geom::Matrix transform; + Geom::Affine transform; SPClipPathReference *clip_ref; SPMaskReference *mask_ref; @@ -132,7 +132,7 @@ public: std::vector constraints; - sigc::signal _transformed_signal; + sigc::signal _transformed_signal; void init(); bool isLocked() const; @@ -160,25 +160,25 @@ public: bool isVisibleAndUnlocked(unsigned display_key) const; - Geom::Matrix getRelativeTransform(SPObject const *obj) const; + Geom::Affine getRelativeTransform(SPObject const *obj) const; void raiseOne(); void lowerOne(); void raiseToTop(); void lowerToBottom(); - Geom::OptRect getBounds(Geom::Matrix const &transform, BBoxType type=APPROXIMATE_BBOX, unsigned int dkey=0) const; + Geom::OptRect getBounds(Geom::Affine const &transform, BBoxType type=APPROXIMATE_BBOX, unsigned int dkey=0) const; sigc::connection _clip_ref_connection; sigc::connection _mask_ref_connection; - sigc::connection connectTransformed(sigc::slot slot) { + sigc::connection connectTransformed(sigc::slot slot) { return _transformed_signal.connect(slot); } - void invoke_bbox( Geom::OptRect &bbox, Geom::Matrix const &transform, unsigned const clear, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX); - void invoke_bbox( NRRect *bbox, Geom::Matrix const &transform, unsigned const clear, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) __attribute__ ((deprecated)); - void invoke_bbox_full( Geom::OptRect &bbox, Geom::Matrix const &transform, unsigned const flags, unsigned const clear) const; - void invoke_bbox_full( NRRect *bbox, Geom::Matrix const &transform, unsigned const flags, unsigned const clear) __attribute__ ((deprecated)); + void invoke_bbox( Geom::OptRect &bbox, Geom::Affine const &transform, unsigned const clear, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX); + void invoke_bbox( NRRect *bbox, Geom::Affine const &transform, unsigned const clear, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) __attribute__ ((deprecated)); + void invoke_bbox_full( Geom::OptRect &bbox, Geom::Affine const &transform, unsigned const flags, unsigned const clear) const; + void invoke_bbox_full( NRRect *bbox, Geom::Affine const &transform, unsigned const flags, unsigned const clear) __attribute__ ((deprecated)); unsigned pos_in_parent(); gchar *description(); @@ -187,23 +187,23 @@ public: NRArenaItem *invoke_show(NRArena *arena, unsigned int key, unsigned int flags); void invoke_hide(unsigned int key); void getSnappoints(std::vector &p, Inkscape::SnapPreferences const *snapprefs=0) const; - void adjust_pattern(/* Geom::Matrix const &premul, */ Geom::Matrix const &postmul, bool set = false); - void adjust_gradient(/* Geom::Matrix const &premul, */ Geom::Matrix const &postmul, bool set = false); + void adjust_pattern(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false); + void adjust_gradient(/* Geom::Affine const &premul, */ Geom::Affine const &postmul, bool set = false); void adjust_stroke(gdouble ex); void adjust_stroke_width_recursive(gdouble ex); - void adjust_paint_recursive(Geom::Matrix advertized_transform, Geom::Matrix t_ancestors, bool is_pattern); - void adjust_livepatheffect(Geom::Matrix const &postmul, bool set = false); - void doWriteTransform(Inkscape::XML::Node *repr, Geom::Matrix const &transform, Geom::Matrix const *adv = NULL, bool compensate = true); - void set_item_transform(Geom::Matrix const &transform_matrix); + void adjust_paint_recursive(Geom::Affine advertized_transform, Geom::Affine t_ancestors, bool is_pattern); + void adjust_livepatheffect(Geom::Affine const &postmul, bool set = false); + void doWriteTransform(Inkscape::XML::Node *repr, Geom::Affine const &transform, Geom::Affine const *adv = NULL, bool compensate = true); + void set_item_transform(Geom::Affine const &transform_matrix); void convert_item_to_guides(); gint emitEvent (SPEvent &event); NRArenaItem *get_arenaitem(unsigned int key); void getBboxDesktop(NRRect *bbox, SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX) __attribute__ ((deprecated)); Geom::OptRect getBboxDesktop(SPItem::BBoxType type = SPItem::APPROXIMATE_BBOX); - Geom::Matrix i2doc_affine() const; - Geom::Matrix i2d_affine() const; - void set_i2d_affine(Geom::Matrix const &transform); - Geom::Matrix dt2i_affine() const; + Geom::Affine i2doc_affine() const; + Geom::Affine i2d_affine() const; + void set_i2d_affine(Geom::Affine const &transform); + Geom::Affine dt2i_affine() const; void convert_to_guides(); private: @@ -240,7 +240,7 @@ public: SPObjectClass parent_class; /** BBox union in given coordinate system */ - void (* bbox) (SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); + void (* bbox) (SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); /** Printing method. Assumes ctm is set to item affine matrix */ /* \todo Think about it, and maybe implement generic export method instead (Lauris) */ @@ -258,7 +258,7 @@ public: void (* snappoints) (SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs); /** Apply the transform optimally, and return any residual transformation */ - Geom::Matrix (* set_transform)(SPItem *item, Geom::Matrix const &transform); + Geom::Affine (* set_transform)(SPItem *item, Geom::Affine const &transform); /** Convert the item to guidelines */ void (* convert_to_guides)(SPItem *item); @@ -275,8 +275,8 @@ public: // Utility -Geom::Matrix i2anc_affine(SPObject const *item, SPObject const *ancestor); -Geom::Matrix i2i_affine(SPObject const *src, SPObject const *dest); +Geom::Affine i2anc_affine(SPObject const *item, SPObject const *ancestor); +Geom::Affine i2i_affine(SPObject const *src, SPObject const *dest); /* fixme: - these are evil, but OK */ diff --git a/src/sp-line.cpp b/src/sp-line.cpp index b8c5a19b7..100eefe87 100644 --- a/src/sp-line.cpp +++ b/src/sp-line.cpp @@ -180,7 +180,7 @@ void SPLine::convertToGuides(SPItem *item) SPLine *line = SP_LINE(item); Geom::Point points[2]; - Geom::Matrix const i2d(item->i2d_affine()); + Geom::Affine const i2d(item->i2d_affine()); points[0] = Geom::Point(line->x1.computed, line->y1.computed)*i2d; points[1] = Geom::Point(line->x2.computed, line->y2.computed)*i2d; @@ -188,7 +188,7 @@ void SPLine::convertToGuides(SPItem *item) SPGuide::createSPGuide(inkscape_active_desktop(), points[0], points[1]); } -Geom::Matrix SPLine::setTransform(SPItem *item, Geom::Matrix const &xform) +Geom::Affine SPLine::setTransform(SPItem *item, Geom::Affine const &xform) { SPLine *line = SP_LINE(item); Geom::Point points[2]; diff --git a/src/sp-line.h b/src/sp-line.h index 8bcb81645..182f85a5c 100644 --- a/src/sp-line.h +++ b/src/sp-line.h @@ -44,7 +44,7 @@ private: static Inkscape::XML::Node *write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); static gchar *getDescription(SPItem * item); - static Geom::Matrix setTransform(SPItem *item, Geom::Matrix const &xform); + static Geom::Affine setTransform(SPItem *item, Geom::Affine const &xform); static void update(SPObject *object, SPCtx *ctx, guint flags); static void setShape(SPShape *shape); diff --git a/src/sp-mask.cpp b/src/sp-mask.cpp index dde91b062..372dd51da 100644 --- a/src/sp-mask.cpp +++ b/src/sp-mask.cpp @@ -217,7 +217,7 @@ static void sp_mask_update(SPObject *object, SPCtx *ctx, guint flags) SPMask *mask = SP_MASK(object); for (SPMaskView *v = mask->display; v != NULL; v = v->next) { if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) { - Geom::Matrix t(Geom::Scale(v->bbox.x1 - v->bbox.x0, v->bbox.y1 - v->bbox.y0)); + Geom::Affine t(Geom::Scale(v->bbox.x1 - v->bbox.x0, v->bbox.y1 - v->bbox.y0)); t[4] = v->bbox.x0; t[5] = v->bbox.y0; nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), &t); @@ -267,7 +267,7 @@ sp_mask_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML // Create a mask element (using passed elements), add it to const gchar * -sp_mask_create (GSList *reprs, SPDocument *document, Geom::Matrix const* applyTransform) +sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform) { Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document)); @@ -284,7 +284,7 @@ sp_mask_create (GSList *reprs, SPDocument *document, Geom::Matrix const* applyTr SPItem *item = SP_ITEM(mask_object->appendChildRepr(node)); if (NULL != applyTransform) { - Geom::Matrix transform (item->transform); + Geom::Affine transform (item->transform); transform *= (*applyTransform); item->doWriteTransform(SP_OBJECT_REPR(item), transform); } @@ -318,7 +318,7 @@ NRArenaItem *sp_mask_show(SPMask *mask, NRArena *arena, unsigned int key) } if (mask->maskContentUnits == SP_CONTENT_UNITS_OBJECTBOUNDINGBOX) { - Geom::Matrix t(Geom::Scale(mask->display->bbox.x1 - mask->display->bbox.x0, mask->display->bbox.y1 - mask->display->bbox.y0)); + Geom::Affine t(Geom::Scale(mask->display->bbox.x1 - mask->display->bbox.x0, mask->display->bbox.y1 - mask->display->bbox.y0)); t[4] = mask->display->bbox.x0; t[5] = mask->display->bbox.y0; nr_arena_group_set_child_transform (NR_ARENA_GROUP (ai), &t); diff --git a/src/sp-mask.h b/src/sp-mask.h index d8b6b33ea..5a98ac8c5 100644 --- a/src/sp-mask.h +++ b/src/sp-mask.h @@ -95,6 +95,6 @@ void sp_mask_hide (SPMask *mask, unsigned int key); void sp_mask_set_bbox (SPMask *mask, unsigned int key, NRRect *bbox); -const gchar *sp_mask_create (GSList *reprs, SPDocument *document, Geom::Matrix const* applyTransform); +const gchar *sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform); #endif // SEEN_SP_MASK_H diff --git a/src/sp-offset.cpp b/src/sp-offset.cpp index 51bb1e1cc..6f825ab1d 100644 --- a/src/sp-offset.cpp +++ b/src/sp-offset.cpp @@ -90,7 +90,7 @@ static void refresh_offset_source(SPOffset* offset); static void sp_offset_start_listening(SPOffset *offset,SPObject* to); static void sp_offset_quit_listening(SPOffset *offset); static void sp_offset_href_changed(SPObject *old_ref, SPObject *ref, SPOffset *offset); -static void sp_offset_move_compensate(Geom::Matrix const *mp, SPItem *original, SPOffset *self); +static void sp_offset_move_compensate(Geom::Affine const *mp, SPItem *original, SPOffset *self); static void sp_offset_delete_self(SPObject *deleted, SPOffset *self); static void sp_offset_source_modified (SPObject *iSource, guint flags, SPItem *item); @@ -1024,20 +1024,20 @@ sp_offset_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPOffset *offse } static void -sp_offset_move_compensate(Geom::Matrix const *mp, SPItem */*original*/, SPOffset *self) +sp_offset_move_compensate(Geom::Affine const *mp, SPItem */*original*/, SPOffset *self) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); guint mode = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_PARALLEL); if (mode == SP_CLONE_COMPENSATION_NONE) return; - Geom::Matrix m(*mp); + Geom::Affine m(*mp); if (!(m.isTranslation())) return; // calculate the compensation matrix and the advertized movement matrix SPItem *item = SP_ITEM(self); - Geom::Matrix compensate; - Geom::Matrix advertized_move; + Geom::Affine compensate; + Geom::Affine advertized_move; if (mode == SP_CLONE_COMPENSATION_UNMOVED) { compensate = Geom::identity(); diff --git a/src/sp-paint-server.cpp b/src/sp-paint-server.cpp index 4b5366a46..b672e4480 100644 --- a/src/sp-paint-server.cpp +++ b/src/sp-paint-server.cpp @@ -82,8 +82,8 @@ static void sp_paint_server_release(SPObject *object) } SPPainter *sp_paint_server_painter_new(SPPaintServer *ps, - Geom::Matrix const &full_transform, - Geom::Matrix const &parent_transform, + Geom::Affine const &full_transform, + Geom::Affine const &parent_transform, const NRRect *bbox) { g_return_val_if_fail(ps != NULL, NULL); diff --git a/src/sp-paint-server.h b/src/sp-paint-server.h index a663807b0..05f5b7bad 100644 --- a/src/sp-paint-server.h +++ b/src/sp-paint-server.h @@ -63,12 +63,12 @@ private: struct SPPaintServerClass { SPObjectClass sp_object_class; /** Get SPPaint instance. */ - SPPainter * (* painter_new) (SPPaintServer *ps, Geom::Matrix const &full_transform, Geom::Matrix const &parent_transform, const NRRect *bbox); + SPPainter * (* painter_new) (SPPaintServer *ps, Geom::Affine const &full_transform, Geom::Affine const &parent_transform, const NRRect *bbox); /** Free SPPaint instance. */ void (* painter_free) (SPPaintServer *ps, SPPainter *painter); }; -SPPainter *sp_paint_server_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, Geom::Matrix const &parent_transform, const NRRect *bbox); +SPPainter *sp_paint_server_painter_new (SPPaintServer *ps, Geom::Affine const &full_transform, Geom::Affine const &parent_transform, const NRRect *bbox); SPPainter *sp_painter_free (SPPainter *painter); diff --git a/src/sp-path.cpp b/src/sp-path.cpp index 66a70e0f1..5d84b468e 100644 --- a/src/sp-path.cpp +++ b/src/sp-path.cpp @@ -59,7 +59,7 @@ static void sp_path_build(SPObject *object, SPDocument *document, Inkscape::XML: static void sp_path_set(SPObject *object, unsigned key, gchar const *value); static Inkscape::XML::Node *sp_path_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); -static Geom::Matrix sp_path_set_transform(SPItem *item, Geom::Matrix const &xform); +static Geom::Affine sp_path_set_transform(SPItem *item, Geom::Affine const &xform); static gchar * sp_path_description(SPItem *item); static void sp_path_convert_to_guides(SPItem *item); @@ -170,7 +170,7 @@ sp_path_convert_to_guides(SPItem *item) std::list > pts; - Geom::Matrix const i2d (SP_ITEM(path)->i2d_affine()); + Geom::Affine const i2d (SP_ITEM(path)->i2d_affine()); Geom::PathVector const & pv = curve->get_pathvector(); for(Geom::PathVector::const_iterator pit = pv.begin(); pit != pv.end(); ++pit) { @@ -372,8 +372,8 @@ sp_path_update(SPObject *object, SPCtx *ctx, guint flags) /** * Writes the given transform into the repr for the given item. */ -static Geom::Matrix -sp_path_set_transform(SPItem *item, Geom::Matrix const &xform) +static Geom::Affine +sp_path_set_transform(SPItem *item, Geom::Affine const &xform) { SPShape *shape = (SPShape *) item; SPPath *path = (SPPath *) item; diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index fbba4cc48..b0264ad13 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -44,17 +44,17 @@ struct SPPatPainter { SPPainter painter; SPPattern *pat; - Geom::Matrix ps2px; - Geom::Matrix px2ps; - Geom::Matrix pcs2px; + Geom::Affine ps2px; + Geom::Affine px2ps; + Geom::Affine pcs2px; NRArena *arena; unsigned int dkey; NRArenaItem *root; bool use_cached_tile; - Geom::Matrix ca2pa; - Geom::Matrix pa2ca; + Geom::Affine ca2pa; + Geom::Affine pa2ca; NRRectL cached_bbox; NRPixBlock cached_tile; @@ -74,7 +74,7 @@ static void sp_pattern_modified (SPObject *object, unsigned int flags); static void pattern_ref_changed(SPObject *old_ref, SPObject *ref, SPPattern *pat); static void pattern_ref_modified (SPObject *ref, guint flags, SPPattern *pattern); -static SPPainter *sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, Geom::Matrix const &parent_transform, const NRRect *bbox); +static SPPainter *sp_pattern_painter_new (SPPaintServer *ps, Geom::Affine const &full_transform, Geom::Affine const &parent_transform, const NRRect *bbox); static void sp_pattern_painter_free (SPPaintServer *ps, SPPainter *painter); static SPPaintServerClass * pattern_parent_class; @@ -228,7 +228,7 @@ sp_pattern_set (SPObject *object, unsigned int key, const gchar *value) object->requestModified(SP_OBJECT_MODIFIED_FLAG); break; case SP_ATTR_PATTERNTRANSFORM: { - Geom::Matrix t; + Geom::Affine t; if (value && sp_svg_transform_read (value, &t)) { pat->patternTransform = t; pat->patternTransform_set = TRUE; @@ -504,7 +504,7 @@ sp_pattern_clone_if_necessary (SPItem *item, SPPattern *pattern, const gchar *pr } void -sp_pattern_transform_multiply (SPPattern *pattern, Geom::Matrix postmul, bool set) +sp_pattern_transform_multiply (SPPattern *pattern, Geom::Affine postmul, bool set) { // this formula is for a different interpretation of pattern transforms as described in (*) in sp-pattern.cpp // for it to work, we also need sp_object_read_attr (SP_OBJECT (item), "transform"); @@ -523,7 +523,7 @@ sp_pattern_transform_multiply (SPPattern *pattern, Geom::Matrix postmul, bool se g_free(c); } -const gchar *pattern_tile(GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Matrix transform, Geom::Matrix move) +const gchar *pattern_tile(GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move) { Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document)); @@ -545,7 +545,7 @@ const gchar *pattern_tile(GSList *reprs, Geom::Rect bounds, SPDocument *document Inkscape::XML::Node *node = (Inkscape::XML::Node *)(i->data); SPItem *copy = SP_ITEM(pat_object->appendChildRepr(node)); - Geom::Matrix dup_transform; + Geom::Affine dup_transform; if (!sp_svg_transform_read (node->attribute("transform"), &dup_transform)) dup_transform = Geom::identity(); dup_transform *= move; @@ -590,7 +590,7 @@ guint pattern_patternContentUnits (SPPattern *pat) return pat->patternContentUnits; } -Geom::Matrix const &pattern_patternTransform(SPPattern const *pat) +Geom::Affine const &pattern_patternTransform(SPPattern const *pat) { for (SPPattern const *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) { if (pat_i->patternTransform_set) @@ -679,7 +679,7 @@ Creates a painter (i.e. the thing that does actual filling at the given zoom). See (*) below for why the parent_transform may be necessary. */ static SPPainter * -sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, Geom::Matrix const &/*parent_transform*/, const NRRect *bbox) +sp_pattern_painter_new (SPPaintServer *ps, Geom::Affine const &full_transform, Geom::Affine const &/*parent_transform*/, const NRRect *bbox) { SPPattern *pat = SP_PATTERN (ps); SPPatPainter *pp = g_new (SPPatPainter, 1); @@ -691,10 +691,10 @@ sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, G if (pattern_patternUnits (pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { /* BBox to user coordinate system */ - Geom::Matrix bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); + Geom::Affine bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); // the final patternTransform, taking into account bbox - Geom::Matrix const ps2user(pattern_patternTransform(pat) * bbox2user); + Geom::Affine const ps2user(pattern_patternTransform(pat) * bbox2user); // see (*) comment below pp->ps2px = ps2user * full_transform; @@ -725,9 +725,9 @@ sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, G gdouble tmp_y = pattern_height (pat) / (pattern_viewBox(pat)->y1 - pattern_viewBox(pat)->y0); // FIXME: preserveAspectRatio must be taken into account here too! - Geom::Matrix vb2ps (tmp_x, 0.0, 0.0, tmp_y, pattern_x(pat) - pattern_viewBox(pat)->x0 * tmp_x, pattern_y(pat) - pattern_viewBox(pat)->y0 * tmp_y); + Geom::Affine vb2ps (tmp_x, 0.0, 0.0, tmp_y, pattern_x(pat) - pattern_viewBox(pat)->x0 * tmp_x, pattern_y(pat) - pattern_viewBox(pat)->y0 * tmp_y); - Geom::Matrix vb2us = vb2ps * pattern_patternTransform(pat); + Geom::Affine vb2us = vb2ps * pattern_patternTransform(pat); // see (*) pp->pcs2px = vb2us * full_transform; @@ -735,9 +735,9 @@ sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, G /* No viewbox, have to parse units */ if (pattern_patternContentUnits (pat) == SP_PATTERN_UNITS_OBJECTBOUNDINGBOX) { /* BBox to user coordinate system */ - Geom::Matrix bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); + Geom::Affine bbox2user (bbox->x1 - bbox->x0, 0.0, 0.0, bbox->y1 - bbox->y0, bbox->x0, bbox->y0); - Geom::Matrix pcs2user = pattern_patternTransform(pat) * bbox2user; + Geom::Affine pcs2user = pattern_patternTransform(pat) * bbox2user; // see (*) pp->pcs2px = pcs2user * full_transform; diff --git a/src/sp-pattern.h b/src/sp-pattern.h index f50504a76..54f2c6a9b 100644 --- a/src/sp-pattern.h +++ b/src/sp-pattern.h @@ -64,7 +64,7 @@ struct SPPattern : public SPPaintServer { guint patternContentUnits : 1; guint patternContentUnits_set : 1; /* patternTransform attribute */ - Geom::Matrix patternTransform; + Geom::Affine patternTransform; guint patternTransform_set : 1; /* Tile rectangle */ SVGLength x; @@ -85,15 +85,15 @@ struct SPPatternClass { guint pattern_users (SPPattern *pattern); SPPattern *pattern_chain (SPPattern *pattern); SPPattern *sp_pattern_clone_if_necessary (SPItem *item, SPPattern *pattern, const gchar *property); -void sp_pattern_transform_multiply (SPPattern *pattern, Geom::Matrix postmul, bool set); +void sp_pattern_transform_multiply (SPPattern *pattern, Geom::Affine postmul, bool set); -const gchar *pattern_tile (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Matrix transform, Geom::Matrix move); +const gchar *pattern_tile (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move); SPPattern *pattern_getroot (SPPattern *pat); guint pattern_patternUnits (SPPattern *pat); guint pattern_patternContentUnits (SPPattern *pat); -Geom::Matrix const &pattern_patternTransform(SPPattern const *pat); +Geom::Affine const &pattern_patternTransform(SPPattern const *pat); gdouble pattern_x (SPPattern *pat); gdouble pattern_y (SPPattern *pat); gdouble pattern_width (SPPattern *pat); diff --git a/src/sp-rect.cpp b/src/sp-rect.cpp index 94be7551b..fd44f64df 100644 --- a/src/sp-rect.cpp +++ b/src/sp-rect.cpp @@ -42,7 +42,7 @@ static void sp_rect_update(SPObject *object, SPCtx *ctx, guint flags); static Inkscape::XML::Node *sp_rect_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); static gchar *sp_rect_description(SPItem *item); -static Geom::Matrix sp_rect_set_transform(SPItem *item, Geom::Matrix const &xform); +static Geom::Affine sp_rect_set_transform(SPItem *item, Geom::Affine const &xform); static void sp_rect_convert_to_guides(SPItem *item); static void sp_rect_set_shape(SPShape *shape); @@ -333,8 +333,8 @@ sp_rect_set_ry(SPRect *rect, gboolean set, gdouble value) /* fixme: Use preferred units somehow (Lauris) */ /* fixme: Alternately preserve whatever units there are (lauris) */ -static Geom::Matrix -sp_rect_set_transform(SPItem *item, Geom::Matrix const &xform) +static Geom::Affine +sp_rect_set_transform(SPItem *item, Geom::Affine const &xform) { SPRect *rect = SP_RECT(item); @@ -343,7 +343,7 @@ sp_rect_set_transform(SPItem *item, Geom::Matrix const &xform) /* This function takes care of translation and scaling, we return whatever parts we can't handle. */ - Geom::Matrix ret(Geom::Matrix(xform).without_translation()); + Geom::Affine ret(Geom::Affine(xform).withoutTranslation()); gdouble const sw = hypot(ret[0], ret[1]); gdouble const sh = hypot(ret[2], ret[3]); if (sw > 1e-9) { @@ -397,7 +397,7 @@ sp_rect_set_transform(SPItem *item, Geom::Matrix const &xform) Returns the ratio in which the vector from p0 to p1 is stretched by transform */ static gdouble -vector_stretch(Geom::Point p0, Geom::Point p1, Geom::Matrix xform) +vector_stretch(Geom::Point p0, Geom::Point p1, Geom::Affine xform) { if (p0 == p1) return 0; @@ -467,7 +467,7 @@ sp_rect_get_rect (SPRect *rect) } void -sp_rect_compensate_rxry(SPRect *rect, Geom::Matrix xform) +sp_rect_compensate_rxry(SPRect *rect, Geom::Affine xform) { if (rect->rx.computed == 0 && rect->ry.computed == 0) return; // nothing to compensate @@ -570,7 +570,7 @@ static void sp_rect_snappoints(SPItem const *item, std::vectori2d_affine ()); + Geom::Affine const i2d (item->i2d_affine ()); Geom::Point p0 = Geom::Point(rect->x.computed, rect->y.computed) * i2d; Geom::Point p1 = Geom::Point(rect->x.computed, rect->y.computed + rect->height.computed) * i2d; @@ -609,7 +609,7 @@ sp_rect_convert_to_guides(SPItem *item) { std::list > pts; - Geom::Matrix const i2d (SP_ITEM(rect)->i2d_affine()); + Geom::Affine const i2d (SP_ITEM(rect)->i2d_affine()); Geom::Point A1(Geom::Point(rect->x.computed, rect->y.computed) * i2d); Geom::Point A2(Geom::Point(rect->x.computed, rect->y.computed + rect->height.computed) * i2d); diff --git a/src/sp-rect.h b/src/sp-rect.h index 09d96739b..7bc85dd8a 100644 --- a/src/sp-rect.h +++ b/src/sp-rect.h @@ -63,7 +63,7 @@ void sp_rect_set_visible_height (SPRect *rect, gdouble ry); gdouble sp_rect_get_visible_width (SPRect *rect); gdouble sp_rect_get_visible_height (SPRect *rect); -void sp_rect_compensate_rxry (SPRect *rect, Geom::Matrix xform); +void sp_rect_compensate_rxry (SPRect *rect, Geom::Affine xform); #endif // SEEN_SP_RECT_H diff --git a/src/sp-root.cpp b/src/sp-root.cpp index 5f868539b..61b5fda5b 100644 --- a/src/sp-root.cpp +++ b/src/sp-root.cpp @@ -438,7 +438,7 @@ sp_root_update(SPObject *object, SPCtx *ctx, guint flags) * fixme: height seems natural, as this makes the inner svg element * fixme: self-contained. The spec is vague here. */ - root->c2p = Geom::Matrix(Geom::Translate(root->x.computed, + root->c2p = Geom::Affine(Geom::Translate(root->x.computed, root->y.computed)); } diff --git a/src/sp-root.h b/src/sp-root.h index 28ed43154..ab379fb50 100644 --- a/src/sp-root.h +++ b/src/sp-root.h @@ -47,7 +47,7 @@ struct SPRoot : public SPGroup { unsigned int aspect_clip : 1; /** Child to parent additional transform. */ - Geom::Matrix c2p; + Geom::Affine c2p; gchar *onload; diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp index 35364692b..59105a1c7 100644 --- a/src/sp-shape.cpp +++ b/src/sp-shape.cpp @@ -307,7 +307,7 @@ void SPShape::sp_shape_update(SPObject *object, SPCtx *ctx, unsigned int flags) * Reference for behaviour of zero-length segments: * http://www.w3.org/TR/SVG11/implnote.html#PathElementImplementationNotes */ -Geom::Matrix sp_shape_marker_get_transform(Geom::Curve const & c1, Geom::Curve const & c2) +Geom::Affine sp_shape_marker_get_transform(Geom::Curve const & c1, Geom::Curve const & c2) { Geom::Point p = c1.pointAt(1); Geom::Curve * c1_reverse = c1.reverse(); @@ -334,10 +334,10 @@ Geom::Matrix sp_shape_marker_get_transform(Geom::Curve const & c1, Geom::Curve c return Geom::Rotate(ret_angle) * Geom::Translate(p); } -Geom::Matrix sp_shape_marker_get_transform_at_start(Geom::Curve const & c) +Geom::Affine sp_shape_marker_get_transform_at_start(Geom::Curve const & c) { Geom::Point p = c.pointAt(0); - Geom::Matrix ret = Geom::Translate(p); + Geom::Affine ret = Geom::Translate(p); if ( !c.isDegenerate() ) { Geom::Point tang = c.unitTangentAt(0); @@ -351,10 +351,10 @@ Geom::Matrix sp_shape_marker_get_transform_at_start(Geom::Curve const & c) return ret; } -Geom::Matrix sp_shape_marker_get_transform_at_end(Geom::Curve const & c) +Geom::Affine sp_shape_marker_get_transform_at_end(Geom::Curve const & c) { Geom::Point p = c.pointAt(1); - Geom::Matrix ret = Geom::Translate(p); + Geom::Affine ret = Geom::Translate(p); if ( !c.isDegenerate() ) { Geom::Curve * c_reverse = c.reverse(); @@ -393,7 +393,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai) // START marker { - Geom::Matrix const m (sp_shape_marker_get_transform_at_start(pathv.begin()->front())); + Geom::Affine const m (sp_shape_marker_get_transform_at_start(pathv.begin()->front())); for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START if ( shape->marker[i] ) { sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai, @@ -411,7 +411,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai) if ( path_it != pathv.begin() && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, don't draw mid marker there { - Geom::Matrix const m (sp_shape_marker_get_transform_at_start(path_it->front())); + Geom::Affine const m (sp_shape_marker_get_transform_at_start(path_it->front())); for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID if ( shape->marker[i] ) { sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai, @@ -431,7 +431,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai) * Loop to end_default (so including closing segment), because when a path is closed, * there should be a midpoint marker between last segment and closing straight line segment */ - Geom::Matrix const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2)); + Geom::Affine const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2)); for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID if (shape->marker[i]) { sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai, @@ -448,7 +448,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai) // END position if ( path_it != (pathv.end()-1) && !path_it->empty()) { Geom::Curve const &lastcurve = path_it->back_default(); - Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve); + Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve); for (int i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID if (shape->marker[i]) { sp_marker_show_instance ((SPMarker* ) shape->marker[i], ai, @@ -471,7 +471,7 @@ void SPShape::sp_shape_update_marker_view(SPShape *shape, NRArenaItem *ai) index--; } Geom::Curve const &lastcurve = path_last[index]; - Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve); + Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve); for (int i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END if (shape->marker[i]) { @@ -506,7 +506,7 @@ void SPShape::sp_shape_modified(SPObject *object, unsigned int flags) * Calculates the bounding box for item, storing it into bbox. * This also includes the bounding boxes of any markers included in the shape. */ -void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags) +void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags) { SPShape const *shape = SP_SHAPE (item); if (shape->curve) { @@ -570,7 +570,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); if (marker_item) { - Geom::Matrix tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front())); + Geom::Affine tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front())); if (!marker->orient_auto) { Geom::Point transl = tr.translation(); tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); @@ -602,7 +602,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const if ( path_it != pathv.begin() && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there { - Geom::Matrix tr(sp_shape_marker_get_transform_at_start(path_it->front())); + Geom::Affine tr(sp_shape_marker_get_transform_at_start(path_it->front())); if (!marker->orient_auto) { Geom::Point transl = tr.translation(); tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); @@ -629,7 +629,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); if (marker_item) { - Geom::Matrix tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2)); + Geom::Affine tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2)); if (!marker->orient_auto) { Geom::Point transl = tr.translation(); tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); @@ -650,7 +650,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const // END position if ( path_it != (pathv.end()-1) && !path_it->empty()) { Geom::Curve const &lastcurve = path_it->back_default(); - Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve); + Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve); if (!marker->orient_auto) { Geom::Point transl = tr.translation(); tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); @@ -681,7 +681,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const } Geom::Curve const &lastcurve = path_last[index]; - Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve); + Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve); if (!marker->orient_auto) { Geom::Point transl = tr.translation(); tr = Geom::Rotate::from_degrees(marker->orient) * Geom::Translate(transl); @@ -713,7 +713,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const } static void -sp_shape_print_invoke_marker_printing(SPObject* obj, Geom::Matrix tr, SPStyle* style, SPPrintContext *ctx) { +sp_shape_print_invoke_marker_printing(SPObject* obj, Geom::Affine tr, SPStyle* style, SPPrintContext *ctx) { SPMarker *marker = SP_MARKER(obj); if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { tr = Geom::Scale(style->stroke_width.computed) * tr; @@ -722,7 +722,7 @@ sp_shape_print_invoke_marker_printing(SPObject* obj, Geom::Matrix tr, SPStyle* s SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); tr = marker_item->transform * marker->c2p * tr; - Geom::Matrix old_tr = marker_item->transform; + Geom::Affine old_tr = marker_item->transform; marker_item->transform = tr; marker_item->invoke_print (ctx); marker_item->transform = old_tr; @@ -761,7 +761,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) dbox.x1 = SP_OBJECT_DOCUMENT (item)->getWidth (); dbox.y1 = SP_OBJECT_DOCUMENT (item)->getHeight (); item->getBboxDesktop (&bbox); - Geom::Matrix const i2d(item->i2d_affine()); + Geom::Affine const i2d(item->i2d_affine()); SPStyle* style = SP_OBJECT_STYLE (item); @@ -777,7 +777,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) // START marker for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START if ( shape->marker[i] ) { - Geom::Matrix tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front())); + Geom::Affine tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front())); sp_shape_print_invoke_marker_printing(shape->marker[i], tr, style, ctx); } } @@ -789,7 +789,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) if ( path_it != pathv.begin() && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there { - Geom::Matrix tr(sp_shape_marker_get_transform_at_start(path_it->front())); + Geom::Affine tr(sp_shape_marker_get_transform_at_start(path_it->front())); sp_shape_print_invoke_marker_printing(shape->marker[i], tr, style, ctx); } // MID position @@ -801,7 +801,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) /* Put marker between curve_it1 and curve_it2. * Loop to end_default (so including closing segment), because when a path is closed, * there should be a midpoint marker between last segment and closing straight line segment */ - Geom::Matrix tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2)); + Geom::Affine tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2)); sp_shape_print_invoke_marker_printing(shape->marker[i], tr, style, ctx); @@ -811,7 +811,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) } if ( path_it != (pathv.end()-1) && !path_it->empty()) { Geom::Curve const &lastcurve = path_it->back_default(); - Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve); + Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve); sp_shape_print_invoke_marker_printing(shape->marker[i], tr, style, ctx); } } @@ -828,7 +828,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) } Geom::Curve const &lastcurve = path_last[index]; - Geom::Matrix tr = sp_shape_marker_get_transform_at_end(lastcurve); + Geom::Affine tr = sp_shape_marker_get_transform_at_end(lastcurve); for (int i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END if (shape->marker[i]) { @@ -1163,7 +1163,7 @@ void SPShape::sp_shape_snappoints(SPItem const *item, std::vectori2d_affine ()); + Geom::Affine const i2d (item->i2d_affine ()); if (snapprefs->getSnapObjectMidpoints()) { Geom::OptRect bbox = item->getBounds(item->i2d_affine()); diff --git a/src/sp-shape.h b/src/sp-shape.h index 493268711..3fd356fdc 100644 --- a/src/sp-shape.h +++ b/src/sp-shape.h @@ -60,7 +60,7 @@ private: static void sp_shape_modified (SPObject *object, unsigned int flags); static Inkscape::XML::Node *sp_shape_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); - static void sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); + static void sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); static NRArenaItem *sp_shape_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags); static void sp_shape_hide (SPItem *item, unsigned int key); static void sp_shape_snappoints (SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs); @@ -88,9 +88,9 @@ private: void sp_shape_set_marker (SPObject *object, unsigned int key, const gchar *value); -Geom::Matrix sp_shape_marker_get_transform(Geom::Curve const & c1, Geom::Curve const & c2); -Geom::Matrix sp_shape_marker_get_transform_at_start(Geom::Curve const & c); -Geom::Matrix sp_shape_marker_get_transform_at_end(Geom::Curve const & c); +Geom::Affine sp_shape_marker_get_transform(Geom::Curve const & c1, Geom::Curve const & c2); +Geom::Affine sp_shape_marker_get_transform_at_start(Geom::Curve const & c); +Geom::Affine sp_shape_marker_get_transform_at_end(Geom::Curve const & c); #endif // SEEN_SP_SHAPE_H diff --git a/src/sp-spiral.cpp b/src/sp-spiral.cpp index cfe02947a..abee41473 100644 --- a/src/sp-spiral.cpp +++ b/src/sp-spiral.cpp @@ -532,7 +532,7 @@ static void sp_spiral_snappoints(SPItem const *item, std::vectorgetSnapObjectMidpoints()) { - Geom::Matrix const i2d (item->i2d_affine ()); + Geom::Affine const i2d (item->i2d_affine ()); SPSpiral *spiral = SP_SPIRAL(item); p.push_back(Inkscape::SnapCandidatePoint(Geom::Point(spiral->cx, spiral->cy) * i2d, Inkscape::SNAPSOURCE_OBJECT_MIDPOINT, Inkscape::SNAPTARGET_OBJECT_MIDPOINT)); // This point is the start-point of the spiral, which is also returned when _snap_to_itemnode has been set diff --git a/src/sp-star.cpp b/src/sp-star.cpp index b94e2dbc4..57c72ca75 100644 --- a/src/sp-star.cpp +++ b/src/sp-star.cpp @@ -410,7 +410,7 @@ sp_star_get_curvepoint (SPStar *star, SPStarPoint point, gint index, bool previ) guint32 seed = point_unique_int (o); // randomly rotate (by step 3 from the seed) and scale (by step 4) the vector - ret = ret * Geom::Matrix (Geom::Rotate (star->randomized * M_PI * rnd (seed, 3))); + ret = ret * Geom::Affine (Geom::Rotate (star->randomized * M_PI * rnd (seed, 3))); ret *= ( 1 + star->randomized * rnd (seed, 4)); // the randomized corner point @@ -559,7 +559,7 @@ static void sp_star_snappoints(SPItem const *item, std::vectorgetSnapObjectMidpoints()) { - Geom::Matrix const i2d (item->i2d_affine ()); + Geom::Affine const i2d (item->i2d_affine ()); p.push_back(Inkscape::SnapCandidatePoint(SP_STAR(item)->center * i2d,Inkscape::SNAPSOURCE_OBJECT_MIDPOINT, Inkscape::SNAPTARGET_OBJECT_MIDPOINT)); } } diff --git a/src/sp-symbol.cpp b/src/sp-symbol.cpp index 6c8d3cd82..182a2756a 100644 --- a/src/sp-symbol.cpp +++ b/src/sp-symbol.cpp @@ -40,7 +40,7 @@ static Inkscape::XML::Node *sp_symbol_write (SPObject *object, Inkscape::XML::Do static NRArenaItem *sp_symbol_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags); static void sp_symbol_hide (SPItem *item, unsigned int key); -static void sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); +static void sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); static void sp_symbol_print (SPItem *item, SPPrintContext *ctx); static SPGroupClass *parent_class; @@ -269,7 +269,7 @@ sp_symbol_update (SPObject *object, SPCtx *ctx, guint flags) /* Calculate child to parent transformation */ /* Apply parent translation (set up as vewport) */ - symbol->c2p = Geom::Matrix(Geom::Translate(rctx.vp.x0, rctx.vp.y0)); + symbol->c2p = Geom::Affine(Geom::Translate(rctx.vp.x0, rctx.vp.y0)); if (symbol->viewBox_set) { double x, y, width, height; @@ -332,7 +332,7 @@ sp_symbol_update (SPObject *object, SPCtx *ctx, guint flags) } } /* Compose additional transformation from scale and position */ - Geom::Matrix q; + Geom::Affine q; q[0] = width / (symbol->viewBox.x1 - symbol->viewBox.x0); q[1] = 0.0; q[2] = 0.0; @@ -343,7 +343,7 @@ sp_symbol_update (SPObject *object, SPCtx *ctx, guint flags) symbol->c2p = q * symbol->c2p; } - rctx.i2doc = symbol->c2p * (Geom::Matrix)rctx.i2doc; + rctx.i2doc = symbol->c2p * (Geom::Affine)rctx.i2doc; /* If viewBox is set initialize child viewport */ /* Otherwise has set it up already */ @@ -445,7 +445,7 @@ sp_symbol_hide (SPItem *item, unsigned int key) } static void -sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags) +sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags) { SPSymbol const *symbol = SP_SYMBOL(item); @@ -453,7 +453,7 @@ sp_symbol_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, /* Cloned is actually renderable */ if (((SPItemClass *) (parent_class))->bbox) { - Geom::Matrix const a( symbol->c2p * transform ); + Geom::Affine const a( symbol->c2p * transform ); ((SPItemClass *) (parent_class))->bbox(item, bbox, a, flags); } } diff --git a/src/sp-symbol.h b/src/sp-symbol.h index 61951cf64..6c0a36d73 100644 --- a/src/sp-symbol.h +++ b/src/sp-symbol.h @@ -25,7 +25,7 @@ class SPSymbol; class SPSymbolClass; #include -#include <2geom/matrix.h> +#include <2geom/affine.h> #include #include "svg/svg-length.h" #include "enums.h" @@ -42,7 +42,7 @@ struct SPSymbol : public SPGroup { unsigned int aspect_clip : 1; /* Child to parent additional transform */ - Geom::Matrix c2p; + Geom::Affine c2p; }; struct SPSymbolClass { diff --git a/src/sp-text.cpp b/src/sp-text.cpp index 80eb786f2..3abeadaee 100644 --- a/src/sp-text.cpp +++ b/src/sp-text.cpp @@ -27,7 +27,7 @@ # include "config.h" #endif -#include <2geom/matrix.h> +#include <2geom/affine.h> #include #include #include @@ -72,12 +72,12 @@ static void sp_text_update (SPObject *object, SPCtx *ctx, guint flags); static void sp_text_modified (SPObject *object, guint flags); static Inkscape::XML::Node *sp_text_write (SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); -static void sp_text_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); +static void sp_text_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); static NRArenaItem *sp_text_show (SPItem *item, NRArena *arena, unsigned key, unsigned flags); static void sp_text_hide (SPItem *item, unsigned key); static char *sp_text_description (SPItem *item); static void sp_text_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs); -static Geom::Matrix sp_text_set_transform(SPItem *item, Geom::Matrix const &xform); +static Geom::Affine sp_text_set_transform(SPItem *item, Geom::Affine const &xform); static void sp_text_print (SPItem *item, SPPrintContext *gpc); static SPItemClass *text_parent_class; @@ -363,7 +363,7 @@ static Inkscape::XML::Node *sp_text_write(SPObject *object, Inkscape::XML::Docum } static void -sp_text_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const /*flags*/) +sp_text_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/) { SP_TEXT(item)->layout.getBoundingBox(bbox, transform); @@ -456,8 +456,8 @@ static void sp_text_snappoints(SPItem const *item, std::vectorgetWidth (); dbox.y1 = SP_OBJECT_DOCUMENT (item)->getHeight (); - Geom::Matrix const ctm (item->i2d_affine()); + Geom::Affine const ctm (item->i2d_affine()); group->layout.print(ctx,&pbox,&dbox,&bbox,ctm); } @@ -642,7 +642,7 @@ void SPText::_adjustFontsizeRecursive(SPItem *item, double ex, bool is_root) } } -void SPText::_adjustCoordsRecursive(SPItem *item, Geom::Matrix const &m, double ex, bool is_root) +void SPText::_adjustCoordsRecursive(SPItem *item, Geom::Affine const &m, double ex, bool is_root) { if (SP_IS_TSPAN(item)) SP_TSPAN(item)->attributes.transform(m, ex, ex, is_root); @@ -903,7 +903,7 @@ void TextTagAttributes::joinSingleAttribute(std::vector *dest_vector, } } -void TextTagAttributes::transform(Geom::Matrix const &matrix, double scale_x, double scale_y, bool extend_zero_length) +void TextTagAttributes::transform(Geom::Affine const &matrix, double scale_x, double scale_y, bool extend_zero_length) { SVGLength zero_length; zero_length = 0.0; diff --git a/src/sp-text.h b/src/sp-text.h index e7c264b07..116d8d869 100644 --- a/src/sp-text.h +++ b/src/sp-text.h @@ -53,7 +53,7 @@ struct SPText : public SPItem { extend zero-length position vectors to length 1 in order to record the new position. This is necessary to convert from objects whose position is completely specified by transformations. */ - static void _adjustCoordsRecursive(SPItem *item, Geom::Matrix const &m, double ex, bool is_root = true); + static void _adjustCoordsRecursive(SPItem *item, Geom::Affine const &m, double ex, bool is_root = true); static void _adjustFontsizeRecursive(SPItem *item, double ex, bool is_root = true); /** discards the NRArena objects representing this text. */ diff --git a/src/sp-tref.cpp b/src/sp-tref.cpp index eddcd270c..a882ee0b0 100644 --- a/src/sp-tref.cpp +++ b/src/sp-tref.cpp @@ -65,7 +65,7 @@ static void sp_tref_update(SPObject *object, SPCtx *ctx, guint flags); static void sp_tref_modified(SPObject *object, guint flags); static Inkscape::XML::Node *sp_tref_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); -static void sp_tref_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); +static void sp_tref_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); static gchar *sp_tref_description(SPItem *item); static void sp_tref_href_changed(SPObject *old_ref, SPObject *ref, SPTRef *tref); @@ -320,7 +320,7 @@ sp_tref_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML: * The code for this function is swiped from the tspan bbox code, since tref should work pretty much the same way */ static void -sp_tref_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const /*flags*/) +sp_tref_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/) { // find out the ancestor text which holds our layout SPObject *parent_text = SP_OBJECT(item); diff --git a/src/sp-tspan.cpp b/src/sp-tspan.cpp index 2afd75e75..57c23929d 100644 --- a/src/sp-tspan.cpp +++ b/src/sp-tspan.cpp @@ -57,7 +57,7 @@ static void sp_tspan_release(SPObject *object); static void sp_tspan_set(SPObject *object, unsigned key, gchar const *value); static void sp_tspan_update(SPObject *object, SPCtx *ctx, guint flags); static void sp_tspan_modified(SPObject *object, unsigned flags); -static void sp_tspan_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); +static void sp_tspan_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); static Inkscape::XML::Node *sp_tspan_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags); static char *sp_tspan_description (SPItem *item); @@ -204,7 +204,7 @@ static void sp_tspan_modified(SPObject *object, unsigned flags) } } -static void sp_tspan_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const /*flags*/) +static void sp_tspan_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/) { // find out the ancestor text which holds our layout SPObject *parent_text = SP_OBJECT(item); diff --git a/src/sp-use-reference.cpp b/src/sp-use-reference.cpp index a05dc0e93..0784f2dd1 100644 --- a/src/sp-use-reference.cpp +++ b/src/sp-use-reference.cpp @@ -41,7 +41,7 @@ bool SPUseReference::_acceptObject(SPObject * const obj) const static void sp_usepath_href_changed(SPObject *old_ref, SPObject *ref, SPUsePath *offset); -static void sp_usepath_move_compensate(Geom::Matrix const *mp, SPItem *original, SPUsePath *self); +static void sp_usepath_move_compensate(Geom::Affine const *mp, SPItem *original, SPUsePath *self); static void sp_usepath_delete_self(SPObject *deleted, SPUsePath *offset); static void sp_usepath_source_modified(SPObject *iSource, guint flags, SPUsePath *offset); @@ -139,7 +139,7 @@ sp_usepath_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPUsePath *off } static void -sp_usepath_move_compensate(Geom::Matrix const *mp, SPItem *original, SPUsePath *self) +sp_usepath_move_compensate(Geom::Affine const *mp, SPItem *original, SPUsePath *self) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); guint mode = prefs->getInt("/options/clonecompensation/value", SP_CLONE_COMPENSATION_PARALLEL); @@ -150,15 +150,15 @@ sp_usepath_move_compensate(Geom::Matrix const *mp, SPItem *original, SPUsePath * // TODO kill naughty naughty #if 0 #if 0 - Geom::Matrix m(*mp); + Geom::Affine m(*mp); if (!(m.is_translation())) { return; } - Geom::Matrix const t(item->transform); - Geom::Matrix clone_move = t.inverse() * m * t; + Geom::Affine const t(item->transform); + Geom::Affine clone_move = t.inverse() * m * t; // Calculate the compensation matrix and the advertized movement matrix. - Geom::Matrix advertized_move; + Geom::Affine advertized_move; if (mode == SP_CLONE_COMPENSATION_PARALLEL) { //clone_move = clone_move.inverse(); advertized_move.set_identity(); diff --git a/src/sp-use.cpp b/src/sp-use.cpp index 505c64fd2..dd5a6c5f9 100644 --- a/src/sp-use.cpp +++ b/src/sp-use.cpp @@ -51,7 +51,7 @@ static Inkscape::XML::Node *sp_use_write(SPObject *object, Inkscape::XML::Docume static void sp_use_update(SPObject *object, SPCtx *ctx, guint flags); static void sp_use_modified(SPObject *object, guint flags); -static void sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags); +static void sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags); static void sp_use_snappoints(SPItem const *item, std::vector &p, Inkscape::SnapPreferences const *snapprefs); static void sp_use_print(SPItem *item, SPPrintContext *ctx); static gchar *sp_use_description(SPItem *item); @@ -64,7 +64,7 @@ static void sp_use_delete_self(SPObject *deleted, SPUse *self); static SPItemClass *parent_class; -//void m_print(gchar *say, Geom::Matrix m) +//void m_print(gchar *say, Geom::Affine m) //{ g_print("%s %g %g %g %g %g %g\n", say, m[0], m[1], m[2], m[3], m[4], m[5]); } GType @@ -278,13 +278,13 @@ sp_use_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML:: } static void -sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Matrix const &transform, unsigned const flags) +sp_use_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const flags) { SPUse const *use = SP_USE(item); if (use->child && SP_IS_ITEM(use->child)) { SPItem *child = SP_ITEM(use->child); - Geom::Matrix const ct( child->transform + Geom::Affine const ct( child->transform * Geom::Translate(use->x.computed, use->y.computed) * transform ); @@ -306,7 +306,7 @@ sp_use_print(SPItem *item, SPPrintContext *ctx) SPUse *use = SP_USE(item); if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) { - Geom::Matrix tp(Geom::Translate(use->x.computed, use->y.computed)); + Geom::Affine tp(Geom::Translate(use->x.computed, use->y.computed)); sp_print_bind(ctx, tp, 1.0); translated = true; } @@ -363,7 +363,7 @@ sp_use_show(SPItem *item, NRArena *arena, unsigned key, unsigned flags) } Geom::Translate t(use->x.computed, use->y.computed); - nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), Geom::Matrix(t)); + nr_arena_group_set_child_transform(NR_ARENA_GROUP(ai), Geom::Affine(t)); } return ai; @@ -407,7 +407,7 @@ sp_use_root(SPUse *use) * Returns the effective transform that goes from the ultimate original to given SPUse, both ends * included. */ -Geom::Matrix +Geom::Affine sp_use_get_root_transform(SPUse *use) { //track the ultimate source of a chain of uses @@ -422,7 +422,7 @@ sp_use_get_root_transform(SPUse *use) //calculate the accummulated transform, starting from the original - Geom::Matrix t(Geom::identity()); + Geom::Affine t(Geom::identity()); for (GSList *i = chain; i != NULL; i = i->next) { SPItem *i_tem = SP_ITEM(i->data); @@ -447,10 +447,10 @@ sp_use_get_root_transform(SPUse *use) * Returns the transform that leads to the use from its immediate original. * Does not inlcude the original's transform if any. */ -Geom::Matrix +Geom::Affine sp_use_get_parent_transform(SPUse *use) { - Geom::Matrix t(Geom::identity()); + Geom::Affine t(Geom::identity()); if ((use->x._set && use->x.computed != 0) || (use->y._set && use->y.computed != 0)) { t *= Geom::Translate(use->x._set ? use->x.computed : 0, use->y._set ? use->y.computed : 0); @@ -466,7 +466,7 @@ sp_use_get_parent_transform(SPUse *use) * clone's transform. */ static void -sp_use_move_compensate(Geom::Matrix const *mp, SPItem */*original*/, SPUse *self) +sp_use_move_compensate(Geom::Affine const *mp, SPItem */*original*/, SPUse *self) { // the clone is orphaned; or this is not a real use, but a clone of another use; // we skip it, otherwise duplicate compensation will occur @@ -485,7 +485,7 @@ sp_use_move_compensate(Geom::Matrix const *mp, SPItem */*original*/, SPUse *self if (mode == SP_CLONE_COMPENSATION_NONE) return; - Geom::Matrix m(*mp); + Geom::Affine m(*mp); // this is not a simple move, do not try to compensate if (!(m.isTranslation())) @@ -494,11 +494,11 @@ sp_use_move_compensate(Geom::Matrix const *mp, SPItem */*original*/, SPUse *self // restore item->transform field from the repr, in case it was changed by seltrans SP_OBJECT (self)->readAttr ("transform"); - Geom::Matrix t = sp_use_get_parent_transform(self); - Geom::Matrix clone_move = t.inverse() * m * t; + Geom::Affine t = sp_use_get_parent_transform(self); + Geom::Affine clone_move = t.inverse() * m * t; // calculate the compensation matrix and the advertized movement matrix - Geom::Matrix advertized_move; + Geom::Affine advertized_move; if (mode == SP_CLONE_COMPENSATION_PARALLEL) { clone_move = clone_move.inverse() * m; advertized_move = m; @@ -633,7 +633,7 @@ sp_use_update(SPObject *object, SPCtx *ctx, unsigned flags) /* As last step set additional transform of arena group */ for (SPItemView *v = item->display; v != NULL; v = v->next) { - Geom::Matrix t(Geom::Translate(use->x.computed, use->y.computed)); + Geom::Affine t(Geom::Translate(use->x.computed, use->y.computed)); nr_arena_group_set_child_transform(NR_ARENA_GROUP(v->arenaitem), t); } } @@ -686,7 +686,7 @@ SPItem *sp_use_unlink(SPUse *use) } // Calculate the accumulated transform, starting from the original. - Geom::Matrix t = sp_use_get_root_transform(use); + Geom::Affine t = sp_use_get_root_transform(use); Inkscape::XML::Node *copy = NULL; if (SP_IS_SYMBOL(orig)) { // make a group, copy children @@ -739,7 +739,7 @@ SPItem *sp_use_unlink(SPUse *use) SPItem *item = SP_ITEM(unlinked); // Set the accummulated transform. { - Geom::Matrix nomove(Geom::identity()); + Geom::Affine nomove(Geom::identity()); // Advertise ourselves as not moving. item->doWriteTransform(SP_OBJECT_REPR(item), t, &nomove); } diff --git a/src/sp-use.h b/src/sp-use.h index c5c07158f..ff0e1c604 100644 --- a/src/sp-use.h +++ b/src/sp-use.h @@ -59,8 +59,8 @@ GType sp_use_get_type (void); SPItem *sp_use_unlink (SPUse *use); SPItem *sp_use_get_original (SPUse *use); -Geom::Matrix sp_use_get_parent_transform (SPUse *use); -Geom::Matrix sp_use_get_root_transform(SPUse *use); +Geom::Affine sp_use_get_parent_transform (SPUse *use); +Geom::Affine sp_use_get_root_transform(SPUse *use); SPItem *sp_use_root(SPUse *use); #endif diff --git a/src/splivarot.cpp b/src/splivarot.cpp index 5f32e591e..bcb9b1bb6 100644 --- a/src/splivarot.cpp +++ b/src/splivarot.cpp @@ -452,7 +452,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb // adjust style properties that depend on a possible transform in the source object in order // to get a correct style attribute for the new path SPItem* item_source = SP_ITEM(source); - Geom::Matrix i2doc(item_source->i2doc_affine()); + Geom::Affine i2doc(item_source->i2doc_affine()); item_source->adjust_stroke(i2doc.descrim()); item_source->adjust_pattern(i2doc); item_source->adjust_gradient(i2doc); @@ -485,7 +485,7 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb // premultiply by the inverse of parent's repr SPItem *parent_item = SP_ITEM(sp_desktop_document(desktop)->getObjectByRepr(parent)); - Geom::Matrix local (parent_item->i2doc_affine()); + Geom::Affine local (parent_item->i2doc_affine()); gchar *transform = sp_svg_transform_write(local.inverse()); // now that we have the result, add it on the canvas @@ -601,14 +601,14 @@ sp_selected_path_boolop(SPDesktop *desktop, bool_op bop, const unsigned int verb } static -void sp_selected_path_outline_add_marker( SPObject *marker_object, Geom::Matrix marker_transform, - Geom::Scale stroke_scale, Geom::Matrix transform, +void sp_selected_path_outline_add_marker( SPObject *marker_object, Geom::Affine marker_transform, + Geom::Scale stroke_scale, Geom::Affine transform, Inkscape::XML::Node *g_repr, Inkscape::XML::Document *xml_doc, SPDocument * doc ) { SPMarker* marker = SP_MARKER (marker_object); SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker_object)); - Geom::Matrix tr(marker_transform); + Geom::Affine tr(marker_transform); if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { tr = stroke_scale * tr; @@ -626,13 +626,13 @@ void sp_selected_path_outline_add_marker( SPObject *marker_object, Geom::Matrix } static -void item_outline_add_marker( SPObject const *marker_object, Geom::Matrix marker_transform, +void item_outline_add_marker( SPObject const *marker_object, Geom::Affine marker_transform, Geom::Scale stroke_scale, Geom::PathVector* pathv_in ) { SPMarker* marker = SP_MARKER (marker_object); SPItem* marker_item = sp_item_first_item_child(SP_OBJECT(marker_object)); - Geom::Matrix tr(marker_transform); + Geom::Affine tr(marker_transform); if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) { tr = stroke_scale * tr; } @@ -682,7 +682,7 @@ Geom::PathVector* item_outline(SPItem const *item) // remember old stroke style, to be set on fill SPStyle *i_style = SP_OBJECT_STYLE(item); - Geom::Matrix const transform(item->transform); + Geom::Affine const transform(item->transform); float const scale = transform.descrim(); float o_width, o_miter; @@ -794,7 +794,7 @@ Geom::PathVector* item_outline(SPItem const *item) // START marker for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START if ( SPObject *marker_obj = shape->marker[i] ) { - Geom::Matrix const m (sp_shape_marker_get_transform_at_start(pathv.front().front())); + Geom::Affine const m (sp_shape_marker_get_transform_at_start(pathv.front().front())); item_outline_add_marker( marker_obj, m, Geom::Scale(i_style->stroke_width.computed), ret_pathv ); @@ -809,7 +809,7 @@ Geom::PathVector* item_outline(SPItem const *item) if ( path_it != pathv.begin() && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there { - Geom::Matrix const m (sp_shape_marker_get_transform_at_start(path_it->front())); + Geom::Affine const m (sp_shape_marker_get_transform_at_start(path_it->front())); item_outline_add_marker( midmarker_obj, m, Geom::Scale(i_style->stroke_width.computed), ret_pathv ); @@ -824,7 +824,7 @@ Geom::PathVector* item_outline(SPItem const *item) * Loop to end_default (so including closing segment), because when a path is closed, * there should be a midpoint marker between last segment and closing straight line segment */ - Geom::Matrix const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2)); + Geom::Affine const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2)); item_outline_add_marker( midmarker_obj, m, Geom::Scale(i_style->stroke_width.computed), ret_pathv); @@ -836,7 +836,7 @@ Geom::PathVector* item_outline(SPItem const *item) // END position if ( path_it != (pathv.end()-1) && !path_it->empty()) { Geom::Curve const &lastcurve = path_it->back_default(); - Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve); + Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve); item_outline_add_marker( midmarker_obj, m, Geom::Scale(i_style->stroke_width.computed), ret_pathv ); @@ -855,7 +855,7 @@ Geom::PathVector* item_outline(SPItem const *item) } Geom::Curve const &lastcurve = path_last[index]; - Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve); + Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve); item_outline_add_marker( marker_obj, m, Geom::Scale(i_style->stroke_width.computed), ret_pathv ); @@ -936,7 +936,7 @@ sp_selected_path_outline(SPDesktop *desktop) sp_repr_css_unset_property(ncss, "marker-end"); } - Geom::Matrix const transform(item->transform); + Geom::Affine const transform(item->transform); float const scale = transform.descrim(); gchar const *mask = SP_OBJECT_REPR(item)->attribute("mask"); gchar const *clip_path = SP_OBJECT_REPR(item)->attribute("clip-path"); @@ -1112,7 +1112,7 @@ sp_selected_path_outline(SPDesktop *desktop) // START marker for (int i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START if ( SPObject *marker_obj = shape->marker[i] ) { - Geom::Matrix const m (sp_shape_marker_get_transform_at_start(pathv.front().front())); + Geom::Affine const m (sp_shape_marker_get_transform_at_start(pathv.front().front())); sp_selected_path_outline_add_marker( marker_obj, m, Geom::Scale(i_style->stroke_width.computed), transform, g_repr, xml_doc, doc ); @@ -1127,7 +1127,7 @@ sp_selected_path_outline(SPDesktop *desktop) if ( path_it != pathv.begin() && ! ((path_it == (pathv.end()-1)) && (path_it->size_default() == 0)) ) // if this is the last path and it is a moveto-only, there is no mid marker there { - Geom::Matrix const m (sp_shape_marker_get_transform_at_start(path_it->front())); + Geom::Affine const m (sp_shape_marker_get_transform_at_start(path_it->front())); sp_selected_path_outline_add_marker( midmarker_obj, m, Geom::Scale(i_style->stroke_width.computed), transform, g_repr, xml_doc, doc ); @@ -1142,7 +1142,7 @@ sp_selected_path_outline(SPDesktop *desktop) * Loop to end_default (so including closing segment), because when a path is closed, * there should be a midpoint marker between last segment and closing straight line segment */ - Geom::Matrix const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2)); + Geom::Affine const m (sp_shape_marker_get_transform(*curve_it1, *curve_it2)); sp_selected_path_outline_add_marker(midmarker_obj, m, Geom::Scale(i_style->stroke_width.computed), transform, g_repr, xml_doc, doc); @@ -1154,7 +1154,7 @@ sp_selected_path_outline(SPDesktop *desktop) // END position if ( path_it != (pathv.end()-1) && !path_it->empty()) { Geom::Curve const &lastcurve = path_it->back_default(); - Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve); + Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve); sp_selected_path_outline_add_marker( midmarker_obj, m, Geom::Scale(i_style->stroke_width.computed), transform, g_repr, xml_doc, doc ); @@ -1173,7 +1173,7 @@ sp_selected_path_outline(SPDesktop *desktop) } Geom::Curve const &lastcurve = path_last[index]; - Geom::Matrix const m = sp_shape_marker_get_transform_at_end(lastcurve); + Geom::Affine const m = sp_shape_marker_get_transform_at_end(lastcurve); sp_selected_path_outline_add_marker( marker_obj, m, Geom::Scale(i_style->stroke_width.computed), transform, g_repr, xml_doc, doc ); @@ -1327,7 +1327,7 @@ sp_selected_path_create_offset_object(SPDesktop *desktop, int expand, bool updat return; } - Geom::Matrix const transform(item->transform); + Geom::Affine const transform(item->transform); item->doWriteTransform(SP_OBJECT_REPR(item), Geom::identity()); @@ -1555,7 +1555,7 @@ sp_selected_path_do_offset(SPDesktop *desktop, bool expand, double prefOffset) continue; } - Geom::Matrix const transform(item->transform); + Geom::Affine const transform(item->transform); item->doWriteTransform(SP_OBJECT_REPR(item), Geom::identity()); @@ -1802,7 +1802,7 @@ sp_selected_path_simplify_item(SPDesktop *desktop, size /= item->i2doc_affine().descrim(); // save the transform, to re-apply it after simplification - Geom::Matrix const transform(item->transform); + Geom::Affine const transform(item->transform); /* reset the transform, effectively transforming the item by transform.inverse(); @@ -2089,7 +2089,7 @@ Path_for_item(SPItem *item, bool doTransformation, bool transformFull) * 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::Matrix extraPreAffine, Geom::Matrix extraPostAffine) +pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool transformFull, Geom::Affine extraPreAffine, Geom::Affine extraPostAffine) { if (curve == NULL) return NULL; @@ -2101,7 +2101,7 @@ pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool t if (transformFull) { *dest *= extraPreAffine * item->i2doc_affine() * extraPostAffine; } else { - *dest *= extraPreAffine * (Geom::Matrix)item->transform * extraPostAffine; + *dest *= extraPreAffine * (Geom::Affine)item->transform * extraPostAffine; } } else { *dest *= extraPreAffine * extraPostAffine; diff --git a/src/splivarot.h b/src/splivarot.h index d85ae030a..ea8183b67 100644 --- a/src/splivarot.h +++ b/src/splivarot.h @@ -49,7 +49,7 @@ Geom::PathVector* item_outline(SPItem const *item); void sp_selected_path_simplify (SPDesktop *desktop); Path *Path_for_item(SPItem *item, bool doTransformation, bool transformFull = true); -Geom::PathVector* pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool transformFull, Geom::Matrix extraPreAffine, Geom::Matrix extraPostAffine); +Geom::PathVector* pathvector_for_curve(SPItem *item, SPCurve *curve, bool doTransformation, bool transformFull, Geom::Affine extraPreAffine, Geom::Affine extraPostAffine); SPCurve *curve_for_item(SPItem *item); boost::optional get_nearest_position_on_Path(Path *path, Geom::Point p, unsigned seg = 0); Geom::Point get_point_on_Path(Path *path, int piece, double t); diff --git a/src/spray-context.cpp b/src/spray-context.cpp index 6d19cbce4..244c52fad 100644 --- a/src/spray-context.cpp +++ b/src/spray-context.cpp @@ -151,9 +151,9 @@ void sp_spray_rotate_rel(Geom::Point c,SPDesktop */*desktop*/,SPItem *item, Geom { Geom::Point center = c; Geom::Translate const s(c); - Geom::Matrix affine = Geom::Matrix(s).inverse() * Geom::Matrix(rotation) * Geom::Matrix(s); + Geom::Affine affine = Geom::Affine(s).inverse() * Geom::Affine(rotation) * Geom::Affine(s); // Rotate item. - item->set_i2d_affine(item->i2d_affine() * (Geom::Matrix)affine); + item->set_i2d_affine(item->i2d_affine() * (Geom::Affine)affine); // Use each item's own transform writer, consistent with sp_selection_apply_affine() item->doWriteTransform(SP_OBJECT_REPR(item), item->transform); // Restore the center position (it's changed because the bbox center changed) @@ -679,7 +679,7 @@ bool sp_spray_dilate(SPSprayContext *tc, Geom::Point /*event_p*/, Geom::Point p, void sp_spray_update_area(SPSprayContext *tc) { double radius = get_dilate_radius(tc); - Geom::Matrix const sm ( Geom::Scale(radius/(1-tc->ratio), radius/(1+tc->ratio)) ); + Geom::Affine const sm ( Geom::Scale(radius/(1-tc->ratio), radius/(1+tc->ratio)) ); sp_canvas_item_affine_absolute(tc->dilate_area, (sm* Geom::Rotate(tc->tilt))* Geom::Translate(SP_EVENT_CONTEXT(tc)->desktop->point())); sp_canvas_item_show(tc->dilate_area); } @@ -763,7 +763,7 @@ gint sp_spray_context_root_handler(SPEventContext *event_context, // draw the dilating cursor double radius = get_dilate_radius(tc); - Geom::Matrix const sm (Geom::Scale(radius/(1-tc->ratio), radius/(1+tc->ratio)) ); + Geom::Affine const sm (Geom::Scale(radius/(1-tc->ratio), radius/(1+tc->ratio)) ); sp_canvas_item_affine_absolute(tc->dilate_area, (sm*Geom::Rotate(tc->tilt))*Geom::Translate(desktop->w2d(motion_w))); sp_canvas_item_show(tc->dilate_area); diff --git a/src/svg/svg-affine-test.h b/src/svg/svg-affine-test.h index be5a941bb..11b9012a8 100644 --- a/src/svg/svg-affine-test.h +++ b/src/svg/svg-affine-test.h @@ -2,7 +2,7 @@ #include "svg/svg.h" #include "streq.h" -#include <2geom/matrix.h> +#include <2geom/affine.h> #include #include #include @@ -14,10 +14,10 @@ class SvgAffineTest : public CxxTest::TestSuite private: struct test_t { char const * str; - Geom::Matrix matrix; + Geom::Affine matrix; }; struct approx_equal_pred { - bool operator()(Geom::Matrix const &ref, Geom::Matrix const &cm) const + bool operator()(Geom::Affine const &ref, Geom::Affine const &cm) const { double maxabsdiff = 0; for(size_t i=0; i<6; i++) { @@ -59,7 +59,7 @@ public: "skewY(0)"}; size_t n = G_N_ELEMENTS(strs); for(size_t i=0; i(c)) { - str.arcTo( svg_elliptical_arc->ray(0), svg_elliptical_arc->ray(1), - Geom::rad_to_deg(svg_elliptical_arc->rotation_angle()), - svg_elliptical_arc->large_arc_flag(), svg_elliptical_arc->sweep_flag(), + str.arcTo( svg_elliptical_arc->ray(Geom::X), svg_elliptical_arc->ray(Geom::Y), + Geom::rad_to_deg(svg_elliptical_arc->rotationAngle()), + svg_elliptical_arc->largeArc(), svg_elliptical_arc->sweep(), svg_elliptical_arc->finalPoint() ); } else if(Geom::HLineSegment const *hline_segment = dynamic_cast(c)) { diff --git a/src/svg/svg.h b/src/svg/svg.h index 237a5d348..d5335e1b4 100644 --- a/src/svg/svg.h +++ b/src/svg/svg.h @@ -54,10 +54,10 @@ unsigned int sp_svg_length_read_ldd( const gchar *str, SVGLength::Unit *unit, do std::string sp_svg_length_write_with_units(SVGLength const &length); -bool sp_svg_transform_read(gchar const *str, Geom::Matrix *transform); +bool sp_svg_transform_read(gchar const *str, Geom::Affine *transform); -gchar *sp_svg_transform_write(Geom::Matrix const &transform); -gchar *sp_svg_transform_write(Geom::Matrix const *transform); +gchar *sp_svg_transform_write(Geom::Affine const &transform); +gchar *sp_svg_transform_write(Geom::Affine const *transform); double sp_svg_read_percentage( const char * str, double def ); diff --git a/src/text-editing.cpp b/src/text-editing.cpp index 2e6e2f9fa..fb9e2e6a3 100644 --- a/src/text-editing.cpp +++ b/src/text-editing.cpp @@ -87,7 +87,7 @@ bool sp_te_input_is_empty(SPObject const *item) Inkscape::Text::Layout::iterator sp_te_get_position_by_coords (SPItem const *item, Geom::Point const &i_p) { - Geom::Matrix im (item->i2d_affine ()); + Geom::Affine im (item->i2d_affine ()); im = im.inverse(); Geom::Point p = i_p * im; @@ -95,7 +95,7 @@ sp_te_get_position_by_coords (SPItem const *item, Geom::Point const &i_p) return layout->getNearestCursorPositionTo(p); } -std::vector sp_te_create_selection_quads(SPItem const *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, Geom::Matrix const &transform) +std::vector sp_te_create_selection_quads(SPItem const *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, Geom::Affine const &transform) { if (start == end) return std::vector(); @@ -979,7 +979,7 @@ sp_te_adjust_kerning_screen (SPItem *item, Inkscape::Text::Layout::iterator cons // divide increment by zoom // divide increment by matrix expansion gdouble factor = 1 / desktop->current_zoom(); - Geom::Matrix t (item->i2doc_affine()); + Geom::Affine t (item->i2doc_affine()); factor = factor / t.descrim(); by = factor * by; @@ -1037,7 +1037,7 @@ sp_te_adjust_rotation_screen(SPItem *text, Inkscape::Text::Layout::iterator cons // divide increment by zoom // divide increment by matrix expansion gdouble factor = 1 / desktop->current_zoom(); - Geom::Matrix t (text->i2doc_affine()); + Geom::Affine t (text->i2doc_affine()); factor = factor / t.descrim(); Inkscape::Text::Layout const *layout = te_get_layout(text); if (layout == NULL) return; @@ -1215,7 +1215,7 @@ sp_te_adjust_linespacing_screen (SPItem *text, Inkscape::Text::Layout::iterator gdouble zby = by / (desktop->current_zoom() * (line_count == 0 ? 1 : line_count)); // divide increment by matrix expansion - Geom::Matrix t (SP_ITEM(text)->i2doc_affine ()); + Geom::Affine t (SP_ITEM(text)->i2doc_affine ()); zby = zby / t.descrim(); switch (style->line_height.unit) { @@ -1908,7 +1908,7 @@ void sp_te_apply_style(SPItem *text, Inkscape::Text::Layout::iterator const &sta SPCSSAttr *css_set = sp_repr_css_attr_new(); sp_repr_css_merge(css_set, (SPCSSAttr*) css); { - Geom::Matrix const local(SP_ITEM(common_ancestor)->i2doc_affine()); + Geom::Affine const local(SP_ITEM(common_ancestor)->i2doc_affine()); double const ex(local.descrim()); if ( ( ex != 0. ) && ( ex != 1. ) ) { diff --git a/src/text-editing.h b/src/text-editing.h index 3d5efbbec..529b25ff5 100644 --- a/src/text-editing.h +++ b/src/text-editing.h @@ -43,7 +43,7 @@ unsigned sp_text_get_length(SPObject const *item); \a item, before and not including \a upto. Also adds 1 for each line break encountered. */ unsigned sp_text_get_length_upto(SPObject const *item, SPObject const *upto); -std::vector sp_te_create_selection_quads(SPItem const *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, Geom::Matrix const &transform); +std::vector sp_te_create_selection_quads(SPItem const *item, Inkscape::Text::Layout::iterator const &start, Inkscape::Text::Layout::iterator const &end, Geom::Affine const &transform); Inkscape::Text::Layout::iterator sp_te_get_position_by_coords (SPItem const *item, Geom::Point const &i_p); void sp_te_get_cursor_coords (SPItem const *item, Inkscape::Text::Layout::iterator const &position, Geom::Point &p0, Geom::Point &p1); diff --git a/src/text-tag-attributes.h b/src/text-tag-attributes.h index 11b751a2c..fdcfa8ce0 100644 --- a/src/text-tag-attributes.h +++ b/src/text-tag-attributes.h @@ -88,7 +88,7 @@ public: If \a extend_zero_length is true, then if the x or y vectors are empty they will be made length 1 in order to store the newly calculated position. */ - void transform(Geom::Matrix const &matrix, double scale_x, double scale_y, bool extend_zero_length = false); + void transform(Geom::Affine const &matrix, double scale_x, double scale_y, bool extend_zero_length = false); /** Gets current value of dx vector at \a index. */ double getDx(unsigned index); diff --git a/src/trace/trace.cpp b/src/trace/trace.cpp index 48d25d0c4..1ee32e6bf 100644 --- a/src/trace/trace.cpp +++ b/src/trace/trace.cpp @@ -515,7 +515,7 @@ void Tracer::traceThread() Geom::Scale scal(iwscale, ihscale); //# Convolve scale, translation, and the original transform - Geom::Matrix tf(scal * trans); + Geom::Affine tf(scal * trans); tf *= img->transform; diff --git a/src/transf_mat_3x4.cpp b/src/transf_mat_3x4.cpp index 533972e29..20eee658c 100644 --- a/src/transf_mat_3x4.cpp +++ b/src/transf_mat_3x4.cpp @@ -13,7 +13,7 @@ #include "transf_mat_3x4.h" #include -#include <2geom/matrix.h> +#include <2geom/affine.h> #include "svg/stringstream.h" #include "syseq.h" #include "document.h" @@ -133,7 +133,7 @@ TransfMat3x4::operator==(const TransfMat3x4 &rhs) const /* Multiply a projective matrix by an affine matrix (by only multiplying the 'affine part' of the * projective matrix) */ TransfMat3x4 -TransfMat3x4::operator*(Geom::Matrix const &A) const { +TransfMat3x4::operator*(Geom::Affine const &A) const { TransfMat3x4 ret; for (int j = 0; j < 4; ++j) { @@ -148,7 +148,7 @@ TransfMat3x4::operator*(Geom::Matrix const &A) const { // FIXME: Shouldn't rather operator* call operator*= for efficiency? (Because in operator*= // there is in principle no need to create a temporary object, which happens in the assignment) TransfMat3x4 & -TransfMat3x4::operator*=(Geom::Matrix const &A) { +TransfMat3x4::operator*=(Geom::Affine const &A) { *this = *this * A; return *this; } diff --git a/src/transf_mat_3x4.h b/src/transf_mat_3x4.h index 6229f61aa..69174d9df 100644 --- a/src/transf_mat_3x4.h +++ b/src/transf_mat_3x4.h @@ -47,8 +47,8 @@ public: gchar * pt_to_str (Proj::Axis axis); bool operator==(const TransfMat3x4 &rhs) const; - TransfMat3x4 operator*(Geom::Matrix const &A) const; - TransfMat3x4 &operator*=(Geom::Matrix const &A); + TransfMat3x4 operator*(Geom::Affine const &A) const; + TransfMat3x4 &operator*=(Geom::Affine const &A); void print() const; diff --git a/src/tweak-context.cpp b/src/tweak-context.cpp index 3b93c659b..999ee877f 100644 --- a/src/tweak-context.cpp +++ b/src/tweak-context.cpp @@ -582,7 +582,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P Shape *theShape = new Shape; Shape *theRes = new Shape; - Geom::Matrix i2doc(item->i2doc_affine()); + Geom::Affine i2doc(item->i2doc_affine()); orig->ConvertWithBackData((0.08 - (0.07 * fidelity)) / i2doc.descrim()); // default 0.059 orig->Fill(theShape, 0); @@ -803,7 +803,7 @@ tweak_colors_in_gradient (SPItem *item, bool fill_or_stroke, if (!gradient || !SP_IS_GRADIENT(gradient)) return; - Geom::Matrix i2d (item->i2doc_affine ()); + Geom::Affine i2d (item->i2doc_affine ()); Geom::Point p = p_w * i2d.inverse(); p *= (gradient->gradientTransform).inverse(); // now p is in gradient's original coordinates @@ -820,7 +820,7 @@ tweak_colors_in_gradient (SPItem *item, bool fill_or_stroke, // This is the matrix which moves and rotates the gradient line // so it's oriented along the X axis: - Geom::Matrix norm = Geom::Matrix(Geom::Translate(-p1)) * Geom::Matrix(Geom::Rotate(-atan2(pdiff[Geom::Y], pdiff[Geom::X]))); + Geom::Affine norm = Geom::Affine(Geom::Translate(-p1)) * Geom::Affine(Geom::Rotate(-atan2(pdiff[Geom::Y], pdiff[Geom::X]))); // Transform the mouse point by it to find out its projection onto the gradient line: Geom::Point pnorm = p * norm; @@ -979,7 +979,7 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point, } double blur_now = 0; - Geom::Matrix i2d = item->i2d_affine (); + Geom::Affine i2d = item->i2d_affine (); if (style->filter.set && style->getFilter()) { //cycle through filter primitives SPObject *primitive_obj = style->getFilter()->children; @@ -1140,7 +1140,7 @@ void sp_tweak_update_area (SPTweakContext *tc) { double radius = get_dilate_radius(tc); - Geom::Matrix const sm (Geom::Scale(radius, radius) * Geom::Translate(SP_EVENT_CONTEXT(tc)->desktop->point())); + Geom::Affine const sm (Geom::Scale(radius, radius) * Geom::Translate(SP_EVENT_CONTEXT(tc)->desktop->point())); sp_canvas_item_affine_absolute(tc->dilate_area, sm); sp_canvas_item_show(tc->dilate_area); } @@ -1216,7 +1216,7 @@ sp_tweak_context_root_handler(SPEventContext *event_context, // draw the dilating cursor double radius = get_dilate_radius(tc); - Geom::Matrix const sm (Geom::Scale(radius, radius) * Geom::Translate(desktop->w2d(motion_w))); + Geom::Affine const sm (Geom::Scale(radius, radius) * Geom::Translate(desktop->w2d(motion_w))); sp_canvas_item_affine_absolute(tc->dilate_area, sm); sp_canvas_item_show(tc->dilate_area); diff --git a/src/ui/cache/svg_preview_cache.cpp b/src/ui/cache/svg_preview_cache.cpp index 6e05f6c03..a7ad1701d 100644 --- a/src/ui/cache/svg_preview_cache.cpp +++ b/src/ui/cache/svg_preview_cache.cpp @@ -34,7 +34,7 @@ GdkPixbuf* render_pixbuf(NRArenaItem* root, double scale_factor, const Geom::Rect& dbox, unsigned psize) { NRGC gc(NULL); - Geom::Matrix t(Geom::Scale(scale_factor, scale_factor)); + Geom::Affine t(Geom::Scale(scale_factor, scale_factor)); nr_arena_item_set_transform(root, t); gc.transform.setIdentity(); diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index d405afb8f..1b98d7474 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -844,7 +844,7 @@ void ClipboardManagerImpl::_pasteDocument(SPDesktop *desktop, SPDocument *clipdo selection->setReprList(pasted_objects); // invers apply parent transform - Geom::Matrix doc2parent = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); + Geom::Affine doc2parent = SP_ITEM(desktop->currentLayer())->i2doc_affine().inverse(); sp_selection_apply_affine(selection, desktop->dt2doc() * doc2parent * desktop->doc2dt(), true, false); // Update (among other things) all curves in paths, for bounds() to work diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp index ca3a99561..e5175be4c 100644 --- a/src/ui/dialog/filedialogimpl-win32.cpp +++ b/src/ui/dialog/filedialogimpl-win32.cpp @@ -949,7 +949,7 @@ bool FileOpenDialogImplWin32::set_svg_preview() arena, key, SP_ITEM_SHOW_DISPLAY); NRGC gc(NULL); - gc.transform = Geom::Matrix(Geom::Scale(scaleFactor, scaleFactor)); + gc.transform = Geom::Affine(Geom::Scale(scaleFactor, scaleFactor)); nr_arena_item_invoke_update (root, NULL, &gc, NR_ARENA_ITEM_STATE_ALL, NR_ARENA_ITEM_STATE_NONE); diff --git a/src/ui/dialog/svg-fonts-dialog.cpp b/src/ui/dialog/svg-fonts-dialog.cpp index 042acb6e1..a7f914327 100644 --- a/src/ui/dialog/svg-fonts-dialog.cpp +++ b/src/ui/dialog/svg-fonts-dialog.cpp @@ -498,7 +498,7 @@ void SvgFontsDialog::set_glyph_description_from_selected_path(){ Geom::PathVector pathv = sp_svg_read_pathv(node->attribute("d")); //This matrix flips the glyph vertically - Geom::Matrix m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(0)); + Geom::Affine m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(0)); pathv*=m; //then we offset it pathv+=Geom::Point(Geom::Coord(0),Geom::Coord(get_selected_spfont()->horiz_adv_x)); @@ -543,7 +543,7 @@ void SvgFontsDialog::missing_glyph_description_from_selected_path(){ Geom::PathVector pathv = sp_svg_read_pathv(node->attribute("d")); //This matrix flips the glyph vertically - Geom::Matrix m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(0)); + Geom::Affine m(Geom::Coord(1),Geom::Coord(0),Geom::Coord(0),Geom::Coord(-1),Geom::Coord(0),Geom::Coord(0)); pathv*=m; //then we offset it // pathv+=Geom::Point(Geom::Coord(0),Geom::Coord(get_selected_spfont()->horiz_adv_x)); diff --git a/src/ui/dialog/tile.cpp b/src/ui/dialog/tile.cpp index 4b994335e..8ae81d528 100644 --- a/src/ui/dialog/tile.cpp +++ b/src/ui/dialog/tile.cpp @@ -336,7 +336,7 @@ g_print("\n row = %f col = %f selection x= %f selection y = %f", total_row_h // signs are inverted between x and y due to y inversion Geom::Point move = Geom::Point(new_x - min[Geom::X], min[Geom::Y] - new_y); - Geom::Matrix const affine = Geom::Matrix(Geom::Translate(move)); + Geom::Affine const affine = Geom::Affine(Geom::Translate(move)); item->set_i2d_affine(item->i2d_affine() * affine); item->doWriteTransform(repr, item->transform, NULL); SP_OBJECT (current_row->data)->updateRepr(); diff --git a/src/ui/dialog/transformation.cpp b/src/ui/dialog/transformation.cpp index 8da9914bc..38664fd3a 100644 --- a/src/ui/dialog/transformation.cpp +++ b/src/ui/dialog/transformation.cpp @@ -539,9 +539,9 @@ Transformation::updatePageTransform(Inkscape::Selection *selection) { if (selection && !selection->isEmpty()) { if (_check_replace_matrix.get_active()) { - Geom::Matrix current (SP_ITEM(selection->itemList()->data)->transform); // take from the first item in selection + Geom::Affine current (SP_ITEM(selection->itemList()->data)->transform); // take from the first item in selection - Geom::Matrix new_displayed = current; + Geom::Affine new_displayed = current; _scalar_transform_a.setValue(new_displayed[0]); _scalar_transform_b.setValue(new_displayed[1]); @@ -841,7 +841,7 @@ Transformation::applyPageTransform(Inkscape::Selection *selection) double e = _scalar_transform_e.getValue(); double f = _scalar_transform_f.getValue(); - Geom::Matrix displayed(a, b, c, d, e, f); + Geom::Affine displayed(a, b, c, d, e, f); if (_check_replace_matrix.get_active()) { for (GSList const *l = selection->itemList(); l != NULL; l = l->next) { @@ -989,10 +989,10 @@ Transformation::onReplaceMatrixToggled() double e = _scalar_transform_e.getValue(); double f = _scalar_transform_f.getValue(); - Geom::Matrix displayed (a, b, c, d, e, f); - Geom::Matrix current = SP_ITEM(selection->itemList()->data)->transform; // take from the first item in selection + Geom::Affine displayed (a, b, c, d, e, f); + Geom::Affine current = SP_ITEM(selection->itemList()->data)->transform; // take from the first item in selection - Geom::Matrix new_displayed; + Geom::Affine new_displayed; if (_check_replace_matrix.get_active()) { new_displayed = current; } else { diff --git a/src/ui/tool/control-point-selection.cpp b/src/ui/tool/control-point-selection.cpp index 517e90da2..1fb98d78f 100644 --- a/src/ui/tool/control-point-selection.cpp +++ b/src/ui/tool/control-point-selection.cpp @@ -166,7 +166,7 @@ void ControlPointSelection::spatialGrow(SelectableControlPoint *origin, int dir) } /** Transform all selected control points by the given affine transformation. */ -void ControlPointSelection::transform(Geom::Matrix const &m) +void ControlPointSelection::transform(Geom::Affine const &m) { for (iterator i = _points.begin(); i != _points.end(); ++i) { SelectableControlPoint *cur = *i; @@ -273,7 +273,7 @@ void ControlPointSelection::_pointGrabbed(SelectableControlPoint *point) _grabbed_point = point; _farthest_point = point; double maxdist = 0; - Geom::Matrix m; + Geom::Affine m; m.setIdentity(); for (iterator i = _points.begin(); i != _points.end(); ++i) { _original_positions.insert(std::make_pair(*i, (*i)->position())); @@ -294,7 +294,7 @@ void ControlPointSelection::_pointDragged(Geom::Point &new_pos, GdkEventMotion * // Sculpting for (iterator i = _points.begin(); i != _points.end(); ++i) { SelectableControlPoint *cur = (*i); - Geom::Matrix trans; + Geom::Affine trans; trans.setIdentity(); double dist = Geom::distance(_original_positions[cur], _original_positions[_grabbed_point]); double deltafrac = 0.5 + 0.5 * cos(M_PI * dist/fdist); @@ -323,7 +323,7 @@ void ControlPointSelection::_pointDragged(Geom::Point &new_pos, GdkEventMotion * Geom::Point newdx = (newpx - newp) / Geom::EPSILON; Geom::Point newdy = (newpy - newp) / Geom::EPSILON; - Geom::Matrix itrans(newdx[Geom::X], newdx[Geom::Y], newdy[Geom::X], newdy[Geom::Y], 0, 0); + Geom::Affine itrans(newdx[Geom::X], newdx[Geom::Y], newdy[Geom::X], newdy[Geom::Y], 0, 0); if (itrans.isSingular()) itrans.setIdentity(); @@ -502,7 +502,7 @@ bool ControlPointSelection::_keyboardRotate(GdkEventKey const &event, int dir) } // translate to origin, rotate, translate back to original position - Geom::Matrix m = Geom::Translate(-rc) + Geom::Affine m = Geom::Translate(-rc) * Geom::Rotate(angle) * Geom::Translate(rc); transform(m); signal_commit.emit(COMMIT_KEYBOARD_ROTATE); @@ -538,7 +538,7 @@ bool ControlPointSelection::_keyboardScale(GdkEventKey const &event, int dir) } double scale = (maxext + length_change) / maxext; - Geom::Matrix m = Geom::Translate(-center) * Geom::Scale(scale) * Geom::Translate(center); + Geom::Affine m = Geom::Translate(-center) * Geom::Scale(scale) * Geom::Translate(center); transform(m); signal_commit.emit(COMMIT_KEYBOARD_SCALE_UNIFORM); return true; @@ -559,7 +559,7 @@ bool ControlPointSelection::_keyboardFlip(Geom::Dim2 d) dynamic_cast(ControlPoint::mouseovered_point); Geom::Point center = scp ? scp->position() : _handles->rotationCenter().position(); - Geom::Matrix m = Geom::Translate(-center) * scale_transform * Geom::Translate(center); + Geom::Affine m = Geom::Translate(-center) * scale_transform * Geom::Translate(center); transform(m); signal_commit.emit(d == Geom::X ? COMMIT_FLIP_X : COMMIT_FLIP_Y); return true; diff --git a/src/ui/tool/control-point-selection.h b/src/ui/tool/control-point-selection.h index 0e5acf6c5..a9c929cb1 100644 --- a/src/ui/tool/control-point-selection.h +++ b/src/ui/tool/control-point-selection.h @@ -91,7 +91,7 @@ public: virtual bool event(GdkEvent *); - void transform(Geom::Matrix const &m); + void transform(Geom::Affine const &m); void align(Geom::Dim2 d); void distribute(Geom::Dim2 d); @@ -130,14 +130,14 @@ private: bool _keyboardRotate(GdkEventKey const &, int); bool _keyboardScale(GdkEventKey const &, int); bool _keyboardFlip(Geom::Dim2); - void _keyboardTransform(Geom::Matrix const &); + void _keyboardTransform(Geom::Affine const &); void _commitHandlesTransform(CommitEvent ce); double _rotationRadius(Geom::Point const &); set_type _points; set_type _all_points; INK_UNORDERED_MAP _original_positions; - INK_UNORDERED_MAP _last_trans; + INK_UNORDERED_MAP _last_trans; boost::optional _rot_radius; boost::optional _mouseover_rot_radius; Geom::OptRect _bounds; diff --git a/src/ui/tool/control-point.cpp b/src/ui/tool/control-point.cpp index 38b421553..bece1324b 100644 --- a/src/ui/tool/control-point.cpp +++ b/src/ui/tool/control-point.cpp @@ -214,7 +214,7 @@ void ControlPoint::move(Geom::Point const &pos) /** Apply an arbitrary affine transformation to a control point. This is used * by ControlPointSelection, and is important for things like nodes with handles. * The default implementation simply moves the point according to the transform. */ -void ControlPoint::transform(Geom::Matrix const &m) { +void ControlPoint::transform(Geom::Affine const &m) { move(position() * m); } diff --git a/src/ui/tool/control-point.h b/src/ui/tool/control-point.h index 3f5fe668d..0b88786e5 100644 --- a/src/ui/tool/control-point.h +++ b/src/ui/tool/control-point.h @@ -56,7 +56,7 @@ public: operator Geom::Point const &() { return _position; } virtual void move(Geom::Point const &pos); virtual void setPosition(Geom::Point const &pos); - virtual void transform(Geom::Matrix const &m); + virtual void transform(Geom::Affine const &m); /// @} /// @name Toggle the point's visibility diff --git a/src/ui/tool/node.cpp b/src/ui/tool/node.cpp index fea02d399..8e3da266b 100644 --- a/src/ui/tool/node.cpp +++ b/src/ui/tool/node.cpp @@ -514,7 +514,7 @@ void Node::move(Geom::Point const &new_pos) _fixNeighbors(old_pos, new_pos); } -void Node::transform(Geom::Matrix const &m) +void Node::transform(Geom::Affine const &m) { Geom::Point old_pos = position(); setPosition(position() * m); @@ -829,26 +829,6 @@ bool Node::_eventHandler(GdkEvent *event) return ControlPoint::_eventHandler(event); } -// TODO Move this to 2Geom! -static double bezier_length (Geom::Point a0, Geom::Point a1, Geom::Point a2, Geom::Point a3) -{ - double lower = Geom::distance(a0, a3); - double upper = Geom::distance(a0, a1) + Geom::distance(a1, a2) + Geom::distance(a2, a3); - - if (upper - lower < Geom::EPSILON) return (lower + upper)/2; - - Geom::Point // Casteljau subdivision - b0 = a0, - c0 = a3, - b1 = 0.5*(a0 + a1), - t0 = 0.5*(a1 + a2), - c1 = 0.5*(a2 + a3), - b2 = 0.5*(b1 + t0), - c2 = 0.5*(t0 + c1), - b3 = 0.5*(b2 + c2); // == c3 - return bezier_length(b0, b1, b2, b3) + bezier_length(b3, c2, c1, c0); -} - /** Select or deselect a node in this node's subpath based on its path distance from this node. * @param dir If negative, shrink selection by one node; if positive, grow by one node */ void Node::_linearGrow(int dir) @@ -875,7 +855,7 @@ void Node::_linearGrow(int dir) // find first unselected nodes on both sides while (fwd && fwd->selected()) { NodeList::iterator n = fwd.next(); - distance_front += bezier_length(*fwd, fwd->_front, n->_back, *n); + distance_front += Geom::bezier_length(*fwd, fwd->_front, n->_back, *n); fwd = n; if (fwd == this_iter) // there is no unselected node in this cyclic subpath @@ -886,7 +866,7 @@ void Node::_linearGrow(int dir) // so we are guaranteed to stop. while (rev && rev->selected()) { NodeList::iterator p = rev.prev(); - distance_back += bezier_length(*rev, rev->_back, p->_front, *p); + distance_back += Geom::bezier_length(*rev, rev->_back, p->_front, *p); rev = p; } @@ -917,7 +897,7 @@ void Node::_linearGrow(int dir) last_distance_front = distance_front; } NodeList::iterator n = fwd.next(); - if (n) distance_front += bezier_length(*fwd, fwd->_front, n->_back, *n); + if (n) distance_front += Geom::bezier_length(*fwd, fwd->_front, n->_back, *n); fwd = n; } else if (rev && (!fwd || distance_front > distance_back)) { if (rev->selected()) { @@ -925,7 +905,7 @@ void Node::_linearGrow(int dir) last_distance_back = distance_back; } NodeList::iterator p = rev.prev(); - if (p) distance_back += bezier_length(*rev, rev->_back, p->_front, *p); + if (p) distance_back += Geom::bezier_length(*rev, rev->_back, p->_front, *p); rev = p; } // Check whether we walked the entire cyclic subpath. @@ -935,8 +915,8 @@ void Node::_linearGrow(int dir) if (fwd && fwd == rev) { if (!fwd->selected()) break; NodeList::iterator fwdp = fwd.prev(), revn = rev.next(); - double df = distance_front + bezier_length(*fwdp, fwdp->_front, fwd->_back, *fwd); - double db = distance_back + bezier_length(*revn, revn->_back, rev->_front, *rev); + double df = distance_front + Geom::bezier_length(*fwdp, fwdp->_front, fwd->_back, *fwd); + double db = distance_back + Geom::bezier_length(*revn, revn->_back, rev->_front, *rev); if (df > db) { last_fwd = fwd; last_distance_front = df; diff --git a/src/ui/tool/node.h b/src/ui/tool/node.h index b5d4d88f2..451915dbe 100644 --- a/src/ui/tool/node.h +++ b/src/ui/tool/node.h @@ -128,7 +128,7 @@ class Node : ListNode, public SelectableControlPoint { public: Node(NodeSharedData const &data, Geom::Point const &pos); virtual void move(Geom::Point const &p); - virtual void transform(Geom::Matrix const &m); + virtual void transform(Geom::Affine const &m); virtual Geom::Rect bounds(); NodeType type() { return _type; } diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index ea7f3412d..47e28a788 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -102,7 +102,7 @@ private: void build_segment(Geom::PathBuilder &, Node *, Node *); PathManipulator::PathManipulator(MultiPathManipulator &mpm, SPPath *path, - Geom::Matrix const &et, guint32 outline_color, Glib::ustring lpe_key) + Geom::Affine const &et, guint32 outline_color, Glib::ustring lpe_key) : PointManipulator(mpm._path_data.node_data.desktop, *mpm._path_data.node_data.selection) , _subpaths(*this) , _multi_path_manipulator(mpm) @@ -847,9 +847,9 @@ void PathManipulator::setLiveObjects(bool set) _live_objects = set; } -void PathManipulator::setControlsTransform(Geom::Matrix const &tnew) +void PathManipulator::setControlsTransform(Geom::Affine const &tnew) { - Geom::Matrix delta = _i2d_transform.inverse() * _edit_transform.inverse() * tnew * _i2d_transform; + Geom::Affine delta = _i2d_transform.inverse() * _edit_transform.inverse() * tnew * _i2d_transform; _edit_transform = tnew; for (SubpathList::iterator i = _subpaths.begin(); i != _subpaths.end(); ++i) { for (NodeList::iterator j = (*i)->begin(); j != (*i)->end(); ++j) { @@ -894,7 +894,7 @@ NodeList::iterator PathManipulator::subdivideSegment(NodeList::iterator first, d // build bezier curve and subdivide Geom::CubicBezier temp(first->position(), first->front()->position(), second->back()->position(), second->position()); - std::pair div = temp.subdivide(t); + std::pair div = temp.subdivide(t); std::vector seg1 = div.first.points(), seg2 = div.second.points(); // set new handle positions @@ -975,7 +975,7 @@ void PathManipulator::_externalChange(unsigned type) _updateOutline(); } break; case PATH_CHANGE_TRANSFORM: { - Geom::Matrix i2d_change = _d2i_transform; + Geom::Affine i2d_change = _d2i_transform; _i2d_transform = SP_ITEM(_path)->i2d_affine(); _d2i_transform = _i2d_transform.inverse(); i2d_change *= _i2d_transform; @@ -1388,7 +1388,7 @@ void PathManipulator::_commit(Glib::ustring const &annotation, gchar const *key) * point of the path. */ void PathManipulator::_updateDragPoint(Geom::Point const &evp) { - Geom::Matrix to_desktop = _edit_transform * _i2d_transform; + Geom::Affine to_desktop = _edit_transform * _i2d_transform; Geom::PathVector pv = _spcurve->get_pathvector(); boost::optional pvp = Geom::nearestPoint(pv, _desktop->w2d(evp) * to_desktop.inverse()); diff --git a/src/ui/tool/path-manipulator.h b/src/ui/tool/path-manipulator.h index 58907ea96..27a83f06b 100644 --- a/src/ui/tool/path-manipulator.h +++ b/src/ui/tool/path-manipulator.h @@ -14,7 +14,7 @@ #include #include #include <2geom/pathvector.h> -#include <2geom/matrix.h> +#include <2geom/affine.h> #include #include #include "forward.h" @@ -53,7 +53,7 @@ class PathManipulator : public PointManipulator { public: typedef SPPath *ItemType; - PathManipulator(MultiPathManipulator &mpm, SPPath *path, Geom::Matrix const &edit_trans, + PathManipulator(MultiPathManipulator &mpm, SPPath *path, Geom::Affine const &edit_trans, guint32 outline_color, Glib::ustring lpe_key); ~PathManipulator(); virtual bool event(GdkEvent *); @@ -85,7 +85,7 @@ public: void showPathDirection(bool show); void setLiveOutline(bool set); void setLiveObjects(bool set); - void setControlsTransform(Geom::Matrix const &); + void setControlsTransform(Geom::Affine const &); void hideDragPoint(); MultiPathManipulator &mpm() { return _multi_path_manipulator; } @@ -134,9 +134,9 @@ private: SPCanvasItem *_outline; CurveDragPoint *_dragpoint; // an invisible control point hoverng over curve PathManipulatorObserver *_observer; - Geom::Matrix _d2i_transform; ///< desktop-to-item transform - Geom::Matrix _i2d_transform; ///< item-to-desktop transform, inverse of _d2i_transform - Geom::Matrix _edit_transform; ///< additional transform to apply to editing controls + Geom::Affine _d2i_transform; ///< desktop-to-item transform + Geom::Affine _i2d_transform; ///< item-to-desktop transform, inverse of _d2i_transform + Geom::Affine _edit_transform; ///< additional transform to apply to editing controls unsigned _num_selected; ///< number of selected nodes bool _show_handles; bool _show_outline; diff --git a/src/ui/tool/shape-record.h b/src/ui/tool/shape-record.h index 893231404..646e6f4f6 100644 --- a/src/ui/tool/shape-record.h +++ b/src/ui/tool/shape-record.h @@ -14,7 +14,7 @@ #include #include -#include <2geom/matrix.h> +#include <2geom/affine.h> class SPItem; namespace Inkscape { @@ -32,7 +32,7 @@ struct ShapeRecord : public boost::totally_ordered { SPItem *item; // SP node for the edited shape - Geom::Matrix edit_transform; // how to transform controls - used for clipping paths and masks + Geom::Affine edit_transform; // how to transform controls - used for clipping paths and masks ShapeRole role; Glib::ustring lpe_key; // name of LPE shape param being edited diff --git a/src/ui/tool/transform-handle-set.cpp b/src/ui/tool/transform-handle-set.cpp index 5c3b494ce..26263c26b 100644 --- a/src/ui/tool/transform-handle-set.cpp +++ b/src/ui/tool/transform-handle-set.cpp @@ -94,10 +94,10 @@ public: protected: virtual void startTransform() {} virtual void endTransform() {} - virtual Geom::Matrix computeTransform(Geom::Point const &pos, GdkEventMotion *event) = 0; + virtual Geom::Affine computeTransform(Geom::Point const &pos, GdkEventMotion *event) = 0; virtual CommitEvent getCommitEvent() = 0; - Geom::Matrix _last_transform; + Geom::Affine _last_transform; Geom::Point _origin; TransformHandleSet &_th; std::vector _snap_points; @@ -129,10 +129,10 @@ private: } virtual void dragged(Geom::Point &new_pos, GdkEventMotion *event) { - Geom::Matrix t = computeTransform(new_pos, event); + Geom::Affine t = computeTransform(new_pos, event); // protect against degeneracies if (t.isSingular()) return; - Geom::Matrix incr = _last_transform.inverse() * t; + Geom::Affine incr = _last_transform.inverse() * t; if (incr.isSingular()) return; _th.signal_transform.emit(incr); _last_transform = t; @@ -202,7 +202,7 @@ protected: ControlPointSelection *selection = nt->_selected_nodes.get(); selection->setOriginalPoints(); } - virtual Geom::Matrix computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) { + virtual Geom::Affine computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) { Geom::Point scc = held_shift(*event) ? _sc_center : _sc_opposite; Geom::Point vold = _origin - scc, vnew = new_pos - scc; @@ -257,7 +257,7 @@ protected: _last_scale_x = scale[0]; _last_scale_y = scale[1]; - Geom::Matrix t = Geom::Translate(-scc) + Geom::Affine t = Geom::Translate(-scc) * Geom::Scale(scale[0], scale[1]) * Geom::Translate(scc); return t; @@ -294,7 +294,7 @@ protected: _sc_opposite = Geom::middle_point(b.corner(_side + 2), b.corner(_side + 3)); _last_scale_x = _last_scale_y = 1.0; } - virtual Geom::Matrix computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) { + virtual Geom::Affine computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) { Geom::Point scc = held_shift(*event) ? _sc_center : _sc_opposite; Geom::Point vs; Geom::Dim2 d1 = static_cast((_side + 1) % 2); @@ -313,7 +313,7 @@ protected: _last_scale_x = vs[Geom::X]; _last_scale_y = vs[Geom::Y]; - Geom::Matrix t = Geom::Translate(-scc) + Geom::Affine t = Geom::Translate(-scc) * Geom::Scale(vs) * Geom::Translate(scc); return t; @@ -351,7 +351,7 @@ protected: _last_angle = 0; } - virtual Geom::Matrix computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) + virtual Geom::Affine computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) { Geom::Point rotc = held_shift(*event) ? _rot_opposite : _rot_center; double angle = Geom::angle_between(_origin - rotc, new_pos - rotc); @@ -359,7 +359,7 @@ protected: angle = snap_angle(angle); } _last_angle = angle; - Geom::Matrix t = Geom::Translate(-rotc) + Geom::Affine t = Geom::Translate(-rotc) * Geom::Rotate(angle) * Geom::Translate(rotc); return t; @@ -425,7 +425,7 @@ protected: _last_horizontal = _side % 2; } - virtual Geom::Matrix computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) + virtual Geom::Affine computeTransform(Geom::Point const &new_pos, GdkEventMotion *event) { Geom::Point scc = held_shift(*event) ? _skew_center : _skew_opposite; // d1 and d2 are reversed with respect to ScaleSideHandle @@ -458,12 +458,12 @@ protected: // skew matrix has the from [[1, k],[0, 1]] for horizontal skew // and [[1,0],[k,1]] for vertical skew. - Geom::Matrix skew = Geom::identity(); + Geom::Affine skew = Geom::identity(); // correct the sign of the tangent skew[d2 + 1] = (d1 == Geom::X ? -1.0 : 1.0) * tan(angle); _last_angle = angle; - Geom::Matrix t = Geom::Translate(-scc) + Geom::Affine t = Geom::Translate(-scc) * Geom::Scale(scale) * skew * Geom::Translate(scc); return t; @@ -645,7 +645,7 @@ bool TransformHandleSet::event(GdkEvent*) return false; } -void TransformHandleSet::_emitTransform(Geom::Matrix const &t) +void TransformHandleSet::_emitTransform(Geom::Affine const &t) { signal_transform.emit(t); _center->transform(t); diff --git a/src/ui/tool/transform-handle-set.h b/src/ui/tool/transform-handle-set.h index b18c598ee..0557b1278 100644 --- a/src/ui/tool/transform-handle-set.h +++ b/src/ui/tool/transform-handle-set.h @@ -50,10 +50,10 @@ public: bool transforming() { return _in_transform; } ControlPoint &rotationCenter(); - sigc::signal signal_transform; + sigc::signal signal_transform; sigc::signal signal_commit; private: - void _emitTransform(Geom::Matrix const &); + void _emitTransform(Geom::Affine const &); void _setActiveHandle(ControlPoint *h); void _clearActiveHandle(); void _updateVisibility(bool v); diff --git a/src/ui/widget/registered-widget.cpp b/src/ui/widget/registered-widget.cpp index 04bd27285..c68e8348b 100644 --- a/src/ui/widget/registered-widget.cpp +++ b/src/ui/widget/registered-widget.cpp @@ -553,7 +553,7 @@ RegisteredTransformedPoint::setValue(Geom::Point const & p) } void -RegisteredTransformedPoint::setTransform(Geom::Matrix const & canvas_to_svg) +RegisteredTransformedPoint::setTransform(Geom::Affine const & canvas_to_svg) { // check if matrix is singular / has inverse if ( ! canvas_to_svg.isSingular() ) { diff --git a/src/ui/widget/registered-widget.h b/src/ui/widget/registered-widget.h index efb5eb70e..9c3ecb5e6 100644 --- a/src/ui/widget/registered-widget.h +++ b/src/ui/widget/registered-widget.h @@ -18,7 +18,7 @@ #include #include #include -#include <2geom/matrix.h> +#include <2geom/affine.h> #include "xml/node.h" #include "registry.h" @@ -326,14 +326,14 @@ public: // redefine setValue, because transform must be applied void setValue(Geom::Point const & p); - void setTransform(Geom::Matrix const & canvas_to_svg); + void setTransform(Geom::Affine const & canvas_to_svg); protected: sigc::connection _value_x_changed_connection; sigc::connection _value_y_changed_connection; void on_value_changed(); - Geom::Matrix to_svg; + Geom::Affine to_svg; }; diff --git a/src/unclump.cpp b/src/unclump.cpp index 1039351a3..951719900 100644 --- a/src/unclump.cpp +++ b/src/unclump.cpp @@ -287,7 +287,7 @@ unclump_push (SPItem *from, SPItem *what, double dist) Geom::Point p = unclump_center (from); Geom::Point by = dist * Geom::unit_vector (- (p - it)); - Geom::Matrix move = Geom::Translate (by); + Geom::Affine move = Geom::Translate (by); std::map::iterator i = c_cache.find(what->getId()); if ( i != c_cache.end() ) { @@ -310,7 +310,7 @@ unclump_pull (SPItem *to, SPItem *what, double dist) Geom::Point p = unclump_center (to); Geom::Point by = dist * Geom::unit_vector (p - it); - Geom::Matrix move = Geom::Translate (by); + Geom::Affine move = Geom::Translate (by); std::map::iterator i = c_cache.find(what->getId()); if ( i != c_cache.end() ) { diff --git a/src/widgets/font-selector.cpp b/src/widgets/font-selector.cpp index 1972ea046..71e9563cd 100644 --- a/src/widgets/font-selector.cpp +++ b/src/widgets/font-selector.cpp @@ -805,7 +805,7 @@ void sp_font_preview_set_font(SPFontPreview *fprev, font_instance *font, SPFontS if (fprev->font) { - Geom::Matrix flip(Geom::Scale(fsel->fontsize, -fsel->fontsize)); + Geom::Affine flip(Geom::Scale(fsel->fontsize, -fsel->fontsize)); fprev->rfont = fprev->font->RasterFont(flip, 0); } diff --git a/src/widgets/icon.cpp b/src/widgets/icon.cpp index e7207d944..25be59942 100644 --- a/src/widgets/icon.cpp +++ b/src/widgets/icon.cpp @@ -1082,7 +1082,7 @@ extern "C" guchar *sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, SPObject *object = doc->getObjectById(name); if (object && SP_IS_ITEM(object)) { /* Find bbox in document */ - Geom::Matrix const i2doc(SP_ITEM(object)->i2doc_affine()); + Geom::Affine const i2doc(SP_ITEM(object)->i2doc_affine()); Geom::OptRect dbox = SP_ITEM(object)->getBounds(i2doc); if ( SP_OBJECT_PARENT(object) == NULL ) @@ -1096,7 +1096,7 @@ extern "C" guchar *sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, NRGC gc(NULL); /* Update to renderable state */ double sf = 1.0; - nr_arena_item_set_transform(root, (Geom::Matrix)Geom::Scale(sf, sf)); + nr_arena_item_set_transform(root, (Geom::Affine)Geom::Scale(sf, sf)); gc.transform.setIdentity(); nr_arena_item_invoke_update( root, NULL, &gc, NR_ARENA_ITEM_STATE_ALL, @@ -1128,7 +1128,7 @@ extern "C" guchar *sp_icon_doc_icon( SPDocument *doc, NRArenaItem *root, } sf = (double)psize / (double)block; - nr_arena_item_set_transform(root, (Geom::Matrix)Geom::Scale(sf, sf)); + nr_arena_item_set_transform(root, (Geom::Affine)Geom::Scale(sf, sf)); gc.transform.setIdentity(); nr_arena_item_invoke_update( root, NULL, &gc, NR_ARENA_ITEM_STATE_ALL, diff --git a/src/widgets/select-toolbar.cpp b/src/widgets/select-toolbar.cpp index a0ec248ca..89253983b 100644 --- a/src/widgets/select-toolbar.cpp +++ b/src/widgets/select-toolbar.cpp @@ -242,7 +242,7 @@ sp_object_layout_any_value_changed(GtkAdjustment *adj, SPWidget *spw) gdouble strokewidth = stroke_average_width (selection->itemList()); int transform_stroke = prefs->getBool("/options/transform/stroke", true) ? 1 : 0; - Geom::Matrix scaler = get_scale_transform_with_stroke (*bbox, strokewidth, transform_stroke, x0, y0, x1, y1); + Geom::Affine scaler = get_scale_transform_with_stroke (*bbox, strokewidth, transform_stroke, x0, y0, x1, y1); sp_selection_apply_affine(selection, scaler); DocumentUndo::maybeDone(document, actionkey, SP_VERB_CONTEXT_SELECT, diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp index 885a58536..9b79ed09e 100644 --- a/src/widgets/stroke-style.cpp +++ b/src/widgets/stroke-style.cpp @@ -186,7 +186,7 @@ sp_marker_prev_new(unsigned psize, gchar const *mname, return NULL; // sandbox broken? // Find object's bbox in document - Geom::Matrix const i2doc(SP_ITEM(object)->i2doc_affine()); + Geom::Affine const i2doc(SP_ITEM(object)->i2doc_affine()); Geom::OptRect dbox = SP_ITEM(object)->getBounds(i2doc); if (!dbox) { diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index f72b0d907..d9e72fe50 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -8038,7 +8038,7 @@ static void connector_spacing_changed(GtkAdjustment *adj, GObject* tbl) GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop); for ( GSList const *iter = items ; iter != NULL ; iter = iter->next ) { SPItem *item = reinterpret_cast(iter->data); - Geom::Matrix m = Geom::identity(); + Geom::Affine m = Geom::identity(); avoid_item_move(&m, item); modmade = true; } -- cgit v1.2.3 From 0dfccc1a7649ea0ae7e5577bed487e01ce4aef83 Mon Sep 17 00:00:00 2001 From: Josh Andler Date: Wed, 2 Feb 2011 19:12:15 -0800 Subject: Add missing 2geom files (bzr r10027) --- src/2geom/affine.cpp | 489 +++++++++++++++++++++++++++++++++++++++++++++++++ src/2geom/affine.h | 253 +++++++++++++++++++++++++ src/2geom/math-utils.h | 108 +++++++++++ 3 files changed, 850 insertions(+) create mode 100644 src/2geom/affine.cpp create mode 100644 src/2geom/affine.h create mode 100644 src/2geom/math-utils.h (limited to 'src') diff --git a/src/2geom/affine.cpp b/src/2geom/affine.cpp new file mode 100644 index 000000000..925f43820 --- /dev/null +++ b/src/2geom/affine.cpp @@ -0,0 +1,489 @@ +#define __Geom_MATRIX_C__ + +/** \file + * Various matrix routines. Currently includes some Geom::Rotate etc. routines too. + */ + +/* + * Authors: + * Lauris Kaplinski + * Michael G. Sloan + * + * This code is in public domain + */ + +#include <2geom/utils.h> +#include <2geom/affine.h> +#include <2geom/point.h> + +namespace Geom { + +/** Creates a Affine given an axis and origin point. + * The axis is represented as two vectors, which represent skew, rotation, and scaling in two dimensions. + * from_basis(Point(1, 0), Point(0, 1), Point(0, 0)) would return the identity matrix. + + \param x_basis the vector for the x-axis. + \param y_basis the vector for the y-axis. + \param offset the translation applied by the matrix. + \return The new Affine. + */ +//NOTE: Inkscape's version is broken, so when including this version, you'll have to search for code with this func +Affine from_basis(Point const x_basis, Point const y_basis, Point const offset) { + return Affine(x_basis[X], x_basis[Y], + y_basis[X], y_basis[Y], + offset [X], offset [Y]); +} + +Point Affine::xAxis() const { + return Point(_c[0], _c[1]); +} + +Point Affine::yAxis() const { + return Point(_c[2], _c[3]); +} + +/** Gets the translation imparted by the Affine. + */ +Point Affine::translation() const { + return Point(_c[4], _c[5]); +} + +void Affine::setXAxis(Point const &vec) { + for(int i = 0; i < 2; i++) + _c[i] = vec[i]; +} + +void Affine::setYAxis(Point const &vec) { + for(int i = 0; i < 2; i++) + _c[i + 2] = vec[i]; +} + +/** Sets the translation imparted by the Affine. + */ +void Affine::setTranslation(Point const &loc) { + for(int i = 0; i < 2; i++) + _c[i + 4] = loc[i]; +} + +/** Calculates the amount of x-scaling imparted by the Affine. This is the scaling applied to + * the original x-axis region. It is \emph{not} the overall x-scaling of the transformation. + * Equivalent to L2(m.xAxis()) + */ +double Affine::expansionX() const { + return sqrt(_c[0] * _c[0] + _c[1] * _c[1]); +} + +/** Calculates the amount of y-scaling imparted by the Affine. This is the scaling applied before + * the other transformations. It is \emph{not} the overall y-scaling of the transformation. + * Equivalent to L2(m.yAxis()) + */ +double Affine::expansionY() const { + return sqrt(_c[2] * _c[2] + _c[3] * _c[3]); +} + +void Affine::setExpansionX(double val) { + double exp_x = expansionX(); + if(!are_near(exp_x, 0.0)) { //TODO: best way to deal with it is to skip op? + double coef = val / expansionX(); + for(unsigned i=0;i<2;i++) _c[i] *= coef; + } +} + +void Affine::setExpansionY(double val) { + double exp_y = expansionY(); + if(!are_near(exp_y, 0.0)) { //TODO: best way to deal with it is to skip op? + double coef = val / expansionY(); + for(unsigned i=2; i<4; i++) _c[i] *= coef; + } +} + +/** Sets this matrix to be the Identity Affine. */ +void Affine::setIdentity() { + _c[0] = 1.0; _c[1] = 0.0; + _c[2] = 0.0; _c[3] = 1.0; + _c[4] = 0.0; _c[5] = 0.0; +} + +/** @brief Check whether this matrix is an identity matrix. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + 1 & 0 & 0 \\ + 0 & 1 & 0 \\ + 0 & 0 & 1 \end{array}\right]\f$ */ +bool Affine::isIdentity(Coord eps) const { + return are_near(_c[0], 1.0, eps) && are_near(_c[1], 0.0, eps) && + are_near(_c[2], 0.0, eps) && are_near(_c[3], 1.0, eps) && + are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps); +} + +/** @brief Check whether this matrix represents a pure translation. + * Will return true for the identity matrix, which represents a zero translation. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + 1 & 0 & 0 \\ + 0 & 1 & 0 \\ + a & b & 1 \end{array}\right]\f$ */ +bool Affine::isTranslation(Coord eps) const { + return are_near(_c[0], 1.0, eps) && are_near(_c[1], 0.0, eps) && + are_near(_c[2], 0.0, eps) && are_near(_c[3], 1.0, eps); +} +/** @brief Check whether this matrix represents a pure nonzero translation. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + 1 & 0 & 0 \\ + 0 & 1 & 0 \\ + a & b & 1 \end{array}\right]\f$ and \f$a, b \neq 0\f$ */ +bool Affine::isNonzeroTranslation(Coord eps) const { + return are_near(_c[0], 1.0, eps) && are_near(_c[1], 0.0, eps) && + are_near(_c[2], 0.0, eps) && are_near(_c[3], 1.0, eps) && + (!are_near(_c[4], 0.0, eps) || !are_near(_c[5], 0.0, eps)); +} + +/** @brief Check whether this matrix represents pure scaling. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + a & 0 & 0 \\ + 0 & b & 0 \\ + 0 & 0 & 1 \end{array}\right]\f$. */ +bool Affine::isScale(Coord eps) const { + return are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) && + are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps); +} + +/** @brief Check whether this matrix represents pure, nonzero scaling. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + a & 0 & 0 \\ + 0 & b & 0 \\ + 0 & 0 & 1 \end{array}\right]\f$ and \f$a, b \neq 1\f$. */ +bool Affine::isNonzeroScale(Coord eps) const { + return (!are_near(_c[0], 1.0, eps) || !are_near(_c[3], 1.0, eps)) && //NOTE: these are the diags, and the next line opposite diags + are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) && + are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps); +} + +/** @brief Check whether this matrix represents pure uniform scaling. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + a & 0 & 0 \\ + 0 & a & 0 \\ + 0 & 0 & 1 \end{array}\right]\f$. */ +bool Affine::isUniformScale(Coord eps) const { + return are_near(_c[0], _c[3], eps) && + are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) && + are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps); +} + +/** @brief Check whether this matrix represents pure, nonzero uniform scaling. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + a & 0 & 0 \\ + 0 & a & 0 \\ + 0 & 0 & 1 \end{array}\right]\f$ and \f$a \neq 1\f$. */ +bool Affine::isNonzeroUniformScale(Coord eps) const { + return !are_near(_c[0], 1.0, eps) && are_near(_c[0], _c[3], eps) && + are_near(_c[1], 0.0, eps) && are_near(_c[2], 0.0, eps) && + are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps); +} + +/** @brief Check whether this matrix represents a pure rotation. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + a & b & 0 \\ + -b & a & 0 \\ + 0 & 0 & 1 \end{array}\right]\f$ and \f$a^2 + b^2 = 1\f$. */ +bool Affine::isRotation(Coord eps) const { + return are_near(_c[0], _c[3], eps) && are_near(_c[1], -_c[2], eps) && + are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps) && + are_near(_c[0]*_c[0] + _c[1]*_c[1], 1.0, eps); +} + +/** @brief Check whether this matrix represents a pure, nonzero rotation. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + a & b & 0 \\ + -b & a & 0 \\ + 0 & 0 & 1 \end{array}\right]\f$, \f$a^2 + b^2 = 1\f$ and \f$a \neq 1\f$. */ +bool Affine::isNonzeroRotation(Coord eps) const { + return !are_near(_c[0], 1.0, eps) && + are_near(_c[0], _c[3], eps) && are_near(_c[1], -_c[2], eps) && + are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps) && + are_near(_c[0]*_c[0] + _c[1]*_c[1], 1.0, eps); +} + +/** @brief Check whether this matrix represents pure horizontal shearing. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + 1 & 0 & 0 \\ + k & 1 & 0 \\ + 0 & 0 & 1 \end{array}\right]\f$. */ +bool Affine::isHShear(Coord eps) const { + return are_near(_c[0], 1.0, eps) && are_near(_c[1], 0.0, eps) && + are_near(_c[3], 1.0, eps) && are_near(_c[4], 0.0, eps) && + are_near(_c[5], 0.0, eps); +} +/** @brief Check whether this matrix represents pure, nonzero horizontal shearing. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + 1 & 0 & 0 \\ + k & 1 & 0 \\ + 0 & 0 & 1 \end{array}\right]\f$ and \f$k \neq 0\f$. */ +bool Affine::isNonzeroHShear(Coord eps) const { + return are_near(_c[0], 1.0, eps) && are_near(_c[1], 0.0, eps) && + !are_near(_c[2], 0.0, eps) && are_near(_c[3], 1.0, eps) && + are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps); +} + +/** @brief Check whether this matrix represents pure vertical shearing. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + 1 & k & 0 \\ + 0 & 1 & 0 \\ + 0 & 0 & 1 \end{array}\right]\f$. */ +bool Affine::isVShear(Coord eps) const { + return are_near(_c[0], 1.0, eps) && are_near(_c[2], 0.0, eps) && + are_near(_c[3], 1.0, eps) && are_near(_c[4], 0.0, eps) && + are_near(_c[5], 0.0, eps); +} + +/** @brief Check whether this matrix represents pure, nonzero vertical shearing. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + 1 & k & 0 \\ + 0 & 1 & 0 \\ + 0 & 0 & 1 \end{array}\right]\f$ and \f$k \neq 0\f$. */ +bool Affine::isNonzeroVShear(Coord eps) const { + return are_near(_c[0], 1.0, eps) && !are_near(_c[1], 0.0, eps) && + are_near(_c[2], 0.0, eps) && are_near(_c[3], 1.0, eps) && + are_near(_c[4], 0.0, eps) && are_near(_c[5], 0.0, eps); +} + +/** @brief Check whether this matrix represents zooming. + * Zooming is any combination of translation and uniform scaling. It preserves angles, ratios + * of distances between arbitrary points and unit vectors of line segments. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + a & 0 & 0 \\ + 0 & a & 0 \\ + b & c & 1 \end{array}\right]\f$. */ +bool Affine::isZoom(Coord eps) const { + return are_near(_c[0], _c[3], eps) && are_near(_c[1], 0, eps) && are_near(_c[2], 0, eps); +} + +/** @brief Check whether the transformation preserves areas of polygons. + * This means that the transformation can be any combination of translation, rotation, + * shearing and squeezing (non-uniform scaling such that the absolute value of the product + * of Y-scale and X-scale is 1). + * @param eps Numerical tolerance + * @return True iff \f$|\det A| = 1\f$. */ +bool Affine::preservesArea(Coord eps) const +{ + return are_near(descrim2(), 1.0, eps); +} + +/** @brief Check whether the transformation preserves angles between lines. + * This means that the transformation can be any combination of translation, uniform scaling + * and rotation. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + a & b & 0 \\ + -b & a & 0 \\ + c & d & 1 \end{array}\right]\f$. */ +bool Affine::preservesAngles(Coord eps) const +{ + return are_near(_c[0], _c[3], eps) && are_near(_c[1], -_c[2], eps); +} + +/** @brief Check whether the transformation preserves distances between points. + * This means that the transformation can be any combination of translation and rotation. + * @param eps Numerical tolerance + * @return True iff the matrix is of the form + * \f$\left[\begin{array}{ccc} + a & b & 0 \\ + -b & a & 0 \\ + c & d & 1 \end{array}\right]\f$ and \f$a^2 + b^2 = 1\f$. */ +bool Affine::preservesDistances(Coord eps) const +{ + return are_near(_c[0], _c[3], eps) && are_near(_c[1], -_c[2], eps) && + are_near(_c[0] * _c[0] + _c[1] * _c[1], 1.0, eps); +} + +/** @brief Check whether this transformation flips objects. + * A transformation flips objects if it has a negative scaling component. */ +bool Affine::flips() const { + // TODO shouldn't this be det() < 0? + return cross(xAxis(), yAxis()) > 0; +} + +/** @brief Check whether this matrix is singular. + * Singular matrices have no inverse, which means that applying them to a set of points + * results in a loss of information. + * @param eps Numerical tolerance + * @return True iff the determinant is near zero. */ +bool Affine::isSingular(Coord eps) const { + return are_near(det(), 0.0, eps); +} + +/** @brief Compute the inverse matrix. + * Inverse is a matrix (denoted \f$A^{-1}) such that \f$AA^{-1} = A^{-1}A = I\f$. + * Singular matrices have no inverse (for example a matrix that has two of its columns equal). + * For such matrices, the identity matrix will be returned instead. + * @param eps Numerical tolerance + * @return Inverse of the matrix, or the identity matrix if the inverse is undefined. + * @post (m * m.inverse()).isIdentity() == true */ +Affine Affine::inverse() const { + Affine d; + + double mx = std::max(fabs(_c[0]) + fabs(_c[1]), + fabs(_c[2]) + fabs(_c[3])); // a random matrix norm (either l1 or linfty + if(mx > 0) { + Geom::Coord const determ = det(); + if (!rel_error_bound(determ, mx*mx)) { + Geom::Coord const ideterm = 1.0 / (determ); + + d._c[0] = _c[3] * ideterm; + d._c[1] = -_c[1] * ideterm; + d._c[2] = -_c[2] * ideterm; + d._c[3] = _c[0] * ideterm; + d._c[4] = (-_c[4] * d._c[0] - _c[5] * d._c[2]); + d._c[5] = (-_c[4] * d._c[1] - _c[5] * d._c[3]); + } else { + d.setIdentity(); + } + } else { + d.setIdentity(); + } + + return d; +} + +/** @brief Calculate the determinant. + * @return \f$\det A\f$. */ +Coord Affine::det() const { + // TODO this can overflow + return _c[0] * _c[3] - _c[1] * _c[2]; +} + +/** @brief Calculate the square of the descriminant. + * This is simply the absolute value of the determinant. + * @return \f$|\det A|\f$. */ +Coord Affine::descrim2() const { + return fabs(det()); +} + +/** @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. + * @return \f$\sqrt{|\det A|}\f$. */ +Coord Affine::descrim() const { + return sqrt(descrim2()); +} + +/** @brief Combine this transformation with another one. + * After this operation, the matrix will correspond to the transformation + * obtained by first applying the original version of this matrix, and then + * applying @a m. */ +Affine &Affine::operator*=(Affine const &o) { + Coord nc[6]; + for(int a = 0; a < 5; a += 2) { + for(int b = 0; b < 2; b++) { + nc[a + b] = _c[a] * o._c[b] + _c[a + 1] * o._c[b + 2]; + } + } + for(int a = 0; a < 6; ++a) { + _c[a] = nc[a]; + } + _c[4] += o._c[4]; + _c[5] += o._c[5]; + return *this; +} + +//TODO: What's this!?! +Affine elliptic_quadratic_form(Affine const &m) { + double od = m[0] * m[1] + m[2] * m[3]; + Affine ret (m[0]*m[0] + m[1]*m[1], od, + od, m[2]*m[2] + m[3]*m[3], + 0, 0); + return ret; // allow NRVO +} + +Eigen::Eigen(Affine const &m) { + double const B = -m[0] - m[3]; + double const C = m[0]*m[3] - m[1]*m[2]; + double const center = -B/2.0; + double const delta = sqrt(B*B-4*C)/2.0; + values[0] = center + delta; values[1] = center - delta; + for (int i = 0; i < 2; i++) { + vectors[i] = unit_vector(rot90(Point(m[0]-values[i], m[1]))); + } +} + +static void quadratic_roots(double q0, double q1, double q2, int &n, double&r0, double&r1) { + std::vector r; + if(q2 == 0) { + if(q1 == 0) { // zero or infinite roots + n = 0; + } else { + n = 1; + r0 = -q0/q1; + } + } else { + double desc = q1*q1 - 4*q2*q0; + if (desc < 0) + n = 0; + else if (desc == 0) { + n = 1; + r0 = -q1/(2*q2); + } else { + n = 2; + desc = std::sqrt(desc); + double t = -0.5*(q1+sgn(q1)*desc); + r0 = t/q2; + r1 = q0/t; + } + } +} + +Eigen::Eigen(double m[2][2]) { + double const B = -m[0][0] - m[1][1]; + double const C = m[0][0]*m[1][1] - m[1][0]*m[0][1]; + //double const desc = B*B-4*C; + //double t = -0.5*(B+sgn(B)*desc); + int n; + values[0] = values[1] = 0; + quadratic_roots(C, B, 1, n, values[0], values[1]); + for (int i = 0; i < n; i++) + vectors[i] = unit_vector(rot90(Point(m[0][0]-values[i], m[0][1]))); + for (int i = n; i < 2; i++) + vectors[i] = Point(0,0); +} + +} //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:fileencoding=utf-8:textwidth=99 : diff --git a/src/2geom/affine.h b/src/2geom/affine.h new file mode 100644 index 000000000..9a6352f8b --- /dev/null +++ b/src/2geom/affine.h @@ -0,0 +1,253 @@ +/** \file + * \brief 3x3 affine transformation matrix. + *//* + * Main authors: + * Lauris Kaplinski (Original NRAffine definition and related macros) + * Nathan Hurst (Geom::Affine class version of the above) + * Michael G. Sloan (reorganization and additions) + * Krzysztof Kosiński (removal of boilerplate, docs) + * + * This code is in public domain. + */ + +#ifndef SEEN_LIB2GEOM_MATRIX_H +#define SEEN_LIB2GEOM_MATRIX_H + +#include +#include <2geom/forward.h> +#include <2geom/point.h> + +namespace Geom { + +/** + * @brief 3x3 matrix representing an affine transformation. + * + * Affine transformations on elements of a vector space are transformations which can be + * expressed in terms of matrix multiplication followed by addition + * (\f$x \mapsto A x + b\f$). They can be thought of as generalizations of linear functions + * (\f$y = a x + b\f$) to vector spaces. Affine transformations of points on a 2D plane preserve + * the following properties: + * + * - Colinearity: if three points lie on the same line, they will still be colinear after + * an affine transformation. + * - Ratios of distances between points on the same line are preserved + * - Parallel lines remain parallel. + * + * All affine transformations on 2D points can be written as combinations of scaling, rotation, + * shearing and translation. They can be represented as a combination of a vector and a 2x2 matrix, + * but this form is inconvenient to work with. A better solution is to represent all affine + * transformations on the 2D plane as 3x3 matrices, where the last column has fixed values. + * \f[ A = \left[ \begin{array}{ccc} + c_0 & c_1 & 0 \\ + c_2 & c_3 & 0 \\ + c_4 & c_5 & 1 \end{array} \right]\f] + * + * We then interpret points as row vectors of the form \f$[p_X, p_Y, 1]\f$. Applying a + * transformation to a point can be written as right-multiplication by a 3x3 matrix + * (\f$p' = pA\f$). This subset of matrices is closed under multiplication - combination + * of any two transforms can be expressed as the multiplication of their matrices. + * In this representation, the \f$c_4\f$ and \f$c_5\f$ coefficients represent + * the translation component of the transformation. + * + * Matrices can be multiplied by other more specific transformations. When multiplying, + * the transformations are applied from left to right, so for example m = a * b + * means: @a m first transforms by a, then by b. + * + * @ingroup Transforms + */ +class Affine + : boost::equality_comparable< Affine // generates operator!= from operator== + , boost::multipliable< Affine + , boost::multipliable< Affine, Translate + , boost::multipliable< Affine, Scale + , boost::multipliable< Affine, Rotate + , boost::multipliable< Affine, HShear + , boost::multipliable< Affine, VShear + > > > > > > > + // boost::multipliable< A, B > generates operator*(A const &, B const &) + // and operator*(B const &, A const &) from A::operator*=(B const &) +{ + Coord _c[6]; +public: + Affine() { + _c[0] = _c[3] = 1; + _c[1] = _c[2] = _c[4] = _c[5] = 0; + } + + Affine(Affine const &m) { + for(int i = 0; i < 6; i++) { + _c[i] = m[i]; + } + } + + /** @brief Create a matrix from its coefficient values. + * It's rather inconvenient to directly create matrices in this way. Use transform classes + * if your transformation has a geometric interpretation. + * @see Translate + * @see Scale + * @see Rotate + * @see HShear + * @see VShear */ + Affine(Coord c0, Coord c1, Coord c2, Coord c3, Coord c4, Coord c5) { + _c[0] = c0; _c[1] = c1; + _c[2] = c2; _c[3] = c3; + _c[4] = c4; _c[5] = c5; + } + + Affine &operator=(Affine const &m) { + for(int i = 0; i < 6; i++) + _c[i] = m._c[i]; + return *this; + } + + /** @brief Access a coefficient by its index. */ + inline Coord operator[](unsigned i) const { return _c[i]; } + inline Coord &operator[](unsigned i) { return _c[i]; } + + /// @name Combine with other transformations + /// @{ + Affine &operator*=(Affine const &m); + // implemented in transforms.cpp + Affine &operator*=(Translate const &t); + Affine &operator*=(Scale const &s); + Affine &operator*=(Rotate const &r); + Affine &operator*=(HShear const &h); + Affine &operator*=(VShear const &v); + /// @} + + bool operator==(Affine const &o) const { + for(unsigned i = 0; i < 6; ++i) { + if ( _c[i] != o._c[i] ) return false; + } + return true; + } + + /// @name Get the parameters of the matrix's transform + /// @{ + Point xAxis() const; + Point yAxis() const; + Point translation() const; + Coord expansionX() const; + Coord expansionY() const; + Point expansion() const { return Point(expansionX(), expansionY()); } + /// @} + + /// @name Modify the matrix + /// @{ + void setXAxis(Point const &vec); + void setYAxis(Point const &vec); + + void setTranslation(Point const &loc); + + void setExpansionX(Coord val); + void setExpansionY(Coord val); + void setIdentity(); + /// @} + + /// @name Inspect the matrix's transform + /// @{ + bool isIdentity(Coord eps = EPSILON) const; + + bool isTranslation(Coord eps = EPSILON) const; + bool isScale(Coord eps = EPSILON) const; + bool isUniformScale(Coord eps = EPSILON) const; + bool isRotation(Coord eps = EPSILON) const; + bool isHShear(Coord eps = EPSILON) const; + bool isVShear(Coord eps = EPSILON) const; + + bool isNonzeroTranslation(Coord eps = EPSILON) const; + bool isNonzeroScale(Coord eps = EPSILON) const; + bool isNonzeroUniformScale(Coord eps = EPSILON) const; + bool isNonzeroRotation(Coord eps = EPSILON) const; + bool isNonzeroHShear(Coord eps = EPSILON) const; + bool isNonzeroVShear(Coord eps = EPSILON) const; + + bool isZoom(Coord eps = EPSILON) const; + bool preservesArea(Coord eps = EPSILON) const; + bool preservesAngles(Coord eps = EPSILON) const; + bool preservesDistances(Coord eps = EPSILON) const; + bool flips() const; + + bool isSingular(Coord eps = EPSILON) const; + /// @} + + /// @name Compute other matrices + /// @{ + Affine withoutTranslation() const { + Affine ret(*this); + ret.setTranslation(Point(0,0)); + return ret; + } + Affine inverse() const; + /// @} + + /// @name Compute scalar values + /// @{ + Coord det() const; + Coord descrim2() const; + Coord descrim() const; + /// @} + inline static Affine identity(); +}; + +/** @brief Print out the Affine (for debugging). + * @relates Affine */ +inline std::ostream &operator<< (std::ostream &out_file, const Geom::Affine &m) { + out_file << "A: " << m[0] << " C: " << m[2] << " E: " << m[4] << "\n"; + out_file << "B: " << m[1] << " D: " << m[3] << " F: " << m[5] << "\n"; + return out_file; +} + +/** Given a matrix m such that unit_circle = m*x, this returns the + * quadratic form x*A*x = 1. + * @relates Affine */ +Affine elliptic_quadratic_form(Affine const &m); + +/** Given a matrix (ignoring the translation) this returns the eigen + * values and vectors. */ +class Eigen{ +public: + Point vectors[2]; + double values[2]; + Eigen(Affine const &m); + Eigen(double M[2][2]); +}; + +// Affine factories +Affine from_basis(const Point x_basis, const Point y_basis, const Point offset=Point(0,0)); + +/** @brief Create an identity matrix. + * This is a convenience function identical to Affine::identity(). */ +inline Affine identity() { + Affine ret(Affine::identity()); + return ret; // allow NRVO +} + +/** @brief Create an identity matrix. + * @return The matrix + * \f$\left[\begin{array}{ccc} + 1 & 0 & 0 \\ + 0 & 1 & 0 \\ + 0 & 0 & 1 \end{array}\right]\f$. + * @relates Affine */ +inline Affine Affine::identity() { + Affine ret(1.0, 0.0, + 0.0, 1.0, + 0.0, 0.0); + return ret; // allow NRVO +} + +} /* namespace Geom */ + +#endif /* !__Geom_MATRIX_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/math-utils.h b/src/2geom/math-utils.h new file mode 100644 index 000000000..2c348f54b --- /dev/null +++ b/src/2geom/math-utils.h @@ -0,0 +1,108 @@ +#ifndef LIB2GEOM_MATH_UTILS_HEADER +#define LIB2GEOM_MATH_UTILS_HEADER + +/** + * \file + * \brief Low level math functions and compatibility wrappers + *//* + * Authors: + * Johan Engelen + * Michael G. Sloan + * Krzysztof Kosiński + * Copyright 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 "config.h" +#include // sincos is usually only available in math.h +#include +#include // for std::pair + +namespace Geom { + +/** @brief Sign function - indicates the sign of a numeric type. + * Mathsy people will know this is basically the derivative of abs, except for the fact + * that it is defined on 0. + * @return -1 when x is negative, 1 when positive, and 0 if equal to 0. */ +template inline int sgn(const T& x) { + return (x < 0 ? -1 : (x > 0 ? 1 : 0) ); +} + +template inline T sqr(const T& x) {return x * x;} +template inline T cube(const T& x) {return x * x * x;} + +/** Between function - returns true if a number x is within a range: (min < x) && (max > x). + * The values delimiting the range and the number must have the same type. + */ +template inline const T& between (const T& min, const T& max, const T& x) + { return (min < x) && (max > x); } + +/** @brief Returns @a x rounded to the nearest multiple of \f$10^{p}\f$. + + Implemented in terms of round, i.e. we make no guarantees as to what happens if x is + half way between two rounded numbers. + + Note: places is the number of decimal places without using scientific (e) notation, not the + number of significant figures. This function may not be suitable for values of x whose + magnitude is so far from 1 that one would want to use scientific (e) notation. + + places may be negative: e.g. places = -2 means rounding to a multiple of .01 +**/ +inline double decimal_round(double x, int p) { + //TODO: possibly implement with modulus instead? + double const multiplier = ::pow(10.0, p); + return ::round( x * multiplier ) / multiplier; +} + +/** @brief Simultaneously compute a sine and a cosine of the same angle. + * This function can be up to 2 times faster than separate computation, depending + * on the platform. It uses the standard library function sincos() if available. + * @param angle Angle + * @param sin_ Variable that will store the sine + * @param cos_ Variable that will store the cosine */ +inline void sincos(double angle, double &sin_, double &cos_) { +#ifdef HAVE_SINCOS + ::sincos(angle, &sin_, &cos_); +#else + sin_ = ::sin(angle); + cos_ = ::cos(angle); +#endif +} + +} + +#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 : -- cgit v1.2.3 From ef9ac12aa99144a8ff2b27c0b56daa2accda5fba Mon Sep 17 00:00:00 2001 From: Josh Andler Date: Wed, 2 Feb 2011 19:38:46 -0800 Subject: more missing 2geom files (bzr r10028) --- src/2geom/conicsec.cpp | 1564 ++++++++++++++++++++++++++++++++++++++++++++++++ src/2geom/conicsec.h | 525 ++++++++++++++++ 2 files changed, 2089 insertions(+) create mode 100644 src/2geom/conicsec.cpp create mode 100644 src/2geom/conicsec.h (limited to 'src') diff --git a/src/2geom/conicsec.cpp b/src/2geom/conicsec.cpp new file mode 100644 index 000000000..2a537a1f0 --- /dev/null +++ b/src/2geom/conicsec.cpp @@ -0,0 +1,1564 @@ +/** + * \file + * \brief Circle Curve + * + * Authors: + * Nathan Hurst +#include <2geom/conic_section_clipper.h> +#include <2geom/numeric/fitting-tool.h> +#include <2geom/numeric/fitting-model.h> + + +// File: convert.h +#include +#include +#include + + + + + +namespace Geom +{ + +LineSegment intersection(Line l, Rect r) { + Point p0, p1; + double a,b,c; + std::vector ifc = l.coefficients(); + a = ifc[0]; + b = ifc[1]; + c = ifc[2]; + if (fabs(b) > fabs(a)) { + p0 = Point(r[0][0], (-c - a*r[0][0])/b); + if (p0[1] < r[1][0]) + p0 = Point((-c - b*r[1][0])/a, r[1][0]); + if (p0[1] > r[1][1]) + p0 = Point((-c - b*r[1][1])/a, r[1][1]); + p1 = Point(r[0][1], (-c - a*r[0][1])/b); + if (p1[1] < r[1][0]) + p1 = Point((-c - b*r[1][0])/a, r[1][0]); + if (p1[1] > r[1][1]) + p1 = Point((-c - b*r[1][1])/a, r[1][1]); + } else { + p0 = Point((-c - b*r[1][0])/a, r[1][0]); + if (p0[0] < r[0][0]) + p0 = Point(r[0][0], (-c - a*r[0][0])/b); + if (p0[0] > r[0][1]) + p0 = Point(r[0][1], (-c - a*r[0][1])/b); + p1 = Point((-c - b*r[1][1])/a, r[1][1]); + if (p1[0] < r[0][0]) + p1 = Point(r[0][0], (-c - a*r[0][0])/b); + if (p1[0] > r[0][1]) + p1 = Point(r[0][1], (-c - a*r[0][1])/b); + } + return LineSegment(p0, p1); +} + +static double det(Point a, Point b) { + return a[0]*b[1] - a[1]*b[0]; +} + +template +static T det(T a, T b, T c, T d) { + return a*d - b*c; +} + +template +static T det(T M[2][2]) { + return M[0][0]*M[1][1] - M[1][0]*M[0][1]; +} + +template +static T det3(T M[3][3]) { + return ( M[0][0] * det(M[1][1], M[1][2], + M[2][1], M[2][2]) + -M[1][0] * det(M[0][1], M[0][2], + M[2][1], M[2][2]) + +M[2][0] * det(M[0][1], M[0][2], + M[1][1], M[1][2])); +} + +static double boxprod(Point a, Point b, Point c) { + return det(a,b) - det(a,c) + det(b,c); +} + + +/** + * Find the roots of (q2x + q1)x+q0 = 0 + * Tries to be numerically robust. + */ +template +static std::vector quadratic_roots(T q0, T q1, T q2) { + std::vector r; + if(q2 == 0) { + if(q1 == 0) { // zero or infinite roots + return r; + } + r.push_back(-q0/q1); + } else { + double desc = q1*q1 - 4*q2*q0; + /*cout << q2 << ", " + << q1 << ", " + << q0 << "; " + << desc << "\n";*/ + if (desc < 0) + return r; + else if (desc == 0) + r.push_back(-q1/(2*q2)); + else { + desc = std::sqrt(desc); + double t = -0.5*(q1+sgn(q1)*desc); + r.push_back(t/q2); + r.push_back(q0/t); + } + } + return r; +} + + + +class BadConversion : public std::runtime_error { +public: + BadConversion(const std::string& s) + : std::runtime_error(s) + { } +}; + +template +inline std::string stringify(T x) +{ + std::ostringstream o; + if (!(o << x)) + throw BadConversion("stringify(T)"); + return o.str(); +} + + /* A G4 continuous cubic parametric approximation for rational quadratics. + See + An analysis of cubic approximation schemes for conic sections + Michael Floater + SINTEF + + This is less accurate overall than some of his other schemes, but + produces very smooth joins and is still optimally h^-6 + convergent. + */ + +double RatQuad::lambda() const { + return 2*(6*w*w +1 -std::sqrt(3*w*w+1))/(12*w*w+3); +} + +RatQuad RatQuad::fromPointsTangents(Point P0, Point dP0, + Point P, + Point P2, Point dP2) { + Line Line0 = Line::from_origin_and_versor(P0, dP0); + Line Line2 = Line::from_origin_and_versor(P2, dP2); + try { + OptCrossing oc = intersection(Line0, Line2); + if(!oc) // what to do? + return RatQuad(Point(), Point(), Point(), 0); // need opt really + //assert(0); + Point P1 = Line0.pointAt((*oc).ta); + double triarea = boxprod(P0, P1, P2); +// std::cout << "RatQuad::fromPointsTangents: triarea = " << triarea << std::endl; + if (triarea == 0) + { + return RatQuad(P0, 0.5*(P0+P2), P2, 1); + } + double tau0 = boxprod(P, P1, P2)/triarea; + double tau1 = boxprod(P0, P, P2)/triarea; + double tau2 = boxprod(P0, P1, P)/triarea; + if (tau0 == 0 || tau1 == 0 || tau2 == 0) + { + return RatQuad(P0, 0.5*(P0+P2), P2, 1); + } + double w = tau1/(2*std::sqrt(tau0*tau2)); +// std::cout << "RatQuad::fromPointsTangents: tau0 = " << tau0 << std::endl; +// std::cout << "RatQuad::fromPointsTangents: tau1 = " << tau1 << std::endl; +// std::cout << "RatQuad::fromPointsTangents: tau2 = " << tau2 << std::endl; +// std::cout << "RatQuad::fromPointsTangents: w = " << w << std::endl; + return RatQuad(P0, P1, P2, w); + } catch(Geom::InfiniteSolutions) { + return RatQuad(P0, 0.5*(P0+P2), P2, 1); + } + return RatQuad(Point(), Point(), Point(), 0); // need opt really +} + +RatQuad RatQuad::circularArc(Point P0, Point P1, Point P2) { + Line Line0 = Line::from_origin_and_versor(P0, P1 - P0); + Line Line2 = Line::from_origin_and_versor(P2, P1 - P2); + return RatQuad(P0, P1, P2, dot(unit_vector(P0 - P1), unit_vector(P0 - P2))); +} + + +CubicBezier RatQuad::toCubic() const { + return toCubic(lambda()); +} + +CubicBezier RatQuad::toCubic(double lamb) const { + return CubicBezier(P[0], + (1-lamb)*P[0] + lamb*P[1], + (1-lamb)*P[2] + lamb*P[1], + P[2]); +} + +Point RatQuad::pointAt(double t) const { + Bezier xt(P[0][0], P[1][0]*w, P[2][0]); + Bezier yt(P[0][1], P[1][1]*w, P[2][1]); + double wt = Bezier(1, w, 1).valueAt(t); + return Point(xt.valueAt(t)/wt, + yt.valueAt(t)/wt); +} + +void RatQuad::split(RatQuad &a, RatQuad &b) const { + a.P[0] = P[0]; + b.P[2] = P[2]; + a.P[1] = (P[0]+w*P[1])/(1+w); + b.P[1] = (w*P[1]+P[2])/(1+w); + a.w = b.w = std::sqrt((1+w)/2); + a.P[2] = b.P[0] = (0.5*a.P[1]+0.5*b.P[1]); +} + + +D2 RatQuad::hermite() const { + SBasis t = Linear(0, 1); + SBasis omt = Linear(1, 0); + + D2 out(omt*omt*P[0][0]+2*omt*t*P[1][0]*w+t*t*P[2][0], + omt*omt*P[0][1]+2*omt*t*P[1][1]*w+t*t*P[2][1]); + for(int dim = 0; dim < 2; dim++) { + out[dim] = divide(out[dim], (omt*omt+2*omt*t*w+t*t), 2); + } + return out; +} + + std::vector RatQuad::homogenous() const { + std::vector res(3, SBasis()); + Bezier xt(P[0][0], P[1][0]*w, P[2][0]); + bezier_to_sbasis(res[0],xt); + Bezier yt(P[0][1], P[1][1]*w, P[2][1]); + bezier_to_sbasis(res[1],yt); + Bezier wt(1, w, 1); + bezier_to_sbasis(res[2],wt); + return res; +} + +#if 0 + std::string xAx::categorise() const { + double M[3][3] = {{c[0], c[1], c[3]}, + {c[1], c[2], c[4]}, + {c[3], c[4], c[5]}}; + double D = det3(M); + if (c[0] == 0 && c[1] == 0 && c[2] == 0) + return "line"; + std::string res = stringify(D); + double descr = c[1]*c[1] - c[0]*c[2]; + if (descr < 0) { + if (c[0] == c[2] && c[1] == 0) + return res + "circle"; + return res + "ellipse"; + } else if (descr == 0) { + return res + "parabola"; + } else if (descr > 0) { + if (c[0] + c[2] == 0) { + if (D == 0) + return res + "two lines"; + return res + "rectangular hyperbola"; + } + return res + "hyperbola"; + + } + return "no idea!"; +} +#endif + + +std::vector decompose_degenerate(xAx const & C1, xAx const & C2, xAx const & xC0) { + std::vector res; + double A[2][2] = {{2*xC0.c[0], xC0.c[1]}, + {xC0.c[1], 2*xC0.c[2]}}; +//Point B0 = xC0.bottom(); + double const determ = det(A); + //std::cout << determ << "\n"; + if (fabs(determ) >= 1e-20) { // hopeful, I know + Geom::Coord const ideterm = 1.0 / determ; + + double b[2] = {-xC0.c[3], -xC0.c[4]}; + Point B0((A[1][1]*b[0] -A[0][1]*b[1]), + (-A[1][0]*b[0] + A[0][0]*b[1])); + B0 *= ideterm; + Point n0, n1; + // Are these just the eigenvectors of A11? + if(xC0.c[0] == xC0.c[2]) { + double b = 0.5*xC0.c[1]/xC0.c[0]; + double c = xC0.c[2]/xC0.c[0]; + //assert(fabs(b*b-c) > 1e-10); + double d = std::sqrt(b*b-c); + //assert(fabs(b-d) > 1e-10); + n0 = Point(1, b+d); + n1 = Point(1, b-d); + } else if(fabs(xC0.c[0]) > fabs(xC0.c[2])) { + double b = 0.5*xC0.c[1]/xC0.c[0]; + double c = xC0.c[2]/xC0.c[0]; + //assert(fabs(b*b-c) > 1e-10); + double d = std::sqrt(b*b-c); + //assert(fabs(b-d) > 1e-10); + n0 = Point(1, b+d); + n1 = Point(1, b-d); + } else { + double b = 0.5*xC0.c[1]/xC0.c[2]; + double c = xC0.c[0]/xC0.c[2]; + //assert(fabs(b*b-c) > 1e-10); + double d = std::sqrt(b*b-c); + //assert(fabs(b-d) > 1e-10); + n0 = Point(b+d, 1); + n1 = Point(b-d, 1); + } + + Line L0 = Line::from_origin_and_versor(B0, rot90(n0)); + Line L1 = Line::from_origin_and_versor(B0, rot90(n1)); + + std::vector rts = C1.roots(L0); + for(unsigned i = 0; i < rts.size(); i++) { + Point P = L0.pointAt(rts[i]); + res.push_back(P); + } + rts = C1.roots(L1); + for(unsigned i = 0; i < rts.size(); i++) { + Point P = L1.pointAt(rts[i]); + res.push_back(P); + } + } else { + // single or double line + // check for completely zero case (what to do?) + assert(xC0.c[0] || xC0.c[1] || + xC0.c[2] || xC0.c[3] || + xC0.c[4] || xC0.c[5]); + Point trial_pt(0,0); + Point g = xC0.gradient(trial_pt); + if(L2sq(g) == 0) { + trial_pt[0] += 1; + g = xC0.gradient(trial_pt); + if(L2sq(g) == 0) { + trial_pt[1] += 1; + g = xC0.gradient(trial_pt); + if(L2sq(g) == 0) { + trial_pt[0] += 1; + g = xC0.gradient(trial_pt); + if(L2sq(g) == 0) { + trial_pt = Point(1.5,0.5); + g = xC0.gradient(trial_pt); + } + } + } + } + //std::cout << trial_pt << ", " << g << "\n"; + /** + * At this point we have tried up to 4 points: 0,0, 1,0, 1,1, 2,1, 1.5,1.5 + * + * No degenerate conic can pass through these points, so we can assume + * that we've found a perpendicular to the double line. + * Proof: + * any degenerate must consist of at most 2 lines. 1.5,0.5 is not on any pair of lines + * passing through the previous 4 trials. + * + * alternatively, there may be a way to determine this directly from xC0 + */ + assert(L2sq(g) != 0); + + Line Lx = Line::from_origin_and_versor(trial_pt, g); // a line along the gradient + std::vector rts = xC0.roots(Lx); + for(unsigned i = 0; i < rts.size(); i++) { + Point P0 = Lx.pointAt(rts[i]); + //std::cout << P0 << "\n"; + Line L = Line::from_origin_and_versor(P0, rot90(g)); + std::vector cnrts; + // It's very likely that at least one of the conics is degenerate, this will hopefully pick the more generate of the two. + if(fabs(C1.hessian().det()) > fabs(C2.hessian().det())) + cnrts = C1.roots(L); + else + cnrts = C2.roots(L); + for(unsigned j = 0; j < cnrts.size(); j++) { + Point P = L.pointAt(cnrts[j]); + res.push_back(P); + } + } + } + return res; +} + +double xAx_descr(xAx const & C) { + double mC[3][3] = {{C.c[0], (C.c[1])/2, (C.c[3])/2}, + {(C.c[1])/2, C.c[2], (C.c[4])/2}, + {(C.c[3])/2, (C.c[4])/2, C.c[5]}}; + + return det3(mC); +} + + +std::vector intersect(xAx const & C1, xAx const & C2) { + // You know, if either of the inputs are degenerate we should use them first! + if(xAx_descr(C1) == 0) { + return decompose_degenerate(C1, C2, C1); + } + if(xAx_descr(C2) == 0) { + return decompose_degenerate(C1, C2, C2); + } + std::vector res; + SBasis T(Linear(-1,1)); + SBasis S(Linear(1,1)); + SBasis C[3][3] = {{T*C1.c[0]+S*C2.c[0], (T*C1.c[1]+S*C2.c[1])/2, (T*C1.c[3]+S*C2.c[3])/2}, + {(T*C1.c[1]+S*C2.c[1])/2, T*C1.c[2]+S*C2.c[2], (T*C1.c[4]+S*C2.c[4])/2}, + {(T*C1.c[3]+S*C2.c[3])/2, (T*C1.c[4]+S*C2.c[4])/2, T*C1.c[5]+S*C2.c[5]}}; + + SBasis D = det3(C); + std::vector rts = Geom::roots(D); + if(rts.empty()) { + T = Linear(1,1); + S = Linear(-1,1); + SBasis C[3][3] = {{T*C1.c[0]+S*C2.c[0], (T*C1.c[1]+S*C2.c[1])/2, (T*C1.c[3]+S*C2.c[3])/2}, + {(T*C1.c[1]+S*C2.c[1])/2, T*C1.c[2]+S*C2.c[2], (T*C1.c[4]+S*C2.c[4])/2}, + {(T*C1.c[3]+S*C2.c[3])/2, (T*C1.c[4]+S*C2.c[4])/2, T*C1.c[5]+S*C2.c[5]}}; + + D = det3(C); + rts = Geom::roots(D); + } + // at this point we have a T and S and perhaps some roots that represent our degenerate conic + // Let's just pick one randomly (can we do better?) + //for(unsigned i = 0; i < rts.size(); i++) { + if(!rts.empty()) { + unsigned i = 0; + double t = T.valueAt(rts[i]); + double s = S.valueAt(rts[i]); + xAx xC0 = C1*t + C2*s; + //::draw(cr, xC0, screen_rect); // degen + + return decompose_degenerate(C1, C2, xC0); + + + } else { + std::cout << "What?\n"; + ;//std::cout << D << "\n"; + } + return res; +} + + +xAx xAx::fromPoint(Point p) { + return xAx(1., 0, 1., -2*p[0], -2*p[1], dot(p,p)); +} + +xAx xAx::fromDistPoint(Point /*p*/, double /*d*/) { + return xAx();//1., 0, 1., -2*(1+d)*p[0], -2*(1+d)*p[1], dot(p,p)+d*d); +} + +xAx xAx::fromLine(Point n, double d) { + return xAx(n[0]*n[0], 2*n[0]*n[1], n[1]*n[1], 2*d*n[0], 2*d*n[1], d*d); +} + +xAx xAx::fromLine(Line l) { + double dist; + Point norm = l.normalAndDist(dist); + + return fromLine(norm, dist); +} + +xAx xAx::fromPoints(std::vector const &pt) { + Geom::NL::Vector V(pt.size(), -1.0); + Geom::NL::Matrix M(pt.size(), 5); + for(unsigned i = 0; i < pt.size(); i++) { + Geom::Point P = pt[i]; + Geom::NL::VectorView vv = M.row_view(i); + vv[0] = P[0]*P[0]; + vv[1] = P[0]*P[1]; + vv[2] = P[1]*P[1]; + vv[3] = P[0]; + vv[4] = P[1]; + } + + Geom::NL::LinearSystem ls(M, V); + + Geom::NL::Vector x = ls.SV_solve(); + return Geom::xAx(x[0], x[1], x[2], x[3], x[4], 1); + +} + + + +double xAx::valueAt(Point P) const { + return evaluate_at(P[0], P[1]); +} + +xAx xAx::scale(double sx, double sy) const { + return xAx(c[0]*sx*sx, c[1]*sx*sy, c[2]*sy*sy, + c[3]*sx, c[4]*sy, c[5]); +} + +Point xAx::gradient(Point p) const{ + double x = p[0]; + double y = p[1]; + return Point(2*c[0]*x + c[1]*y + c[3], + c[1]*x + 2*c[2]*y + c[4]); +} + +xAx xAx::operator-(xAx const &b) const { + xAx res; + for(int i = 0; i < 6; i++) { + res.c[i] = c[i] - b.c[i]; + } + return res; +} +xAx xAx::operator+(xAx const &b) const { + xAx res; + for(int i = 0; i < 6; i++) { + res.c[i] = c[i] + b.c[i]; + } + return res; +} +xAx xAx::operator+(double const &b) const { + xAx res; + for(int i = 0; i < 5; i++) { + res.c[i] = c[i]; + } + res.c[5] = c[5] + b; + return res; +} + +xAx xAx::operator*(double const &b) const { + xAx res; + for(int i = 0; i < 6; i++) { + res.c[i] = c[i] * b; + } + return res; +} + + std::vector xAx::crossings(Rect r) const { + std::vector res; + for(int ei = 0; ei < 4; ei++) { + Geom::LineSegment ls(r.corner(ei), r.corner(ei+1)); + D2 lssb = ls.toSBasis(); + SBasis edge_curve = evaluate_at(lssb[0], lssb[1]); + std::vector rts = Geom::roots(edge_curve); + for(unsigned eci = 0; eci < rts.size(); eci++) { + res.push_back(lssb.valueAt(rts[eci])); + } + } + return res; +} + + boost::optional xAx::toCurve(Rect const & bnd) const { + std::vector crs = crossings(bnd); + if(crs.size() == 1) { + Point A = crs[0]; + Point dA = rot90(gradient(A)); + if(L2sq(dA) <= 1e-10) { // perhaps a single point? + return boost::optional (); + } + LineSegment ls = intersection(Line::from_origin_and_versor(A, dA), bnd); + return RatQuad::fromPointsTangents(A, dA, ls.pointAt(0.5), ls[1], dA); + } + else if(crs.size() >= 2 and crs.size() < 4) { + Point A = crs[0]; + Point C = crs[1]; + if(crs.size() == 3) { + if(distance(A, crs[2]) > distance(A, C)) + C = crs[2]; + else if(distance(C, crs[2]) > distance(A, C)) + A = crs[2]; + } + Line bisector = make_bisector_line(LineSegment(A, C)); + std::vector bisect_rts = this->roots(bisector); + if(bisect_rts.size() > 0) { + int besti = -1; + for(unsigned i =0; i < bisect_rts.size(); i++) { + Point p = bisector.pointAt(bisect_rts[i]); + if(bnd.contains(p)) { + besti = i; + } + } + if(besti >= 0) { + Point B = bisector.pointAt(bisect_rts[besti]); + + Point dA = gradient(A); + Point dC = gradient(C); + if(L2sq(dA) <= 1e-10 or L2sq(dC) <= 1e-10) { + return RatQuad::fromPointsTangents(A, C-A, B, C, A-C); + } + + RatQuad rq = RatQuad::fromPointsTangents(A, rot90(dA), + B, C, rot90(dC)); + return rq; + //std::vector hrq = rq.homogenous(); + /*SBasis vertex_poly = evaluate_at(hrq[0], hrq[1], hrq[2]); + std::vector rts = roots(vertex_poly); + for(unsigned i = 0; i < rts.size(); i++) { + //draw_circ(cr, Point(rq.pointAt(rts[i]))); + }*/ + } + } + } + return boost::optional(); +} + + std::vector xAx::roots(Point d, Point o) const { + // Find the roots on line l + // form the quadratic Q(t) = 0 by composing l with xAx + double q2 = c[0]*d[0]*d[0] + c[1]*d[0]*d[1] + c[2]*d[1]*d[1]; + double q1 = (2*c[0]*d[0]*o[0] + + c[1]*(d[0]*o[1]+d[1]*o[0]) + + 2*c[2]*d[1]*o[1] + + c[3]*d[0] + c[4]*d[1]); + double q0 = c[0]*o[0]*o[0] + c[1]*o[0]*o[1] + c[2]*o[1]*o[1] + c[3]*o[0] + c[4]*o[1] + c[5]; + std::vector r; + if(q2 == 0) { + if(q1 == 0) { + return r; + } + r.push_back(-q0/q1); + } else { + double desc = q1*q1 - 4*q2*q0; + /*std::cout << q2 << ", " + << q1 << ", " + << q0 << "; " + << desc << "\n";*/ + if (desc < 0) + return r; + else if (desc == 0) + r.push_back(-q1/(2*q2)); + else { + desc = std::sqrt(desc); + double t; + if (q1 == 0) + { + t = -0.5 * desc; + } + else + { + t = -0.5 * (q1 + sgn(q1) * desc); + } + r.push_back(t/q2); + r.push_back(q0/t); + } + } + return r; +} + +std::vector xAx::roots(Line const &l) const { + return roots(l.versor(), l.origin()); +} + +Interval xAx::quad_ex(double a, double b, double c, Interval ivl) { + double cx = -b*0.5/a; + Interval bnds((a*ivl[0]+b)*ivl[0]+c, (a*ivl[1]+b)*ivl[1]+c); + if(ivl.contains(cx)) + bnds.expandTo((a*cx+b)*cx+c); + return bnds; +} + +Geom::Affine xAx::hessian() const { + Geom::Affine m(2*c[0], c[1], + c[1], 2*c[2], + 0, 0); + return m; +} + + +boost::optional solve(double A[2][2], double b[2]) { + double const determ = det(A); + if (determ != 0.0) { // hopeful, I know + Geom::Coord const ideterm = 1.0 / determ; + + return Point ((A[1][1]*b[0] -A[0][1]*b[1]), + (-A[1][0]*b[0] + A[0][0]*b[1]))* ideterm; + } else { + return boost::optional(); + } +} + +boost::optional xAx::bottom() const { + double A[2][2] = {{2*c[0], c[1]}, + {c[1], 2*c[2]}}; + double b[2] = {-c[3], -c[4]}; + return solve(A, b); + //return Point(-c[3], -c[4])*hessian().inverse(); +} + +Interval xAx::extrema(Rect r) const { + if (c[0] == 0 and c[1] == 0 and c[2] == 0) { + Interval ext(valueAt(r.corner(0))); + for(int i = 1; i < 4; i++) + ext |= Interval(valueAt(r.corner(i))); + return ext; + } + double k = r[0][0]; + Interval ext = quad_ex(c[2], c[1]*k+c[4], (c[0]*k + c[3])*k + c[5], r[1]); + k = r[0][1]; + ext |= quad_ex(c[2], c[1]*k+c[4], (c[0]*k + c[3])*k + c[5], r[1]); + k = r[1][0]; + ext |= quad_ex(c[0], c[1]*k+c[3], (c[2]*k + c[4])*k + c[5], r[0]); + k = r[1][1]; + ext |= quad_ex(c[0], c[1]*k+c[3], (c[2]*k + c[4])*k + c[5], r[0]); + boost::optional B0 = bottom(); + if (B0 and r.contains(*B0)) + ext.expandTo(0); + return ext; +} + + + + + + + + + +/* + * helper functions + */ + +bool at_infinity (Point const& p) +{ + if (p[X] == infinity() || p[X] == -infinity() + || p[Y] == infinity() || p[Y] == -infinity()) + { + return true; + } + return false; +} + +inline +double signed_triangle_area (Point const& p1, Point const& p2, Point const& p3) +{ + return (cross(p3, p2) - cross(p3, p1) + cross(p2, p1)); +} + + + +/* + * Define a conic section by computing the one that fits better with + * N points. + * + * points: points to fit + * + * precondition: there must be at least 5 non-overlapping points + */ +void xAx::set(std::vector const& points) +{ + size_t sz = points.size(); + if (sz < 5) + { + THROW_RANGEERROR("fitting error: too few points passed"); + } + NL::LFMConicSection model; + NL::least_squeares_fitter fitter(model, sz); + + for (size_t i = 0; i < sz; ++i) + { + fitter.append(points[i]); + } + fitter.update(); + + NL::Vector z(sz, 0.0); + model.instance(*this, fitter.result(z)); +} + +/* + * Define a section conic by providing the coordinates of one of its vertex, + * the major axis inclination angle and the coordinates of its foci + * with respect to the unidimensional system defined by the major axis with + * origin set at the provided vertex. + * + * _vertex : section conic vertex V + * _angle : section conic major axis angle + * _dist1: +/-distance btw V and nearest focus + * _dist2: +/-distance btw V and farest focus + * + * prerequisite: _dist1 <= _dist2 + */ +void xAx::set (const Point& _vertex, double _angle, double _dist1, double _dist2) +{ + if (_dist2 == infinity() || _dist2 == -infinity()) // parabola + { + if (_dist1 == infinity()) // degenerate to a line + { + Line l(_vertex, _angle); + std::vector lcoeff = l.coefficients(); + coeff(3) = lcoeff[0]; + coeff(4) = lcoeff[1]; + coeff(5) = lcoeff[2]; + return; + } + + // y^2 - 4px == 0 + double cD = -4 * _dist1; + + double cosa = std::cos (_angle); + double sina = std::sin (_angle); + double cca = cosa * cosa; + double ssa = sina * sina; + double csa = cosa * sina; + + coeff(0) = ssa; + coeff(1) = -2 * csa; + coeff(2) = cca; + coeff(3) = cD * cosa; + coeff(4) = cD * sina; + + double VxVx = _vertex[X] * _vertex[X]; + double VxVy = _vertex[X] * _vertex[Y]; + double VyVy = _vertex[Y] * _vertex[Y]; + + coeff(5) = coeff(0) * VxVx + coeff(1) * VxVy + coeff(2) * VyVy + - coeff(3) * _vertex[X] - coeff(4) * _vertex[Y]; + coeff(3) -= (2 * coeff(0) * _vertex[X] + coeff(1) * _vertex[Y]); + coeff(4) -= (2 * coeff(2) * _vertex[Y] + coeff(1) * _vertex[X]); + + return; + } + + if (std::fabs(_dist1) > std::fabs(_dist2)) + { + std::swap (_dist1, _dist2); + } + if (_dist1 < 0) + { + _angle -= M_PI; + _dist1 = -_dist1; + _dist2 = -_dist2; + } + + // ellipse and hyperbola + double lin_ecc = (_dist2 - _dist1) / 2; + double rx = (_dist2 + _dist1) / 2; + + double cA = rx * rx - lin_ecc * lin_ecc; + double cC = rx * rx; + double cF = - cA * cC; +// std::cout << "cA: " << cA << std::endl; +// std::cout << "cC: " << cC << std::endl; +// std::cout << "cF: " << cF << std::endl; + + double cosa = std::cos (_angle); + double sina = std::sin (_angle); + double cca = cosa * cosa; + double ssa = sina * sina; + double csa = cosa * sina; + + coeff(0) = cca * cA + ssa * cC; + coeff(2) = ssa * cA + cca * cC; + coeff(1) = 2 * csa * (cA - cC); + + Point C (rx * cosa + _vertex[X], rx * sina + _vertex[Y]); + double CxCx = C[X] * C[X]; + double CxCy = C[X] * C[Y]; + double CyCy = C[Y] * C[Y]; + + coeff(3) = -2 * coeff(0) * C[X] - coeff(1) * C[Y]; + coeff(4) = -2 * coeff(2) * C[Y] - coeff(1) * C[X]; + coeff(5) = cF + coeff(0) * CxCx + coeff(1) * CxCy + coeff(2) * CyCy; +} + +/* + * Define a conic section by providing one of its vertex and its foci. + * + * _vertex: section conic vertex + * _focus1: section conic focus + * _focus2: section conic focus + */ +void xAx::set (const Point& _vertex, const Point& _focus1, const Point& _focus2) +{ + if (at_infinity(_vertex)) + { + THROW_RANGEERROR("case not handled: vertex at infinity"); + } + if (at_infinity(_focus2)) + { + if (at_infinity(_focus1)) + { + THROW_RANGEERROR("case not handled: both focus at infinity"); + } + Point VF = _focus1 - _vertex; + double dist1 = L2(VF); + double angle = atan2(VF); + set(_vertex, angle, dist1, infinity()); + return; + } + else if (at_infinity(_focus1)) + { + Point VF = _focus2 - _vertex; + double dist1 = L2(VF); + double angle = atan2(VF); + set(_vertex, angle, dist1, infinity()); + return; + } + assert (are_collinear (_vertex, _focus1, _focus2)); + if (!are_near(_vertex, _focus1)) + { + Point VF = _focus1 - _vertex; + Line axis(_vertex, _focus1); + double angle = atan2(VF); + double dist1 = L2(VF); + double dist2 = distance (_vertex, _focus2); + double t = axis.timeAt(_focus2); + if (t < 0) dist2 = -dist2; +// std::cout << "t = " << t << std::endl; +// std::cout << "dist2 = " << dist2 << std::endl; + set (_vertex, angle, dist1, dist2); + } + else if (!are_near(_vertex, _focus2)) + { + Point VF = _focus2 - _vertex; + double angle = atan2(VF); + double dist1 = 0; + double dist2 = L2(VF); + set (_vertex, angle, dist1, dist2); + } + else + { + coeff(0) = coeff(2) = 1; + coeff(1) = coeff(3) = coeff(4) = coeff(5) = 0; + } +} + +/* + * Define a conic section by passing a focus, the related directrix, + * and the eccentricity (e) + * (e < 1 -> ellipse; e = 1 -> parabola; e > 1 -> hyperbola) + * + * _focus: a focus of the conic section + * _directrix: the directrix related to the given focus + * _eccentricity: the eccentricity parameter of the conic section + */ +void xAx::set (const Point & _focus, const Line & _directrix, double _eccentricity) +{ + Point O = _directrix.pointAt (_directrix.timeAtProjection (_focus)); + //std::cout << "O = " << O << std::endl; + Point OF = _focus - O; + double p = L2(OF); + + coeff(0) = 1 - _eccentricity * _eccentricity; + coeff(1) = 0; + coeff(2) = 1; + coeff(3) = -2 * p; + coeff(4) = 0; + coeff(5) = p * p; + + double angle = atan2 (OF); + + (*this) = rotate (angle); + //std::cout << "O = " << O << std::endl; + (*this) = translate (O); +} + +/* + * Made up a degenerate conic section as a pair of lines + * + * l1, l2: lines that made up the conic section + */ +void xAx::set (const Line& l1, const Line& l2) +{ + std::vector cl1 = l1.coefficients(); + std::vector cl2 = l2.coefficients(); + + coeff(0) = cl1[0] * cl2[0]; + coeff(2) = cl1[1] * cl2[1]; + coeff(5) = cl1[2] * cl2[2]; + coeff(1) = cl1[0] * cl2[1] + cl1[1] * cl2[0]; + coeff(3) = cl1[0] * cl2[2] + cl1[2] * cl2[0]; + coeff(4) = cl1[1] * cl2[2] + cl1[2] * cl2[1]; +} + + + +/* + * Return the section conic kind + */ +xAx::kind_t xAx::kind () const +{ + + xAx conic(*this); + NL::SymmetricMatrix<3> C = conic.get_matrix(); + NL::ConstSymmetricMatrixView<2> A = C.main_minor_const_view(); + + double t1 = trace(A); + double t2 = det(A); + //double T3 = det(C); + int st1 = trace_sgn(A); + int st2 = det_sgn(A); + int sT3 = det_sgn(C); + + //std::cout << "T3 = " << T3 << std::endl; + //std::cout << "sT3 = " << sT3 << std::endl; + //std::cout << "t2 = " << t2 << std::endl; + //std::cout << "t1 = " << t1 << std::endl; + //std::cout << "st2 = " << st2 << std::endl; + + if (sT3 != 0) + { + if (st2 == 0) + { + return PARABOLA; + } + else if (st2 == 1) + { + + if (sT3 * st1 < 0) + { + NL::SymmetricMatrix<2> discr; + discr(0,0) = 4; discr(1,1) = t2; discr(1,0) = t1; + int discr_sgn = - det_sgn (discr); + //std::cout << "t1 * t1 - 4 * t2 = " + // << (t1 * t1 - 4 * t2) << std::endl; + //std::cout << "discr_sgn = " << discr_sgn << std::endl; + if (discr_sgn == 0) + { + return CIRCLE; + } + else + { + return REAL_ELLIPSE; + } + } + else // sT3 * st1 > 0 + { + return IMAGINARY_ELLIPSE; + } + } + else // t2 < 0 + { + if (st1 == 0) + { + return RECTANGULAR_HYPERBOLA; + } + else + { + return HYPERBOLA; + } + } + } + else // T3 == 0 + { + if (st2 == 0) + { + //double T2 = NL::trace<2>(C); + int sT2 = NL::trace_sgn<2>(C); + //std::cout << "T2 = " << T2 << std::endl; + //std::cout << "sT2 = " << sT2 << std::endl; + + if (sT2 == 0) + { + return DOUBLE_LINE; + } + if (sT2 == -1) + { + return TWO_REAL_PARALLEL_LINES; + } + else // T2 > 0 + { + return TWO_IMAGINARY_PARALLEL_LINES; + } + } + else if (st2 == -1) + { + return TWO_REAL_CROSSING_LINES; + } + else // t2 > 0 + { + return TWO_IMAGINARY_CROSSING_LINES; + } + } + return UNKNOWN; +} + +/* + * Return a string representing the conic section kind + */ +std::string xAx::categorise() const +{ + kind_t KIND = kind(); + + switch (KIND) + { + case PARABOLA : + return "parabola"; + case CIRCLE : + return "circle"; + case REAL_ELLIPSE : + return "real ellispe"; + case IMAGINARY_ELLIPSE : + return "imaginary ellispe"; + case RECTANGULAR_HYPERBOLA : + return "rectangular hyperbola"; + case HYPERBOLA : + return "hyperbola"; + case DOUBLE_LINE : + return "double line"; + case TWO_REAL_PARALLEL_LINES : + return "two real parallel lines"; + case TWO_IMAGINARY_PARALLEL_LINES : + return "two imaginary parallel lines"; + case TWO_REAL_CROSSING_LINES : + return "two real crossing lines"; + case TWO_IMAGINARY_CROSSING_LINES : + return "two imaginary crossing lines"; + default : + return "unknown"; + } +} + +/* + * Compute the solutions of the conic section algebraic equation with respect to + * one coordinate after substituting to the other coordinate the passed value + * + * sol: the computed solutions + * v: the provided value + * d: the index of the coordinate the passed value have to be substituted to + */ +void xAx::roots (std::vector& sol, Coord v, Dim2 d) const +{ + sol.clear(); + if (d < 0 || d > Y) + { + THROW_RANGEERROR("dimension parameter out of range"); + } + + // p*t^2 + q*t + r = 0; + double p, q, r; + + if (d == X) + { + p = coeff(2); + q = coeff(4) + coeff(1) * v; + r = coeff(5) + (coeff(0) * v + coeff(3)) * v; + } + else + { + p = coeff(0); + q = coeff(3) + coeff(1) * v; + r = coeff(5) + (coeff(2) * v + coeff(4)) * v; + } + + if (p == 0) + { + if (q == 0) return; + double t = -r/q; + sol.push_back(t); + return; + } + + if (q == 0) + { + if ((p > 0 && r > 0) || (p < 0 && r < 0)) return; + double t = -r / p; + t = std::sqrt (t); + sol.push_back(-t); + sol.push_back(t); + return; + } + + if (r == 0) + { + double t = -q/p; + sol.push_back(0); + sol.push_back(t); + return; + } + + + //std::cout << "p = " << p << ", q = " << q << ", r = " << r << std::endl; + double delta = q * q - 4 * p * r; + if (delta < 0) return; + if (delta == 0) + { + double t = -q / (2 * p); + sol.push_back(t); + return; + } + // else + double srd = std::sqrt(delta); + double t = - (q + sgn(q) * srd) / 2; + sol.push_back (t/p); + sol.push_back (r/t); + +} + +/* + * Return the inclination angle of the major axis of the conic section + */ +double xAx::axis_angle() const +{ + if (coeff(0) == 0 && coeff(1) == 0 && coeff(2) == 0) + { + Line l (coeff(3), coeff(4), coeff(5)); + return l.angle(); + } + if (coeff(1) == 0 && (coeff(0) == coeff(2))) return 0; + + double angle; + + int sgn_discr = det_sgn (get_matrix().main_minor_const_view()); + if (sgn_discr == 0) + { + //std::cout << "rotation_angle: sgn_discr = " + // << sgn_discr << std::endl; + angle = std::atan2 (-coeff(1), 2 * coeff(2)); + if (angle < 0) angle += 2*M_PI; + if (angle >= M_PI) angle -= M_PI; + + } + else + { + angle = std::atan2 (coeff(1), coeff(0) - coeff(2)); + if (angle < 0) angle += 2*M_PI; + angle -= M_PI; + if (angle < 0) angle += 2*M_PI; + angle /= 2; + if (angle >= M_PI) angle -= M_PI; + } + //std::cout << "rotation_angle : angle = " << angle << std::endl; + return angle; +} + +/* + * Translate the conic section by the given vector offset + * + * _offset: represent the vector offset + */ +xAx xAx::translate (const Point & _offset) const +{ + double B = coeff(1) / 2; + double D = coeff(3) / 2; + double E = coeff(4) / 2; + + Point T = - _offset; + + xAx cs; + cs.coeff(0) = coeff(0); + cs.coeff(1) = coeff(1); + cs.coeff(2) = coeff(2); + + Point DE; + DE[0] = coeff(0) * T[0] + B * T[1]; + DE[1] = B * T[0] + coeff(2) * T[1]; + + cs.coeff(3) = (DE[0] + D) * 2; + cs.coeff(4) = (DE[1] + E) * 2; + + cs.coeff(5) = dot (T, DE) + 2 * (T[0] * D + T[1] * E) + coeff(5); + + return cs; +} + + +/* + * Rotate the conic section by the given angle wrt the point (0,0) + * + * angle: represent the rotation angle + */ +xAx xAx::rotate (double angle) const +{ + double c = std::cos(-angle); + double s = std::sin(-angle); + double cc = c * c; + double ss = s * s; + double cs = c * s; + + xAx result; + result.coeff(5) = coeff(5); + + // quadratic terms + double Bcs = coeff(1) * cs; + + result.coeff(0) = coeff(0) * cc + Bcs + coeff(2) * ss; + result.coeff(2) = coeff(0) * ss - Bcs + coeff(2) * cc; + result.coeff(1) = coeff(1) * (cc - ss) + 2 * (coeff(2) - coeff(0)) * cs; + + // linear terms + result.coeff(3) = coeff(3) * c + coeff(4) * s; + result.coeff(4) = coeff(4) * c - coeff(3) * s; + + return result; +} + + +/* + * Decompose a degenerate conic in two lines the conic section is made by. + * Return true if the decomposition is successfull, else if it fails. + * + * l1, l2: out parameters where the decomposed conic section is returned + */ +bool xAx::decompose (Line& l1, Line& l2) const +{ + NL::SymmetricMatrix<3> C = get_matrix(); + if (!is_quadratic() || !isDegenerate()) + { + return false; + } + NL::Matrix M(C); + NL::SymmetricMatrix<3> D = -adj(C); + + if (!D.is_zero()) // D == 0 <=> rank(C) < 2 + { + + //if (D.get<0,0>() < 0 || D.get<1,1>() < 0 || D.get<2,2>() < 0) + //{ + //std::cout << "C: \n" << C << std::endl; + //std::cout << "D: \n" << D << std::endl; + + /* + * This case should be impossible because any diagonal element + * of D is a square, but due to non exact aritmethic computation + * it can actually happen; however the algorithm seems to work + * correctly even if some diagonal term is negative, the only + * difference is that we should compute the absolute value of + * diagonal elements. So until we elaborate a better degenerate + * test it's better not rising exception when we have a negative + * diagonal element. + */ + //} + + NL::Vector d(3); + d[0] = std::fabs (D.get<0,0>()); + d[1] = std::fabs (D.get<1,1>()); + d[2] = std::fabs (D.get<2,2>()); + + size_t idx = d.max_index(); + if (d[idx] == 0) + { + THROW_LOGICALERROR ("xAx::decompose: " + "rank 2 but adjoint with null diagonal"); + } + d[0] = D(idx,0); d[1] = D(idx,1); d[2] = D(idx,2); + d.scale (1 / std::sqrt (std::fabs (D(idx,idx)))); + M(1,2) += d[0]; M(2,1) -= d[0]; + M(0,2) -= d[1]; M(2,0) += d[1]; + M(0,1) += d[2]; M(1,0) -= d[2]; + + //std::cout << "C: \n" << C << std::endl; + //std::cout << "D: \n" << D << std::endl; + //std::cout << "d = " << d << std::endl; + //std::cout << "M = " << M << std::endl; + } + + std::pair max_ij = M.max_index(); + std::pair min_ij = M.min_index(); + double abs_max = std::fabs (M(max_ij.first, max_ij.second)); + double abs_min = std::fabs (M(min_ij.first, min_ij.second)); + size_t i_max, j_max; + if (abs_max > abs_min) + { + i_max = max_ij.first; + j_max = max_ij.second; + } + else + { + i_max = min_ij.first; + j_max = min_ij.second; + } + l1.setCoefficients (M(i_max,0), M(i_max,1), M(i_max,2)); + l2.setCoefficients (M(0, j_max), M(1,j_max), M(2,j_max)); + + return true; +} + + +/* + * Return the rectangle that bound the conic section arc characterized by + * the passed points. + * + * P1: the initial point of the arc + * Q: the inner point of the arc + * P2: the final point of the arc + * + * prerequisite: the passed points must lie on the conic + */ +Rect xAx::arc_bound (const Point & P1, const Point & Q, const Point & P2) const +{ + //std::cout << "BOUND: P1 = " << P1 << std::endl; + //std::cout << "BOUND: Q = " << Q << std::endl; + //std::cout << "BOUND: P2 = " << P2 << std::endl; + + Rect B(P1, P2); + double Qside = signed_triangle_area (P1, Q, P2); + //std::cout << "BOUND: Qside = " << Qside << std::endl; + + Line gl[2]; + bool empty[2] = {false, false}; + + try // if the passed coefficients lead to an equation 0x + 0y + c == 0, + { // with c != 0 the setCoefficients rise an exception + gl[0].setCoefficients (coeff(1), 2 * coeff(2), coeff(4)); + } + catch(Geom::LogicalError e) + { + empty[0] = true; + } + + try + { + gl[1].setCoefficients (2 * coeff(0), coeff(1), coeff(3)); + } + catch(Geom::LogicalError e) + { + empty[1] = true; + } + + std::vector rts; + std::vector M; + for (size_t dim = 0; dim < 2; ++dim) + { + if (empty[dim]) continue; + rts = roots (gl[dim]); + M.clear(); + for (size_t i = 0; i < rts.size(); ++i) + M.push_back (gl[dim].pointAt (rts[i])); + if (M.size() == 1) + { + double Mside = signed_triangle_area (P1, M[0], P2); + if (sgn(Mside) == sgn(Qside)) + { + //std::cout << "BOUND: M.size() == 1" << std::endl; + if (M[0][dim] > B[dim][1]) + B[dim][1] = M[0][dim]; + else if (M[0][dim] < B[dim][0]) + B[dim][0] = M[0][dim]; + } + } + else if (M.size() == 2) + { + //std::cout << "BOUND: M.size() == 2" << std::endl; + if (M[0][dim] > M[1][dim]) + std::swap (M[0], M[1]); + + if (M[0][dim] > B[dim][1]) + { + double Mside = signed_triangle_area (P1, M[0], P2); + if (sgn(Mside) == sgn(Qside)) + B[dim][1] = M[0][dim]; + } + else if (M[1][dim] < B[dim][0]) + { + double Mside = signed_triangle_area (P1, M[1], P2); + if (sgn(Mside) == sgn(Qside)) + B[dim][0] = M[1][dim]; + } + else + { + double Mside = signed_triangle_area (P1, M[0], P2); + if (sgn(Mside) == sgn(Qside)) + B[dim][0] = M[0][dim]; + Mside = signed_triangle_area (P1, M[1], P2); + if (sgn(Mside) == sgn(Qside)) + B[dim][1] = M[1][dim]; + } + } + } + + return B; +} + +/* + * Return all points on the conic section nearest to the passed point "P". + * + * P: the point to compute the nearest one + */ +std::vector xAx::allNearestPoints (const Point P) const +{ + // TODO: manage the circle - centre case + std::vector points; + + // named C the conic we look for points (x,y) on C such that + // dot (grad (C(x,y)), rot90 (P -(x,y))) == 0; the set of points satisfying + // this equation is still a conic G, so the wanted points can be found by + // intersecting C with G + xAx G (-coeff(1), + 2 * (coeff(0) - coeff(2)), + coeff(1), + -coeff(4) + coeff(1) * P[X] - 2 * coeff(0) * P[Y], + coeff(3) - coeff(1) * P[Y] + 2 * coeff(2) * P[X], + -coeff(3) * P[Y] + coeff(4) * P[X]); + + std::vector crs = intersect (*this, G); + + //std::cout << "NEAREST POINT: crs.size = " << crs.size() << std::endl; + if (crs.size() == 0) return points; + + size_t idx = 0; + double mindist = distanceSq (crs[0], P); + std::vector dist; + dist.push_back (mindist); + + for (size_t i = 1; i < crs.size(); ++i) + { + dist.push_back (distanceSq (crs[i], P)); + if (mindist > dist.back()) + { + idx = i; + mindist = dist.back(); + } + } + + points.push_back (crs[idx]); + for (size_t i = 0; i < crs.size(); ++i) + { + if (i == idx) continue; + if (dist[i] == mindist) + points.push_back (crs[i]); + } + + return points; +} + + + +bool clip (std::vector & rq, const xAx & cs, const Rect & R) +{ + clipper aclipper (cs, R); + return aclipper.clip (rq); +} + + +} // end 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:fileencoding=utf-8:textwidth=99 : diff --git a/src/2geom/conicsec.h b/src/2geom/conicsec.h new file mode 100644 index 000000000..be9a68bfa --- /dev/null +++ b/src/2geom/conicsec.h @@ -0,0 +1,525 @@ +/** + * \file + * \brief Conic Section + * + * Authors: + * Nathan Hurst + * + * Copyright 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 _2GEOM_CONIC_SECTION_H_ +#define _2GEOM_CONIC_SECTION_H_ + +#include <2geom/exception.h> +#include <2geom/angle.h> +#include <2geom/rect.h> +#include <2geom/affine.h> +#include <2geom/point.h> +#include <2geom/line.h> +#include <2geom/bezier-curve.h> +#include <2geom/numeric/linear_system.h> +#include <2geom/numeric/symmetric-matrix-fs.h> +#include <2geom/numeric/symmetric-matrix-fs-operation.h> + +#include + +#include +#include +#include + + + + +namespace Geom +{ + +class RatQuad{ + /** + * A curve of the form B02*A + B12*B*w + B22*C/(B02 + B12*w + B22) + * These curves can exactly represent a piece conic section less than a certain angle (find out) + * + **/ + +public: + Point P[3]; + double w; + RatQuad() {} + RatQuad(Point a, Point b, Point c, double w) : w(w) { + P[0] = a; + P[1] = b; + P[2] = c; + } + double lambda() const; + + static RatQuad fromPointsTangents(Point P0, Point dP0, + Point P, + Point P2, Point dP2); + static RatQuad circularArc(Point P0, Point P1, Point P2); + + CubicBezier toCubic() const; + CubicBezier toCubic(double lam) const; + + Point pointAt(double t) const; + Point at0() const {return P[0];} + Point at1() const {return P[2];} + + void split(RatQuad &a, RatQuad &b) const; + + D2 hermite() const; + std::vector homogenous() const; +}; + + + + +class xAx{ +public: + double c[6]; + + enum kind_t + { + PARABOLA, + CIRCLE, + REAL_ELLIPSE, + IMAGINARY_ELLIPSE, + RECTANGULAR_HYPERBOLA, + HYPERBOLA, + DOUBLE_LINE, + TWO_REAL_PARALLEL_LINES, + TWO_IMAGINARY_PARALLEL_LINES, + TWO_REAL_CROSSING_LINES, + TWO_IMAGINARY_CROSSING_LINES, // crossing at a real point + SINGLE_POINT = TWO_IMAGINARY_CROSSING_LINES, + UNKNOWN + }; + + + xAx() {} + + /* + * Define the conic section by its algebraic equation coefficients + * + * c0, .., c5: equation coefficients + */ + xAx (double c0, double c1, double c2, double c3, double c4, double c5) + { + set (c0, c1, c2, c3, c4, c5); + } + + /* + * Define a conic section by its related symmetric matrix + */ + xAx (const NL::ConstSymmetricMatrixView<3> & C) + { + set(C); + } + + /* + * Define a conic section by computing the one that fits better with + * N points. + * + * points: points to fit + * + * precondition: there must be at least 5 non-overlapping points + */ + xAx (std::vector const& points) + { + set (points); + } + + /* + * Define a section conic by providing the coordinates of one of its + * vertex,the major axis inclination angle and the coordinates of its foci + * with respect to the unidimensional system defined by the major axis with + * origin set at the provided vertex. + * + * _vertex : section conic vertex V + * _angle : section conic major axis angle + * _dist1: +/-distance btw V and nearest focus + * _dist2: +/-distance btw V and farest focus + * + * prerequisite: _dist1 <= _dist2 + */ + xAx (const Point& _vertex, double _angle, double _dist1, double _dist2) + { + set (_vertex, _angle, _dist1, _dist2); + } + + /* + * Define a conic section by providing one of its vertex and its foci. + * + * _vertex: section conic vertex + * _focus1: section conic focus + * _focus2: section conic focus + */ + xAx (const Point& _vertex, const Point& _focus1, const Point& _focus2) + { + set(_vertex, _focus1, _focus2); + } + + /* + * Define a conic section by passing a focus, the related directrix, + * and the eccentricity (e) + * (e < 1 -> ellipse; e = 1 -> parabola; e > 1 -> hyperbola) + * + * _focus: a focus of the conic section + * _directrix: the directrix related to the given focus + * _eccentricity: the eccentricity parameter of the conic section + */ + xAx (const Point & _focus, const Line & _directrix, double _eccentricity) + { + set (_focus, _directrix, _eccentricity); + } + + /* + * Made up a degenerate conic section as a pair of lines + * + * l1, l2: lines that made up the conic section + */ + xAx (const Line& l1, const Line& l2) + { + set (l1, l2); + } + + /* + * Define the conic section by its algebraic equation coefficients + * c0, ..., c5: equation coefficients + */ + void set (double c0, double c1, double c2, double c3, double c4, double c5) + { + c[0] = c0; c[1] = c1; c[2] = c2; // xx, xy, yy + c[3] = c3; c[4] = c4; // x, y + c[5] = c5; // 1 + } + + /* + * Define a conic section by its related symmetric matrix + */ + void set (const NL::ConstSymmetricMatrixView<3> & C) + { + set(C(0,0), 2*C(1,0), C(1,1), 2*C(2,0), 2*C(2,1), C(2,2)); + } + + void set (std::vector const& points); + + void set (const Point& _vertex, double _angle, double _dist1, double _dist2); + + void set (const Point& _vertex, const Point& _focus1, const Point& _focus2); + + void set (const Point & _focus, const Line & _directrix, double _eccentricity); + + void set (const Line& l1, const Line& l2); + + + static xAx fromPoint(Point p); + static xAx fromDistPoint(Point p, double d); + static xAx fromLine(Point n, double d); + static xAx fromLine(Line l); + static xAx fromPoints(std::vector const &pts); + + + template + T evaluate_at(T x, T y) const { + return c[0]*x*x + c[1]*x*y + c[2]*y*y + c[3]*x + c[4]*y + c[5]; + } + + double valueAt(Point P) const; + + std::vector implicit_form_coefficients() const { + return std::vector(c, c+6); + } + + template + T evaluate_at(T x, T y, T w) const { + return c[0]*x*x + c[1]*x*y + c[2]*y*y + c[3]*x*w + c[4]*y*w + c[5]*w*w; + } + + xAx scale(double sx, double sy) const; + + Point gradient(Point p) const; + + xAx operator-(xAx const &b) const; + xAx operator+(xAx const &b) const; + xAx operator+(double const &b) const; + xAx operator*(double const &b) const; + + std::vector crossings(Rect r) const; + boost::optional toCurve(Rect const & bnd) const; + std::vector roots(Point d, Point o) const; + + std::vector roots(Line const &l) const; + + static Interval quad_ex(double a, double b, double c, Interval ivl); + + Geom::Affine hessian() const; + + boost::optional bottom() const; + + Interval extrema(Rect r) const; + + + /* + * Return the symmetric matrix related to the conic section. + * Modifying the matrix does not modify the conic section + */ + NL::SymmetricMatrix<3> get_matrix() const + { + NL::SymmetricMatrix<3> C(c); + C(1,0) *= 0.5; C(2,0) *= 0.5; C(2,1) *= 0.5; + return C; + } + + /* + * Return the i-th coefficient of the conic section algebraic equation + * Modifying the returned value does not modify the conic section coefficient + */ + double coeff (size_t i) const + { + return c[i]; + } + + /* + * Return the i-th coefficient of the conic section algebraic equation + * Modifying the returned value modifies the conic section coefficient + */ + double& coeff (size_t i) + { + return c[i]; + } + + kind_t kind () const; + + std::string categorise() const; + + /* + * Return true if the equation: + * c0*x^2 + c1*xy + c2*y^2 + c3*x + c4*y +c5 == 0 + * really defines a conic, false otherwise + */ + bool is_quadratic() const + { + return (coeff(0) != 0 || coeff(1) != 0 || coeff(2) != 0); + } + + /* + * Return true if the conic is degenerate, i.e. if the related matrix + * determinant is null, false otherwise + */ + bool isDegenerate() const + { + return (det_sgn (get_matrix()) == 0); + } + + /* + * Compute the centre of simmetry of the conic section when it exists, + * else it return an unitialized boost::optional instance. + */ + boost::optional centre() const + { + typedef boost::optional opt_point_t; + + double d = coeff(1) * coeff(1) - 4 * coeff(0) * coeff(2); + if (are_near (d, 0)) return opt_point_t(); + NL::Matrix Q(2, 2); + Q(0,0) = coeff(0); + Q(1,1) = coeff(2); + Q(0,1) = Q(1,0) = coeff(1) * 0.5; + NL::Vector T(2); + T[0] = - coeff(3) * 0.5; + T[1] = - coeff(4) * 0.5; + + NL::LinearSystem ls (Q, T); + NL::Vector sol = ls.SV_solve(); + Point C; + C[0] = sol[0]; + C[1] = sol[1]; + + return opt_point_t(C); + } + + double axis_angle() const; + + void roots (std::vector& sol, Coord v, Dim2 d) const; + + xAx translate (const Point & _offset) const; + + xAx rotate (double angle) const; + + /* + * Rotate the conic section by the given angle wrt the provided point. + * + * _rot_centre: the rotation centre + * _angle: the rotation angle + */ + xAx rotate (const Point & _rot_centre, double _angle) const + { + xAx result + = translate (-_rot_centre).rotate (_angle).translate (_rot_centre); + return result; + } + + /* + * Compute the tangent line of the conic section at the provided point + * + * _point: the conic section point the tangent line pass through + */ + Line tangent (const Point & _point) const + { + NL::Vector pp(3); + pp[0] = _point[0]; pp[1] = _point[1]; pp[2] = 1; + NL::SymmetricMatrix<3> C = get_matrix(); + NL::Vector line = C * pp; + return Line(line[0], line[1], line[2]); + } + + /* + * For a non degenerate conic compute the dual conic. + * TODO: investigate degenerate case + */ + xAx dual () const + { + //assert (! isDegenerate()); + NL::SymmetricMatrix<3> C = get_matrix(); + NL::SymmetricMatrix<3> D = adj(C); + xAx dc(D); + return dc; + } + + bool decompose (Line& l1, Line& l2) const; + + /* + * Generate a RatQuad object from a conic arc. + * + * p0: the initial point of the arc + * p1: the inner point of the arc + * p2: the final point of the arc + */ + RatQuad toRatQuad (const Point & p0, + const Point & p1, + const Point & p2) const + { + Point dp0 = gradient (p0); + Point dp2 = gradient (p2); + return + RatQuad::fromPointsTangents (p0, rot90 (dp0), p1, p2, rot90 (dp2)); + } + + /* + * Return the angle related to the normal gradient computed at the passed + * point. + * + * _point: the point at which computes the angle + * + * prerequisite: the passed point must lie on the conic + */ + double angle_at (const Point & _point) const + { + double angle = atan2 (gradient (_point)); + if (angle < 0) angle += (2*M_PI); + return angle; + } + + /* + * Return true if the given point is contained in the conic arc determined + * by the passed points. + * + * _point: the point to be tested + * _initial: the initial point of the arc + * _inner: an inner point of the arc + * _final: the final point of the arc + * + * prerequisite: the passed points must lie on the conic, the inner point + * has to be strictly contained in the arc, except when the + * initial and final points are equal: in such a case if the + * inner point is also equal to them, then they define an arc + * made up by a single point. + * + */ + bool arc_contains (const Point & _point, const Point & _initial, + const Point & _inner, const Point & _final) const + { + double pa = angle_at (_point); + double sa = angle_at (_initial); + double ia = angle_at (_inner); + double ea = angle_at (_final); + // we test if _point and _inner have the same position + // wrt _initial and _final + return Geom::arc_contains (pa, sa, ia, ea); + } + + Rect arc_bound (const Point & P1, const Point & Q, const Point & P2) const; + + std::vector allNearestPoints (const Point P) const; + + /* + * Return the point on the conic section nearest to the passed point "P". + * + * P: the point to compute the nearest one + */ + Point nearestPoint (const Point P) const + { + std::vector points = allNearestPoints (P); + if (points.size() != 0) + { + return points.front(); + } + // else + THROW_LOGICALERROR ("nearestPoint: no nearest point found"); + return Point(); + } + +}; + +std::vector intersect(const xAx & C1, const xAx & C2); + +bool clip (std::vector & rq, const xAx & cs, const Rect & R); + +inline std::ostream &operator<< (std::ostream &out_file, const xAx &x) { + for(int i = 0; i < 6; i++) { + out_file << x.c[i] << ", "; + } + return out_file; +} + +}; + + +#endif // _2GEOM_CONIC_SECTION_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 : + -- cgit v1.2.3 From 531327b6c806d863e716af55489da3c85b14c857 Mon Sep 17 00:00:00 2001 From: Josh Andler Date: Wed, 2 Feb 2011 20:59:17 -0800 Subject: the last 2geom files I could find missing, linking issues still exist (bzr r10029) --- src/2geom/numeric/symmetric-matrix-fs-operation.h | 107 ++++ src/2geom/numeric/symmetric-matrix-fs-trace.h | 433 +++++++++++++ src/2geom/numeric/symmetric-matrix-fs.h | 730 ++++++++++++++++++++++ 3 files changed, 1270 insertions(+) create mode 100644 src/2geom/numeric/symmetric-matrix-fs-operation.h create mode 100644 src/2geom/numeric/symmetric-matrix-fs-trace.h create mode 100644 src/2geom/numeric/symmetric-matrix-fs.h (limited to 'src') diff --git a/src/2geom/numeric/symmetric-matrix-fs-operation.h b/src/2geom/numeric/symmetric-matrix-fs-operation.h new file mode 100644 index 000000000..5222d2734 --- /dev/null +++ b/src/2geom/numeric/symmetric-matrix-fs-operation.h @@ -0,0 +1,107 @@ +/* + * SymmetricMatrix basic operation + * + * Authors: + * Marco Cecchetti + * + * Copyright 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 _NL_SYMMETRIC_MATRIX_FS_OPERATION_H_ +#define _NL_SYMMETRIC_MATRIX_FS_OPERATION_H_ + + +#include <2geom/numeric/symmetric-matrix-fs.h> +#include <2geom/numeric/symmetric-matrix-fs-trace.h> + + + + +namespace Geom { namespace NL { + +template +inline +SymmetricMatrix adj(const ConstBaseSymmetricMatrix & S) +{ + THROW_NOTIMPLEMENTED(); + return SymmetricMatrix(); +} + +template <> +inline +SymmetricMatrix<2> adj(const ConstBaseSymmetricMatrix<2> & S) +{ + SymmetricMatrix<2> result; + result.get<0,0>() = S.get<1,1>(); + result.get<1,0>() = -S.get<1,0>(); + result.get<1,1>() = S.get<0,0>(); + return result; +} + +template <> +inline +SymmetricMatrix<3> adj(const ConstBaseSymmetricMatrix<3> & S) +{ + SymmetricMatrix<3> result; + + result.get<0,0>() = S.get<1,1>() * S.get<2,2>() - S.get<1,2>() * S.get<2,1>(); + result.get<1,0>() = S.get<0,2>() * S.get<2,1>() - S.get<0,1>() * S.get<2,2>(); + result.get<1,1>() = S.get<0,0>() * S.get<2,2>() - S.get<0,2>() * S.get<2,0>(); + result.get<2,0>() = S.get<0,1>() * S.get<1,2>() - S.get<0,2>() * S.get<1,1>(); + result.get<2,1>() = S.get<0,2>() * S.get<1,0>() - S.get<0,0>() * S.get<1,2>(); + result.get<2,2>() = S.get<0,0>() * S.get<1,1>() - S.get<0,1>() * S.get<1,0>(); + return result; +} + +template +inline +SymmetricMatrix inverse(const ConstBaseSymmetricMatrix & S) +{ + SymmetricMatrix result = adj(S); + double d = det(S); + assert (d != 0); + result.scale (1/d); + return result; +} + +} /* end namespace NL*/ } /* end namespace Geom*/ + + +#endif // _NL_SYMMETRIC_MATRIX_FS_OPERATION_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/numeric/symmetric-matrix-fs-trace.h b/src/2geom/numeric/symmetric-matrix-fs-trace.h new file mode 100644 index 000000000..099c834a8 --- /dev/null +++ b/src/2geom/numeric/symmetric-matrix-fs-trace.h @@ -0,0 +1,433 @@ +/* + * SymmetricMatrix trace + * + * Authors: + * Marco Cecchetti + * + * Copyright 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 _NL_TRACE_H_ +#define _NL_TRACE_H_ + + +#include <2geom/numeric/matrix.h> +#include <2geom/numeric/symmetric-matrix-fs.h> + + + + + +namespace Geom { namespace NL { + + +namespace detail +{ + +/* + * helper routines + */ + +inline +int sgn_prod (int x, int y) +{ + if (x == 0 || y == 0) return 0; + if (x == y) return 1; + return -1; +} + +inline +bool abs_less (double x, double y) +{ + return (std::fabs(x) < std::fabs(y)); +} + + +/* + * trace K-th of symmetric matrix S of order N + */ +template +struct trace +{ + static + double evaluate (const ConstBaseSymmetricMatrix & S) + { + THROW_NOTIMPLEMENTED(); + return K; + } + +}; + +template +struct trace<1,N> +{ + static + double evaluate (const ConstBaseSymmetricMatrix & S) + { + double t = 0; + for (size_t i = 0; i < N; ++i) + { + t += S(i,i); + } + return t; + } +}; + +template +struct trace +{ + static + double evaluate (const ConstBaseSymmetricMatrix & S) + { + Matrix M(S); + return det(M); + } +}; + +/* + * trace for symmetric matrix of order 2 + */ +template <> +struct trace<1,2> +{ + static + double evaluate (const ConstBaseSymmetricMatrix<2> & S) + { + return (S.get<0,0>() + S.get<1,1>()); + } +}; + +template <> +struct trace<2,2> +{ + static + double evaluate (const ConstBaseSymmetricMatrix<2> & S) + { + return (S.get<0,0>() * S.get<1,1>() - S.get<0,1>() * S.get<1,0>()); + } +}; + + +/* + * trace for symmetric matrix of order 3 + */ +template <> +struct trace<1,3> +{ + static + double evaluate (const ConstBaseSymmetricMatrix<3> & S) + { + return (S.get<0,0>() + S.get<1,1>() + S.get<2,2>()); + } +}; + +template <> +struct trace<2,3> +{ + static + double evaluate (const ConstBaseSymmetricMatrix<3> & S) + { + double a00 = S.get<1,1>() * S.get<2,2>() - S.get<1,2>() * S.get<2,1>(); + double a11 = S.get<0,0>() * S.get<2,2>() - S.get<0,2>() * S.get<2,0>(); + double a22 = S.get<0,0>() * S.get<1,1>() - S.get<0,1>() * S.get<1,0>(); + return (a00 + a11 + a22); + } +}; + +template <> +struct trace<3,3> +{ + static + double evaluate (const ConstBaseSymmetricMatrix<3> & S) + { + double d = S.get<0,0>() * S.get<1,1>() * S.get<2,2>(); + d += (2 * S.get<1,0>() * S.get<2,0>() * S.get<2,1>()); + d -= (S.get<0,0>() * S.get<2,1>() * S.get<2,1>()); + d -= (S.get<1,1>() * S.get<2,0>() * S.get<2,0>()); + d -= (S.get<2,2>() * S.get<1,0>() * S.get<1,0>()); + return d; + } +}; + + +/* + * sign of trace K-th + */ +template +struct trace_sgn +{ + static + int evaluate (const ConstBaseSymmetricMatrix & S) + { + double d = trace::evaluate(S); + return sgn(d); + } +}; + + +/* + * sign of trace for symmetric matrix of order 2 + */ +template <> +struct trace_sgn<2,2> +{ + static + int evaluate (const ConstBaseSymmetricMatrix<2> & S) + { + double m00 = S.get<0,0>(); + double m10 = S.get<1,0>(); + double m11 = S.get<1,1>(); + + int sm00 = sgn (m00); + int sm10 = sgn (m10); + int sm11 = sgn (m11); + + if (sm10 == 0) + { + return sgn_prod (sm00, sm11); + } + else + { + int sm00m11 = sgn_prod (sm00, sm11); + if (sm00m11 == 1) + { + int e00, e10, e11; + double f00 = std::frexp (m00, &e00); + double f10 = std::frexp (m10, &e10); + double f11 = std::frexp (m11, &e11); + + int e0011 = e00 + e11; + int e1010 = e10 << 1; + int ed = e0011 - e1010; + + if (ed > 1) + { + return 1; + } + else if (ed < -1) + { + return -1; + } + else + { + double d = std::ldexp (f00 * f11, ed) - f10 * f10; + //std::cout << "trace_sgn<2,2>: det = " << d << std::endl; + double eps = std::ldexp (1, -50); + if (std::fabs(d) < eps) return 0; + return sgn (d); + } + } + return -1; + } + } +}; + + +/* + * sign of trace for symmetric matrix of order 3 + */ +template <> +struct trace_sgn<2,3> +{ + static + int evaluate (const ConstBaseSymmetricMatrix<3> & S) + { + double eps = std::ldexp (1, -50); + double t[6]; + + t[0] = S.get<1,1>() * S.get<2,2>(); + t[1] = - S.get<1,2>() * S.get<2,1>(); + t[2] = S.get<0,0>() * S.get<2,2>(); + t[3] = - S.get<0,2>() * S.get<2,0>(); + t[4] = S.get<0,0>() * S.get<1,1>(); + t[5] = - S.get<0,1>() * S.get<1,0>(); + + + double* maxp = std::max_element (t, t+6, abs_less); + int em; + std::frexp(*maxp, &em); + double d = 0; + for (size_t i = 0; i < 6; ++i) + { + d += t[i]; + } + double r = std::fabs (std::ldexp (d, -em)); // relative error + //std::cout << "trace_sgn<2,3>: d = " << d << std::endl; + //std::cout << "trace_sgn<2,3>: r = " << r << std::endl; + if (r < eps) return 0; + if (d > 0) return 1; + return -1; + } +}; + +template <> +struct trace_sgn<3,3> +{ + static + int evaluate (const ConstBaseSymmetricMatrix<3> & S) + { + + double eps = std::ldexp (1, -48); + double t[5]; + + t[0] = S.get<0,0>() * S.get<1,1>() * S.get<2,2>(); + t[1] = 2 * S.get<1,0>() * S.get<2,0>() * S.get<2,1>(); + t[2] = -(S.get<0,0>() * S.get<2,1>() * S.get<2,1>()); + t[3] = -(S.get<1,1>() * S.get<2,0>() * S.get<2,0>()); + t[4] = -(S.get<2,2>() * S.get<1,0>() * S.get<1,0>()); + + double* maxp = std::max_element (t, t+5, abs_less); + int em; + std::frexp(*maxp, &em); + double d = 0; + for (size_t i = 0; i < 5; ++i) + { + d += t[i]; + } + //std::cout << "trace_sgn<3,3>: d = " << d << std::endl; + double r = std::fabs (std::ldexp (d, -em)); // relative error + //std::cout << "trace_sgn<3,3>: r = " << r << std::endl; + + if (r < eps) return 0; + if (d > 0) return 1; + return -1; + } +}; // end struct trace_sgn<3,3> + +} // end namespace detail + + +template +inline +double trace (const ConstBaseSymmetricMatrix & _matrix) +{ + return detail::trace::evaluate(_matrix); +} + +template +inline +double trace (const ConstBaseSymmetricMatrix & _matrix) +{ + return detail::trace<1, N>::evaluate(_matrix); +} + +template +inline +double det (const ConstBaseSymmetricMatrix & _matrix) +{ + return detail::trace::evaluate(_matrix); +} + + +template +inline +int trace_sgn (const ConstBaseSymmetricMatrix & _matrix) +{ + return detail::trace_sgn::evaluate(_matrix); +} + +template +inline +int trace_sgn (const ConstBaseSymmetricMatrix & _matrix) +{ + return detail::trace_sgn<1, N>::evaluate(_matrix); +} + +template +inline +int det_sgn (const ConstBaseSymmetricMatrix & _matrix) +{ + return detail::trace_sgn::evaluate(_matrix); +} + +/* +template +inline +size_t rank (const ConstBaseSymmetricMatrix & S) +{ + THROW_NOTIMPLEMENTED(); + return 0; +} + +template <> +inline +size_t rank<2> (const ConstBaseSymmetricMatrix<2> & S) +{ + if (S.is_zero()) return 0; + double d = S.get<0,0>() * S.get<1,1>() - S.get<0,1>() * S.get<1,0>(); + if (d != 0) return 2; + return 1; +} + +template <> +inline +size_t rank<3> (const ConstBaseSymmetricMatrix<3> & S) +{ + if (S.is_zero()) return 0; + + double a20 = S.get<0,1>() * S.get<1,2>() - S.get<0,2>() * S.get<1,1>(); + double a21 = S.get<0,2>() * S.get<1,0>() - S.get<0,0>() * S.get<1,2>(); + double a22 = S.get<0,0>() * S.get<1,1>() - S.get<0,1>() * S.get<1,0>(); + double d = a20 * S.get<2,0>() + a21 * S.get<2,1>() + a22 * S.get<2,2>(); + + if (d != 0) return 3; + + if (a20 != 0 || a21 != 0 || a22 != 0) return 2; + + double a00 = S.get<1,1>() * S.get<2,2>() - S.get<1,2>() * S.get<2,1>(); + if (a00 != 0) return 2; + + double a10 = S.get<0,2>() * S.get<2,1>() - S.get<0,1>() * S.get<2,2>(); + if (a10 != 0) return 2; + + double a11 = S.get<0,0>() * S.get<2,2>() - S.get<0,2>() * S.get<2,0>(); + if (a11 != 0) return 2; + + return 1; +} +*/ + +} /* end namespace NL*/ } /* end namespace Geom*/ + + + + +#endif // _NL_TRACE_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/numeric/symmetric-matrix-fs.h b/src/2geom/numeric/symmetric-matrix-fs.h new file mode 100644 index 000000000..c1de27afd --- /dev/null +++ b/src/2geom/numeric/symmetric-matrix-fs.h @@ -0,0 +1,730 @@ +/* + * SymmetricMatrix, ConstSymmetricMatrixView, SymmetricMatrixView template + * classes implement fixed size symmetric matrix; "views" mimic the semantic + * of C++ references: any operation performed on a "view" is actually performed + * on the "viewed object" + * + * Authors: + * Marco Cecchetti + * + * Copyright 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 _NL_SYMMETRIC_MATRIX_FS_H_ +#define _NL_SYMMETRIC_MATRIX_FS_H_ + + +#include <2geom/numeric/vector.h> +#include <2geom/numeric/matrix.h> +#include <2geom/utils.h> +#include <2geom/exception.h> + +#include + +#include +#include // for std::pair +#include // for std::swap, std::copy +#include +#include + + + +namespace Geom { namespace NL { + + +namespace detail +{ + +template +struct index +{ + static const size_t K = index::K; +}; + +template +struct index +{ + static const size_t K = (((I+1) * I) >> 1) + J; +}; + +} // end namespace detail + + + + +template +class ConstBaseSymmetricMatrix; + +template +class BaseSymmetricMatrix; + +template +class SymmetricMatrix; + +template +class ConstSymmetricMatrixView; + +template +class SymmetricMatrixView; + + + +// declaration needed for friend clause +template +bool operator== (ConstBaseSymmetricMatrix const& _smatrix1, + ConstBaseSymmetricMatrix const& _smatrix2); + + + + +template +class ConstBaseSymmetricMatrix +{ + public: + const static size_t DIM = N; + const static size_t DATA_SIZE = ((DIM+1) * DIM) / 2; + + public: + + ConstBaseSymmetricMatrix (VectorView const& _data) + : m_data(_data) + { + } + + double operator() (size_t i, size_t j) const + { + return m_data[get_index(i,j)]; + } + + template + double get() const + { + BOOST_STATIC_ASSERT ((I < N && J < N)); + return m_data[detail::index::K]; + } + + + size_t rows() const + { + return DIM; + } + + size_t columns() const + { + return DIM; + } + + bool is_zero() const + { + return m_data.is_zero(); + } + + bool is_positive() const + { + return m_data.is_positive(); + } + + bool is_negative() const + { + return m_data.is_negative(); + } + + bool is_non_negative() const + { + return m_data.is_non_negative(); + } + + double min() const + { + return m_data.min(); + } + + double max() const + { + return m_data.max(); + } + + std::pair + min_index() const + { + std::pair indices(0,0); + double min_value = m_data[0]; + for (size_t i = 1; i < DIM; ++i) + { + for (size_t j = 0; j <= i; ++j) + { + if (min_value > (*this)(i,j)) + { + min_value = (*this)(i,j); + indices.first = i; + indices.second = j; + } + } + } + return indices; + } + + std::pair + max_index() const + { + std::pair indices(0,0); + double max_value = m_data[0]; + for (size_t i = 1; i < DIM; ++i) + { + for (size_t j = 0; j <= i; ++j) + { + if (max_value < (*this)(i,j)) + { + max_value = (*this)(i,j); + indices.first = i; + indices.second = j; + } + } + } + return indices; + } + + size_t min_on_row_index (size_t i) const + { + size_t idx = 0; + double min_value = (*this)(i,0); + for (size_t j = 1; j < DIM; ++j) + { + if (min_value > (*this)(i,j)) + { + min_value = (*this)(i,j); + idx = j; + } + } + return idx; + } + + size_t max_on_row_index (size_t i) const + { + size_t idx = 0; + double max_value = (*this)(i,0); + for (size_t j = 1; j < DIM; ++j) + { + if (max_value < (*this)(i,j)) + { + max_value = (*this)(i,j); + idx = j; + } + } + return idx; + } + + size_t min_on_column_index (size_t j) const + { + return min_on_row_index(j); + } + + size_t max_on_column_index (size_t j) const + { + return max_on_row_index(j); + } + + size_t min_on_diag_index () const + { + size_t idx = 0; + double min_value = (*this)(0,0); + for (size_t i = 1; i < DIM; ++i) + { + if (min_value > (*this)(i,i)) + { + min_value = (*this)(i,i); + idx = i; + } + } + return idx; + } + + size_t max_on_diag_index () const + { + size_t idx = 0; + double max_value = (*this)(0,0); + for (size_t i = 1; i < DIM; ++i) + { + if (max_value < (*this)(i,i)) + { + max_value = (*this)(i,i); + idx = i; + } + } + return idx; + } + + std::string str() const; + + ConstSymmetricMatrixView main_minor_const_view() const; + + SymmetricMatrix operator- () const; + + Vector operator* (ConstVectorView _vector) const + { + assert (_vector.size() == DIM); + Vector result(DIM, 0.0); + + for (size_t i = 0; i < DIM; ++i) + { + for (size_t j = 0; j < DIM; ++j) + { + result[i] += (*this)(i,j) * _vector[j]; + } + } + return result; + } + + protected: + static size_t get_index (size_t i, size_t j) + { + if (i < j) return get_index (j, i); + size_t k = (i+1) * i; + k >>= 1; + k += j; + return k; + } + + protected: + ConstVectorView get_data() const + { + return m_data; + } + + friend + bool operator== (ConstBaseSymmetricMatrix const& _smatrix1, + ConstBaseSymmetricMatrix const& _smatrix2); + + protected: + VectorView m_data; + +}; //end ConstBaseSymmetricMatrix + + +template +class BaseSymmetricMatrix : public ConstBaseSymmetricMatrix +{ + public: + typedef ConstBaseSymmetricMatrix base_type; + + + public: + + BaseSymmetricMatrix (VectorView const& _data) + : base_type(_data) + { + } + + using base_type::operator(); + + double& operator() (size_t i, size_t j) + { + return m_data[base_type::get_index(i,j)]; + } + + template + double& get() + { + BOOST_STATIC_ASSERT ((I < N && J < N)); + return m_data[detail::index::K]; + } + + void set_all (double x) + { + m_data.set_all(x); + } + + SymmetricMatrixView main_minor_view(); + + BaseSymmetricMatrix& transpose() const + { + return (*this); + } + + BaseSymmetricMatrix& translate (double c) + { + m_data.translate(c); + return (*this); + } + + BaseSymmetricMatrix& scale (double c) + { + m_data.scale(c); + return (*this); + } + + BaseSymmetricMatrix& operator+= (base_type const& _smatrix) + { + m_data += (static_cast(_smatrix).m_data); + return (*this); + } + + BaseSymmetricMatrix& operator-= (base_type const& _smatrix) + { + m_data -= (static_cast(_smatrix).m_data); + return (*this); + } + + using base_type::DIM; + using base_type::DATA_SIZE; + using base_type::m_data; + using base_type::operator-; + using base_type::operator*; + +}; //end BaseSymmetricMatrix + + +template +class SymmetricMatrix : public BaseSymmetricMatrix +{ + public: + typedef BaseSymmetricMatrix base_type; + typedef typename base_type::base_type base_base_type; + + using base_type::DIM; + using base_type::DATA_SIZE; + using base_type::m_data; + + public: + SymmetricMatrix () + : base_type (VectorView(m_adata, DATA_SIZE)) + { + } + + explicit + SymmetricMatrix (ConstVectorView _data) + : base_type (VectorView(m_adata, DATA_SIZE)) + { + assert (_data.size() == DATA_SIZE); + m_data = _data; + } + + explicit + SymmetricMatrix (const double _data[DATA_SIZE]) + : base_type (VectorView(m_adata, DATA_SIZE)) + { + std::copy (_data, _data + DATA_SIZE, m_adata); + } + + SymmetricMatrix (SymmetricMatrix const& _smatrix) + : base_type (VectorView(m_adata, DATA_SIZE)) + { + m_data = _smatrix.m_data; + } + + explicit + SymmetricMatrix (base_base_type const& _smatrix) + : base_type (VectorView(m_adata, DATA_SIZE)) + { + m_data = static_cast &>(_smatrix).m_data; + } + + explicit + SymmetricMatrix (ConstMatrixView const& _matrix) + : base_type (VectorView(m_adata, DATA_SIZE)) + { + assert (_matrix.rows() == N && _matrix.columns() == N); + for (size_t i = 0; i < N; ++i) + for (size_t j = 0; j <= i ; ++j) + (*this)(i,j) = _matrix(i,j); + } + + SymmetricMatrix& operator= (SymmetricMatrix const& _smatrix) + { + m_data = _smatrix.m_data; + return (*this); + } + + SymmetricMatrix& operator= (base_base_type const& _smatrix) + { + + m_data = static_cast &>(_smatrix).m_data; + return (*this); + } + + SymmetricMatrix& operator= (ConstMatrixView const& _matrix) + { + assert (_matrix.rows() == N && _matrix.columns() == N); + for (size_t i = 0; i < N; ++i) + for (size_t j = 0; j <= i ; ++j) + (*this)(i,j) = _matrix(i,j); + + return (*this); + } + + // needed for accessing m_adata + friend class ConstSymmetricMatrixView; + friend class SymmetricMatrixView; + private: + double m_adata[DATA_SIZE]; +}; //end SymmetricMatrix + + +template +class ConstSymmetricMatrixView : public ConstBaseSymmetricMatrix +{ + public: + typedef ConstBaseSymmetricMatrix base_type; + + using base_type::DIM; + using base_type::DATA_SIZE; + using base_type::m_data; + + + public: + + explicit + ConstSymmetricMatrixView (ConstVectorView _data) + : base_type (const_vector_view_cast(_data)) + { + assert (_data.size() == DATA_SIZE); + } + + explicit + ConstSymmetricMatrixView (const double _data[DATA_SIZE]) + : base_type (const_vector_view_cast (ConstVectorView (_data, DATA_SIZE))) + { + } + + ConstSymmetricMatrixView (const ConstSymmetricMatrixView & _smatrix) + : base_type (_smatrix.m_data) + { + } + + ConstSymmetricMatrixView (const base_type & _smatrix) + : base_type (static_cast(_smatrix).m_data) + { + } + +}; //end SymmetricMatrix + + +// declaration needed for friend clause +template +void swap_view(SymmetricMatrixView & m1, SymmetricMatrixView & m2); + + +template +class SymmetricMatrixView : public BaseSymmetricMatrix +{ + public: + typedef BaseSymmetricMatrix base_type; + typedef typename base_type::base_type base_base_type; + + using base_type::DIM; + using base_type::DATA_SIZE; + using base_type::m_data; + + public: + + explicit + SymmetricMatrixView (VectorView _data) + : base_type (_data) + { + assert (_data.size() == DATA_SIZE); + } + + explicit + SymmetricMatrixView (double _data[DATA_SIZE]) + : base_type (VectorView (_data, DATA_SIZE)) + { + } + + SymmetricMatrixView (const SymmetricMatrixView & _smatrix) + : base_type (_smatrix.m_data) + { + } + + SymmetricMatrixView (SymmetricMatrix & _smatrix) + : base_type (VectorView (_smatrix.m_adata, DATA_SIZE)) + { + } + + SymmetricMatrixView& operator= (const SymmetricMatrixView & _smatrix) + { + m_data = _smatrix.m_data; + return (*this); + } + + SymmetricMatrixView& operator= (const base_base_type & _smatrix) + { + m_data = static_cast &>(_smatrix).m_data; + return (*this); + } + + friend + void swap_view(SymmetricMatrixView & m1, SymmetricMatrixView & m2); + +}; //end SymmetricMatrix + + + + +/* + * class ConstBaseSymmetricMatrix methods + */ + +template +inline +std::string ConstBaseSymmetricMatrix::str() const +{ + std::ostringstream oss; + oss << (*this); + return oss.str(); +} + +template +inline +ConstSymmetricMatrixView +ConstBaseSymmetricMatrix::main_minor_const_view() const +{ + ConstVectorView data(m_data.get_gsl_vector()->data, DATA_SIZE - DIM); + ConstSymmetricMatrixView mm(data); + return mm; +} + +template +inline +SymmetricMatrix ConstBaseSymmetricMatrix::operator- () const +{ + SymmetricMatrix result; + for (size_t i = 0; i < DATA_SIZE; ++i) + { + result.m_data[i] = -m_data[i]; + } + return result; +} + + +/* + * class ConstBaseSymmetricMatrix friend free functions + */ + +template +inline +bool operator== (ConstBaseSymmetricMatrix const& _smatrix1, + ConstBaseSymmetricMatrix const& _smatrix2) +{ + return (_smatrix1.m_data == _smatrix2.m_data); +} + +/* + * class ConstBaseSymmetricMatrix related free functions + */ + +template< size_t N, class charT > +inline +std::basic_ostream & +operator<< (std::basic_ostream & os, + const ConstBaseSymmetricMatrix & _matrix) +{ + os << "[[" << _matrix(0,0); + for (size_t j = 1; j < N; ++j) + { + os << ", " << _matrix(0,j); + } + os << "]"; + for (size_t i = 1; i < N; ++i) + { + os << "\n [" << _matrix(i,0); + for (size_t j = 1; j < N; ++j) + { + os << ", " << _matrix(i,j); + } + os << "]"; + } + os << "]"; + return os; +} + + +/* + * class ConstBaseSymmetricMatrix specialized methods + */ + +template<> +inline +size_t ConstBaseSymmetricMatrix<2>::get_index (size_t i, size_t j) +{ + return (i+j); +} + +template<> +inline +size_t ConstBaseSymmetricMatrix<3>::get_index (size_t i, size_t j) +{ + size_t k = i + j; + if (i == 2 || j == 2) ++k; + return k; +} + + +/* + * class BaseSymmetricMatrix methods + */ + +template +inline +SymmetricMatrixView BaseSymmetricMatrix::main_minor_view() +{ + VectorView data(m_data.get_gsl_vector()->data, DATA_SIZE - DIM); + SymmetricMatrixView mm(data); + return mm; +} + + +/* + * class SymmetricMatrixView friend free functions + */ + +template +inline +void swap_view(SymmetricMatrixView & m1, SymmetricMatrixView & m2) +{ + swap_view(m1.m_data, m2.m_data); +} + +} /* end namespace NL*/ } /* end namespace Geom*/ + + + + +#endif // _NL_SYMMETRIC_MATRIX_FS_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 : -- cgit v1.2.3 From 5aae9964808fa5447f7574c592b7049012575cca Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Thu, 3 Feb 2011 19:40:17 +0100 Subject: Translations. Context removed in filter-enums (context support too complex to be added here) and replaced with context in input and toolbox where needed. inkscape.pot and fr.po updated accordingly. (bzr r10030) --- src/filter-enums.cpp | 10 +++++----- src/ui/dialog/input.cpp | 2 +- src/widgets/toolbox.cpp | 6 +++--- 3 files changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/filter-enums.cpp b/src/filter-enums.cpp index 2f6d2f64b..315b242bf 100644 --- a/src/filter-enums.cpp +++ b/src/filter-enums.cpp @@ -48,11 +48,11 @@ const EnumDataConverter FPInputConverter(FPInputData, FPIN // feBlend const EnumData BlendModeData[Inkscape::Filters::BLEND_ENDMODE] = { - {Inkscape::Filters::BLEND_NORMAL, C_("Filter blend mode", "Normal"), "normal"}, - {Inkscape::Filters::BLEND_MULTIPLY, C_("Filter blend mode", "Multiply"), "multiply"}, - {Inkscape::Filters::BLEND_SCREEN, C_("Filter blend mode", "Screen"), "screen"}, - {Inkscape::Filters::BLEND_DARKEN, C_("Filter blend mode", "Darken"), "darken"}, - {Inkscape::Filters::BLEND_LIGHTEN, C_("Filter blend mode", "Lighten"), "lighten"} + {Inkscape::Filters::BLEND_NORMAL, _("Normal"), "normal"}, + {Inkscape::Filters::BLEND_MULTIPLY, _("Multiply"), "multiply"}, + {Inkscape::Filters::BLEND_SCREEN, _("Screen"), "screen"}, + {Inkscape::Filters::BLEND_DARKEN, _("Darken"), "darken"}, + {Inkscape::Filters::BLEND_LIGHTEN, _("Lighten"), "lighten"} }; const EnumDataConverter BlendModeConverter(BlendModeData, Inkscape::Filters::BLEND_ENDMODE); diff --git a/src/ui/dialog/input.cpp b/src/ui/dialog/input.cpp index 34d55a440..6869aa97b 100644 --- a/src/ui/dialog/input.cpp +++ b/src/ui/dialog/input.cpp @@ -347,7 +347,7 @@ static std::map &getModeToString() static std::map mapping; if (mapping.empty()) { mapping[Gdk::MODE_DISABLED] = _("Disabled"); - mapping[Gdk::MODE_SCREEN] = _("Screen"); + mapping[Gdk::MODE_SCREEN] = C_("Input device", "Screen"); mapping[Gdk::MODE_WINDOW] = _("Window"); } diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index d9e72fe50..da919e42e 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -7671,7 +7671,7 @@ static void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions /* Line height */ { // Drop down menu - gchar const* labels[] = {_("Smaller spacing"), 0, 0, 0, 0, _("Normal"), 0, 0, 0, 0, 0, _("Larger spacing")}; + gchar const* labels[] = {_("Smaller spacing"), 0, 0, 0, 0, C_("Text tool", "Normal"), 0, 0, 0, 0, 0, _("Larger spacing")}; gdouble values[] = { 0.5, 0.6, 0.7, 0.8, 0.9, 1.0, 1.1, 1,2, 1.3, 1.4, 1.5, 2.0}; EgeAdjustmentAction *eact = create_adjustment_action( @@ -7702,7 +7702,7 @@ static void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions /* Word spacing */ { // Drop down menu - gchar const* labels[] = {_("Negative spacing"), 0, 0, 0, _("Normal"), 0, 0, 0, 0, 0, 0, 0, _("Positive spacing")}; + gchar const* labels[] = {_("Negative spacing"), 0, 0, 0, C_("Text tool", "Normal"), 0, 0, 0, 0, 0, 0, 0, _("Positive spacing")}; gdouble values[] = {-2.0, -1.5, -1.0, -0.5, 0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0}; EgeAdjustmentAction *eact = create_adjustment_action( @@ -7733,7 +7733,7 @@ static void sp_text_toolbox_prep(SPDesktop *desktop, GtkActionGroup* mainActions /* Letter spacing */ { // Drop down menu - gchar const* labels[] = {_("Negative spacing"), 0, 0, 0, _("Normal"), 0, 0, 0, 0, 0, 0, 0, _("Positive spacing")}; + gchar const* labels[] = {_("Negative spacing"), 0, 0, 0, C_("Text tool", "Normal"), 0, 0, 0, 0, 0, 0, 0, _("Positive spacing")}; gdouble values[] = {-2.0, -1.5, -1.0, -0.5, 0, 0.5, 1.0, 1.5, 2.0, 2.5, 3.0, 4.0, 5.0}; EgeAdjustmentAction *eact = create_adjustment_action( -- cgit v1.2.3 From 7c620545cbc054aaf59605e37b50bdd3c1cb1133 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Fri, 4 Feb 2011 00:13:20 +0100 Subject: Fix Linux build after 2Geom update (bzr r10031) --- src/2geom/Makefile_insert | 109 ++++----- src/2geom/bezier-curve.cpp | 358 ++++++++++++++++++++++++++++++ src/2geom/chebyshev.cpp | 126 ----------- src/2geom/chebyshev.h | 30 --- src/2geom/curve-helpers.cpp | 94 -------- src/2geom/curve.cpp | 125 +++++++++++ src/extension/dbus/dbus-init.cpp | 2 + src/extension/dbus/document-interface.cpp | 45 ++-- src/extension/dbus/document-interface.h | 8 + 9 files changed, 563 insertions(+), 334 deletions(-) create mode 100644 src/2geom/bezier-curve.cpp delete mode 100644 src/2geom/chebyshev.cpp delete mode 100644 src/2geom/chebyshev.h delete mode 100644 src/2geom/curve-helpers.cpp create mode 100644 src/2geom/curve.cpp (limited to 'src') diff --git a/src/2geom/Makefile_insert b/src/2geom/Makefile_insert index ead0e3517..174f56433 100644 --- a/src/2geom/Makefile_insert +++ b/src/2geom/Makefile_insert @@ -6,109 +6,110 @@ rm -f 2geom/lib2geom.a $(2geom_lib2geom_a_OBJECTS) 2geom_lib2geom_a_SOURCES = \ - 2geom/basic-intersection.cpp \ - 2geom/bezier-clipping.cpp \ - 2geom/utils.cpp \ - 2geom/bezier-utils.cpp \ - 2geom/circle-circle.cpp \ - 2geom/circle.cpp \ - 2geom/circle.h \ - 2geom/conjugate_gradient.cpp \ - 2geom/convex-cover.cpp \ - 2geom/crossing.cpp \ - 2geom/curve-helpers.cpp \ - 2geom/d2-sbasis.cpp \ - 2geom/ellipse.cpp \ - 2geom/elliptical-arc.cpp \ - 2geom/geom.cpp \ - 2geom/line.cpp \ 2geom/affine.cpp \ - 2geom/nearest-point.cpp \ - 2geom/path-intersection.cpp \ - 2geom/path.cpp \ - 2geom/pathvector.cpp \ - 2geom/piecewise.cpp \ - 2geom/point.cpp \ - 2geom/poly.cpp \ - 2geom/quadtree.cpp \ - 2geom/region.cpp \ - 2geom/sbasis-2d.cpp \ - 2geom/sbasis-geometric.cpp \ - 2geom/sbasis-math.cpp \ - 2geom/sbasis-poly.cpp \ - 2geom/sbasis-roots.cpp \ - 2geom/sbasis-to-bezier.cpp \ - 2geom/sbasis.cpp \ - 2geom/shape.cpp \ - 2geom/solve-bezier-one-d.cpp \ - 2geom/solve-bezier-parametric.cpp \ - 2geom/svg-elliptical-arc.cpp \ - 2geom/svg-path-parser.cpp \ - 2geom/svg-path.cpp \ - 2geom/sweep.cpp \ - 2geom/transforms.cpp \ 2geom/angle.h \ + 2geom/basic-intersection.cpp \ 2geom/basic-intersection.h \ + 2geom/bezier-clipping.cpp \ + 2geom/bezier-curve.cpp \ 2geom/bezier-curve.h \ + 2geom/bezier.h \ 2geom/bezier-to-sbasis.h \ + 2geom/bezier-utils.cpp \ 2geom/bezier-utils.h \ - 2geom/bezier.h \ 2geom/choose.h \ + 2geom/circle-circle.cpp \ + 2geom/circle.cpp \ + 2geom/circle.h \ 2geom/circulator.h \ 2geom/concepts.h \ + 2geom/conjugate_gradient.cpp \ 2geom/conjugate_gradient.h \ + 2geom/convex-cover.cpp \ 2geom/convex-cover.h \ 2geom/coord.h \ + 2geom/crossing.cpp \ 2geom/crossing.h \ + 2geom/curve.cpp \ 2geom/curve.h \ 2geom/curves.h \ - 2geom/d2-sbasis.h \ 2geom/d2.h \ + 2geom/d2-sbasis.cpp \ + 2geom/d2-sbasis.h \ + 2geom/ellipse.cpp \ 2geom/ellipse.h \ + 2geom/elliptical-arc.cpp \ 2geom/elliptical-arc.h \ 2geom/exception.h \ 2geom/forward.h \ + 2geom/geom.cpp \ 2geom/geom.h \ 2geom/hvlinesegment.h \ 2geom/interval.h \ 2geom/isnan.h \ - 2geom/line.h \ 2geom/linear.h \ + 2geom/line.cpp \ + 2geom/line.h \ 2geom/matrix.h \ + 2geom/nearest-point.cpp \ 2geom/nearest-point.h \ + 2geom/numeric/fitting-model.h \ + 2geom/numeric/fitting-tool.h \ + 2geom/numeric/linear_system.h \ + 2geom/numeric/matrix.cpp \ + 2geom/numeric/matrix.h \ + 2geom/numeric/vector.h \ 2geom/ord.h \ - 2geom/path-intersection.h \ + 2geom/path.cpp \ 2geom/path.h \ + 2geom/path-intersection.cpp \ + 2geom/path-intersection.h \ + 2geom/pathvector.cpp \ 2geom/pathvector.h \ + 2geom/piecewise.cpp \ 2geom/piecewise.h \ + 2geom/point.cpp \ + 2geom/point.h \ 2geom/point-l.h \ 2geom/point-ops.h \ - 2geom/point.h \ + 2geom/poly.cpp \ 2geom/poly.h \ + 2geom/quadtree.cpp \ 2geom/quadtree.h \ 2geom/ray.h \ 2geom/rect.h \ + 2geom/region.cpp \ 2geom/region.h \ + 2geom/sbasis-2d.cpp \ 2geom/sbasis-2d.h \ + 2geom/sbasis.cpp \ 2geom/sbasis-curve.h \ + 2geom/sbasis-geometric.cpp \ 2geom/sbasis-geometric.h \ + 2geom/sbasis.h \ + 2geom/sbasis-math.cpp \ 2geom/sbasis-math.h \ + 2geom/sbasis-poly.cpp \ 2geom/sbasis-poly.h \ + 2geom/sbasis-roots.cpp \ + 2geom/sbasis-to-bezier.cpp \ 2geom/sbasis-to-bezier.h \ - 2geom/sbasis.h \ + 2geom/shape.cpp \ 2geom/shape.h \ + 2geom/solve-bezier-one-d.cpp \ + 2geom/solve-bezier-parametric.cpp \ 2geom/solver.h \ 2geom/sturm.h \ + 2geom/svg-elliptical-arc.cpp \ 2geom/svg-elliptical-arc.h \ - 2geom/svg-path-parser.h \ + 2geom/svg-path.cpp \ 2geom/svg-path.h \ + 2geom/svg-path-parser.cpp \ + 2geom/svg-path-parser.h \ + 2geom/sweep.cpp \ 2geom/sweep.h \ + 2geom/transforms.cpp \ 2geom/transforms.h \ - 2geom/utils.h \ - 2geom/numeric/matrix.cpp \ - 2geom/numeric/fitting-model.h \ - 2geom/numeric/fitting-tool.h \ - 2geom/numeric/linear_system.h \ - 2geom/numeric/matrix.h \ - 2geom/numeric/vector.h + 2geom/utils.cpp \ + 2geom/utils.h diff --git a/src/2geom/bezier-curve.cpp b/src/2geom/bezier-curve.cpp new file mode 100644 index 000000000..1a2e079bf --- /dev/null +++ b/src/2geom/bezier-curve.cpp @@ -0,0 +1,358 @@ +/** + * \file + * \brief Bezier curve + * + *//* + * Authors: + * MenTaLguY + * Marco Cecchetti + * Krzysztof Kosiński + * + * 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. + */ + +#include <2geom/bezier-curve.h> + +namespace Geom +{ + +/** + * @class BezierCurve + * @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. + * + * Let \f$\mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\ldots\mathbf{p}_n}\f$ denote a Bezier curve + * of order \f$n\f$ defined by the points \f$\mathbf{p}_0, \mathbf{p}_1, \ldots, \mathbf{p}_n\f$. + * Bezier curve of order 1 is a linear interpolation curve between two points, defined as + * \f[ \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1}(t) = (1-t)\mathbf{p}_0 + t\mathbf{p}_1 \f] + * If we now substitute points \f$\mathbf{p_0}\f$ and \f$\mathbf{p_1}\f$ in this definition + * by linear interpolations, we get the definition of a Bezier curve of order 2, also called + * a quadratic Bezier curve. + * \f{align*}{ \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\mathbf{p}_2}(t) + &= (1-t) \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1}(t) + t \mathbf{B}_{\mathbf{p}_1\mathbf{p}_2}(t) \\ + \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\mathbf{p}_2}(t) + &= (1-t)^2\mathbf{p}_0 + 2(1-t)t\mathbf{p}_1 + t^2\mathbf{p}_2 \f} + * By substituting points for quadratic Bezier curves in the original definition, + * we get a Bezier curve of order 3, called a cubic Bezier curve. + * \f{align*}{ \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\mathbf{p}_2\mathbf{p}_3}(t) + &= (1-t) \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\mathbf{p}_2}(t) + + t \mathbf{B}_{\mathbf{p}_1\mathbf{p}_2\mathbf{p}_3}(t) \\ + \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\mathbf{p}_2\mathbf{p}_3}(t) + &= (1-t)^3\mathbf{p}_0+3(1-t)^2t\mathbf{p}_1+3(1-t)t^2\mathbf{p}_2+t^3\mathbf{p}_3 \f} + * In general, a Bezier curve or order \f$n\f$ can be recursively defined as + * \f[ \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\ldots\mathbf{p}_n}(t) + = (1-t) \mathbf{B}_{\mathbf{p}_0\mathbf{p}_1\ldots\mathbf{p}_{n-1}}(t) + + t \mathbf{B}_{\mathbf{p}_1\mathbf{p}_2\ldots\mathbf{p}_n}(t) \f] + * + * This substitution can be repeated an arbitrary number of times. To picture this, imagine + * the evaluation of a point on the curve as follows: first, all control points are joined with + * straight lines, and a point corresponding to the selected time value is marked on them. + * Then, the marked points are joined with straight lines and the point corresponding to + * the time value is marked. This is repeated until only one marked point remains, which is the + * point at the selected time value. + * + * @image html bezier-curve-evaluation.png "Evaluation of the Bezier curve" + * + * An important property of the Bezier curves is that their parameters (control points) + * 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 + * 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. + * Note that if you create a generic BezierCurve, you cannot use a dynamic cast to those more + * specific types, and you might face a slight preformance penalty relative to the more specific + * classes. To obtain an instance of the correct optimized type, use the optimize() + * or duplicate() methods. The difference is that optimize() will not create a new object + * if it can't be optimized or is already an instance of one of the specific types, while + * duplicate() will always create a new object. + * + * @ingroup Curves + */ + +/** @brief Create an optimized instance of the curve. + * If the curve was created as a generic Bezier curve but has an order between 1 and 3, + * this method will create a newly allocated curve that is a LineSegment, a QuadraticBezier, + * or a CubicBezier. For other cases it returns the pointer to the current curve, to avoid + * allocating extra memory. Be careful when you use this method, because whether you have + * to delete the returned object or not depends on its return value! If easier deletion + * semantics are required, you can use the duplicate() method instead, which returns + * optimized objects by default. + * @return Pointer to a curve that is an instance of LineSegment, QuadraticBezier + * or CubicBezier based on the order. If the object is already an instance + * of te more specific types or the order is above 3, a pointer to the original + * object is returned instead, and no memory is allocated. */ +BezierCurve *BezierCurve::optimize() const +{ + switch(order()) { + case 1: + if (!dynamic_cast(this)) + return new LineSegment((*this)[0], (*this)[1]); + break; + case 2: + if (!dynamic_cast(this)) + return new QuadraticBezier((*this)[0], (*this)[1], (*this)[2]); + break; + case 3: + if (!dynamic_cast(this)) + return new CubicBezier((*this)[0], (*this)[1], (*this)[2], (*this)[3]); + break; + } + return const_cast(this); +} +Curve *BezierCurve::duplicate() const +{ + switch(order()) { + case 1: + return new LineSegment((*this)[0], (*this)[1]); + case 2: + return new QuadraticBezier((*this)[0], (*this)[1], (*this)[2]); + case 3: + return new CubicBezier((*this)[0], (*this)[1], (*this)[2], (*this)[3]); + } + return new BezierCurve(*this); +} + +Curve *BezierCurve::derivative() const +{ + if (order() == 1) { + double dx = inner[X][1] - inner[X][0], dy = inner[Y][1] - inner[Y][0]; + return new LineSegment(Point(dx,dy),Point(dx,dy)); + } + return new BezierCurve(Geom::derivative(inner[X]), Geom::derivative(inner[Y])); +} + +Coord BezierCurve::length(Coord tolerance) const +{ + switch (order()) + { + case 0: + return 0.0; + case 1: + return distance(initialPoint(), finalPoint()); + case 2: + { + std::vector pts = points(); + return bezier_length(pts[0], pts[1], pts[2], tolerance); + } + case 3: + { + std::vector pts = points(); + return bezier_length(pts[0], pts[1], pts[2], pts[3], tolerance); + } + default: + return bezier_length(points(), tolerance); + } +} + +/** + * @class LineSegment + * @brief Linear segment, a special case of a Bezier curve. + * + * This class uses some optimizations for a linear segment (a Bezier curve of order 1). + * Note that if you created a BezierCurve, you will not be able to cast it to a LineSegment + * using a dynamic cast regardless of its order - use the optimize() method. + * + * @ingroup Curves */ +Coord LineSegment::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); +} + + +/** + * @class QuadraticBezier + * @brief Quadratic Bezier curve. + * Note that if you created a BezierCurve, you will not be able to cast it to a QuadraticBezier + * using a dynamic cast regardless of its order - use the optimize() method. + * @ingroup Curves */ + +Coord QuadraticBezier::length(Coord tolerance) const +{ + std::vector pts = points(); + return bezier_length(pts[0], pts[1], pts[2], tolerance); +} + +/** + * @class CubicBezier + * @brief Cubic Bezier curve. + * Note that if you created a BezierCurve, you will not be able to cast it to a CubicBezier + * using a dynamic cast regardless of its order - use the optimize() method. + * @ingroup Curves */ + +Coord CubicBezier::length(Coord tolerance) const +{ + std::vector pts = points(); + return bezier_length(pts[0], pts[1], pts[2], pts[3], tolerance); +} + +static Coord bezier_length_internal(std::vector &v1, Coord tolerance) +{ + /* The Bezier length algorithm used in 2Geom utilizes a simple fact: + * the Bezier curve is longer than the distance between its endpoints + * but shorter than the length of the polyline formed by its control + * points. When the difference between the two values is smaller than the + * error tolerance, we can be sure that the true value is no further than + * 2*tolerance from their arithmetic mean. When it's larger, we recursively + * subdivide the Bezier curve into two parts and add their lengths. + */ + Coord lower = distance(v1.front(), v1.back()); + Coord upper = 0.0; + for (size_t i = 0; i < v1.size() - 1; ++i) { + upper += distance(v1[i], v1[i+1]); + } + if (upper - lower < 2*tolerance) { + return (lower + upper) / 2; + } + + + std::vector v2 = v1; + + /* Compute the right subdivision directly in v1 and the left one in v2. + * Explanation of the algorithm used: + * We have to compute the left and right edges of this triangle in which + * the top row are the control points of the Bezier curve, and each cell + * is equal to the arithmetic mean of the cells directly above it + * to the right and left. This corresponds to subdividing the Bezier curve + * at time value 0.5: the left edge has the control points of the first + * portion of the Bezier curve and the right edge - the second one. + * In the example we subdivide a curve with 5 control points (order 4). + * + * Start: + * 0 1 2 3 4 + * ? ? ? ? + * ? ? ? + * ? ? + * ? + * # means we have overwritten the value, ? means we don't know + * the value yet. Numbers mean the value is at i-th position in the vector. + * + * After loop with i==1 + * # 1 2 3 4 + * 0 ? ? ? -> write 0 to v2[1] + * ? ? ? + * ? ? + * ? + * + * After loop with i==2 + * # # 2 3 4 + * # 1 ? ? + * 0 ? ? -> wirte 0 to v2[2] + * ? ? + * ? + * + * After loop with i==3 + * # # # 3 4 + * # # 2 ? + * # 1 ? + * 0 ? -> write 0 to v2[3] + * ? + * + * After loop with i==4, we have the right edge of the triangle in v1, + * and we write the last value needed for the left edge in v2[4]. + */ + + for (size_t i = 1; i < v1.size(); ++i) { + for (size_t j = i; j > 0; --j) { + v1[j-1] = 0.5 * (v1[j-1] + v1[j]); + } + v2[i] = v1[0]; + } + + return bezier_length_internal(v1, 0.5*tolerance) + bezier_length_internal(v2, 0.5*tolerance); +} + +/** @brief Compute the length of a bezier curve given by a vector of its control points + * @relates BezierCurve */ +Coord bezier_length(std::vector const &points, Coord tolerance) +{ + if (points.size() < 2) return 0.0; + std::vector v1 = points; + return bezier_length_internal(v1, tolerance); +} + +/** @brief Compute the length of a quadratic bezier curve given by its control points + * @relates QuadraticBezier */ +Coord bezier_length(Point a0, Point a1, Point a2, Coord tolerance) +{ + Coord lower = distance(a0, a2); + Coord upper = distance(a0, a1) + distance(a1, a2); + + if (upper - lower < 2*tolerance) return (lower + upper)/2; + + Point // Casteljau subdivision + // b0 = a0, + // c0 = a2, + b1 = 0.5*(a0 + a1), + c1 = 0.5*(a1 + a2), + b2 = 0.5*(b1 + c1); // == c2 + return bezier_length(a0, b1, b2, 0.5*tolerance) + bezier_length(b2, c1, a2, 0.5*tolerance); +} + +/** @brief Compute the length of a cubic bezier curve given by its control points + * @relates CubicBezier */ +Coord bezier_length(Point a0, Point a1, Point a2, Point a3, Coord tolerance) +{ + Coord lower = distance(a0, a3); + Coord upper = distance(a0, a1) + distance(a1, a2) + distance(a2, a3); + + if (upper - lower < 2*tolerance) return (lower + upper)/2; + + Point // Casteljau subdivision + // b0 = a0, + // c0 = a3, + b1 = 0.5*(a0 + a1), + t0 = 0.5*(a1 + a2), + c1 = 0.5*(a2 + a3), + b2 = 0.5*(b1 + t0), + c2 = 0.5*(t0 + c1), + b3 = 0.5*(b2 + c2); // == c3 + return bezier_length(a0, b1, b2, b3, 0.5*tolerance) + bezier_length(b3, c2, c1, a3, 0.5*tolerance); +} + +} // end 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:fileencoding=utf-8:textwidth=99 : diff --git a/src/2geom/chebyshev.cpp b/src/2geom/chebyshev.cpp deleted file mode 100644 index c886daf88..000000000 --- a/src/2geom/chebyshev.cpp +++ /dev/null @@ -1,126 +0,0 @@ -#include <2geom/chebyshev.h> - -#include <2geom/sbasis.h> -#include <2geom/sbasis-poly.h> - -#include -using std::vector; - -#include -#include - -namespace Geom{ - -SBasis cheb(unsigned n) { - static std::vector basis; - if(basis.empty()) { - basis.push_back(Linear(1,1)); - basis.push_back(Linear(0,1)); - } - for(unsigned i = basis.size(); i <= n; i++) { - basis.push_back(Linear(0,2)*basis[i-1] - basis[i-2]); - } - - return basis[n]; -} - -SBasis cheb_series(unsigned n, double* cheb_coeff) { - SBasis r; - for(unsigned i = 0; i < n; i++) { - double cof = cheb_coeff[i]; - //if(i == 0) - //cof /= 2; - r += cheb(i)*cof; - } - - return r; -} - -SBasis clenshaw_series(unsigned m, double* cheb_coeff) { - /** b_n = a_n - b_n-1 = 2*x*b_n + a_n-1 - b_n-k = 2*x*b_{n-k+1} + a_{n-k} - b_{n - k + 2} - b_0 = x*b_1 + a_0 - b_2 - */ - - double a = -1, b = 1; - SBasis d, dd; - SBasis y = (Linear(0, 2) - (a+b)) / (b-a); - SBasis y2 = 2*y; - for(int j = m - 1; j >= 1; j--) { - SBasis sv = d; - d = y2*d - dd + cheb_coeff[j]; - dd = sv; - } - - return y*d - dd + 0.5*cheb_coeff[0]; -} - -SBasis chebyshev_approximant (double (*f)(double,void*), int order, Interval in, void* p) { - gsl_cheb_series *cs = gsl_cheb_alloc (order+2); - - gsl_function F; - - F.function = f; - F.params = p; - - gsl_cheb_init (cs, &F, in[0], in[1]); - - SBasis r = compose(clenshaw_series(order, cs->c), Linear(-1,1)); - - gsl_cheb_free (cs); - return r; -} - -struct wrap { - double (*f)(double,void*); - void* pp; - double fa, fb; - Interval in; -}; - -double f_interp(double x, void* p) { - struct wrap *wr = (struct wrap *)p; - double z = (x - wr->in[0]) / (wr->in[1] - wr->in[0]); - return (wr->f)(x, wr->pp) - ((1 - z)*wr->fa + z*wr->fb); -} - -SBasis chebyshev_approximant_interpolating (double (*f)(double,void*), - int order, Interval in, void* p) { - double fa = f(in[0], p); - double fb = f(in[1], p); - struct wrap wr; - wr.fa = fa; - wr.fb = fb; - wr.in = in; - printf("%f %f\n", fa, fb); - wr.f = f; - wr.pp = p; - return compose(Linear(in[0], in[1]), Linear(fa, fb)) + chebyshev_approximant(f_interp, order, in, &wr) + Linear(fa, fb); -} - -SBasis chebyshev(unsigned n) { - static std::vector basis; - if(basis.empty()) { - basis.push_back(Linear(1,1)); - basis.push_back(Linear(0,1)); - } - for(unsigned i = basis.size(); i <= n; i++) { - basis.push_back(Linear(0,2)*basis[i-1] - basis[i-2]); - } - - return basis[n]; -} - -}; - -/* - 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/chebyshev.h b/src/2geom/chebyshev.h deleted file mode 100644 index f729e1f07..000000000 --- a/src/2geom/chebyshev.h +++ /dev/null @@ -1,30 +0,0 @@ -#ifndef _CHEBYSHEV -#define _CHEBYSHEV - -#include <2geom/sbasis.h> -#include <2geom/interval.h> - -/*** Conversion between Chebyshev approximation and SBasis. - * - */ - -namespace Geom{ - -SBasis chebyshev_approximant (double (*f)(double,void*), int order, Interval in, void* p=0); -SBasis chebyshev_approximant_interpolating (double (*f)(double,void*), int order, Interval in, void* p=0); -SBasis chebyshev(unsigned n); - -}; - -/* - 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 : - -#endif diff --git a/src/2geom/curve-helpers.cpp b/src/2geom/curve-helpers.cpp deleted file mode 100644 index 0ecd7d425..000000000 --- a/src/2geom/curve-helpers.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/* - * - * Authors: - * MenTaLguY - * Marco Cecchetti - * - * 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 - * 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/curve.h> -#include <2geom/ord.h> - - -namespace Geom -{ - -int CurveHelpers::root_winding(Curve const &c, Point p) { - std::vector ts = c.roots(p[Y], Y); - - if(ts.empty()) return 0; - - double const fudge = 0.01; //fudge factor used on first and last - - std::sort(ts.begin(), ts.end()); - - // winding determined by crossings at roots - int wind=0; - // previous time - double pt = ts.front() - fudge; - for ( std::vector::iterator ti = ts.begin() - ; ti != ts.end() - ; ++ti ) - { - double t = *ti; - if ( t <= 0. || t >= 1. ) continue; //skip endpoint roots - if ( c.valueAt(t, X) > p[X] ) { // root is ray intersection - // Get t of next: - std::vector::iterator next = ti; - next++; - double nt; - if(next == ts.end()) nt = t + fudge; else nt = *next; - - // Check before in time and after in time for positions - // Currently we're using the average times between next and previous segs - Cmp after_to_ray = cmp(c.valueAt((t + nt) / 2, Y), p[Y]); - Cmp before_to_ray = cmp(c.valueAt((t + pt) / 2, Y), p[Y]); - // if y is included, these will have opposite values, giving order. - Cmp dt = cmp(after_to_ray, before_to_ray); - if(dt != EQUAL_TO) //Should always be true, but yah never know.. - wind += dt; - pt = t; - } - } - - return wind; -} - - -} // end 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:fileencoding=utf-8:textwidth=99 : diff --git a/src/2geom/curve.cpp b/src/2geom/curve.cpp new file mode 100644 index 000000000..49e011a8b --- /dev/null +++ b/src/2geom/curve.cpp @@ -0,0 +1,125 @@ +/** + * \file + * \brief Abstract curve type - implementation of default methods + * + *//* + * Authors: + * MenTaLguY + * Marco Cecchetti + * Krzysztof Kosiński + * + * 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. + */ + +#include <2geom/curve.h> +#include <2geom/nearest-point.h> +#include <2geom/sbasis-geometric.h> +#include <2geom/ord.h> + +namespace Geom +{ + +int CurveHelpers::root_winding(Curve const &c, Point p) { + std::vector ts = c.roots(p[Y], Y); + + if(ts.empty()) return 0; + + double const fudge = 0.01; //fudge factor used on first and last + + std::sort(ts.begin(), ts.end()); + + // winding determined by crossings at roots + int wind=0; + // previous time + double pt = ts.front() - fudge; + for ( std::vector::iterator ti = ts.begin() + ; ti != ts.end() + ; ++ti ) + { + double t = *ti; + if ( t <= 0. || t >= 1. ) continue; //skip endpoint roots + if ( c.valueAt(t, X) > p[X] ) { // root is ray intersection + // Get t of next: + std::vector::iterator next = ti; + next++; + double nt; + if(next == ts.end()) nt = t + fudge; else nt = *next; + + // Check before in time and after in time for positions + // Currently we're using the average times between next and previous segs + Cmp after_to_ray = cmp(c.valueAt((t + nt) / 2, Y), p[Y]); + Cmp before_to_ray = cmp(c.valueAt((t + pt) / 2, Y), p[Y]); + // if y is included, these will have opposite values, giving order. + Cmp dt = cmp(after_to_ray, before_to_ray); + if(dt != EQUAL_TO) //Should always be true, but yah never know.. + wind += dt; + pt = t; + } + } + + return wind; +} + +Coord Curve::nearestPoint(Point const& p, Coord a, Coord b) const +{ + return nearest_point(p, toSBasis(), a, b); +} + +std::vector Curve::allNearestPoints(Point const& p, Coord from, Coord to) const +{ + return all_nearest_points(p, toSBasis(), from, to); +} + +Coord Curve::length(Coord tolerance) const +{ + return ::Geom::length(toSBasis(), tolerance); +} + +Point Curve::unitTangentAt(Coord t, unsigned n) const +{ + std::vector derivs = pointAndDerivatives(t, n); + for (unsigned deriv_n = 1; deriv_n < derivs.size(); deriv_n++) { + Coord length = derivs[deriv_n].length(); + if ( ! are_near(length, 0) ) { + // length of derivative is non-zero, so return unit vector + return derivs[deriv_n] / length; + } + } + return Point (0,0); +}; + +} // 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:fileencoding=utf-8:textwidth=99 : diff --git a/src/extension/dbus/dbus-init.cpp b/src/extension/dbus/dbus-init.cpp index 2ae606940..9c562d169 100644 --- a/src/extension/dbus/dbus-init.cpp +++ b/src/extension/dbus/dbus-init.cpp @@ -14,6 +14,8 @@ */ #include +// this is reguired so that giomm headers won't barf +#undef DBUS_MESSAGE_TYPE_INVALID #include "dbus-init.h" #include "application-interface.h" diff --git a/src/extension/dbus/document-interface.cpp b/src/extension/dbus/document-interface.cpp index 485e92aa6..0e5d8de50 100644 --- a/src/extension/dbus/document-interface.cpp +++ b/src/extension/dbus/document-interface.cpp @@ -18,41 +18,26 @@ #include "document-interface.h" #include -#include "verbs.h" -#include "helper/action.h" //sp_action_perform - -#include "inkscape.h" //inkscape_find_desktop_by_dkey, activate desktops - #include "desktop-handles.h" //sp_desktop_document() -#include "xml/repr.h" //sp_repr_document_new - -#include "sp-object.h" - -#include "document.h" // getReprDoc() - #include "desktop-style.h" //sp_desktop_get_style - -#include "selection.h" //selection struct +#include "display/canvas-text.h" //text +#include "display/sp-canvas.h" //text +#include "document.h" // getReprDoc() +#include "extension/output.h" //IO +#include "extension/system.h" //IO +#include "file.h" //IO +#include "helper/action.h" //sp_action_perform +#include "inkscape.h" //inkscape_find_desktop_by_dkey, activate desktops +#include "layer-fns.h" //LPOS_BELOW +#include "live_effects/parameter/text.h" //text +#include "print.h" //IO #include "selection-chemistry.h"// lots of selection functions - +#include "selection.h" //selection struct #include "sp-ellipse.h" - -#include "layer-fns.h" //LPOS_BELOW - +#include "sp-object.h" #include "style.h" //style_write - -#include "file.h" //IO - -#include "extension/system.h" //IO - -#include "extension/output.h" //IO - -#include "print.h" //IO - -#include "live_effects/parameter/text.h" //text -#include "display/canvas-text.h" //text - -#include "display/sp-canvas.h" //text +#include "verbs.h" +#include "xml/repr.h" //sp_repr_document_new //#include "2geom/svg-path-parser.h" //get_node_coordinates diff --git a/src/extension/dbus/document-interface.h b/src/extension/dbus/document-interface.h index ac9fd11c1..12e033918 100644 --- a/src/extension/dbus/document-interface.h +++ b/src/extension/dbus/document-interface.h @@ -22,6 +22,14 @@ #include #include #include + +// this is reguired so that giomm headers won't barf +#undef DBUS_MESSAGE_TYPE_INVALID +#undef DBUS_MESSAGE_TYPE_METHOD_CALL +#undef DBUS_MESSAGE_TYPE_METHOD_RETURN +#undef DBUS_MESSAGE_TYPE_ERROR +#undef DBUS_MESSAGE_TYPE_SIGNAL + #include "desktop.h" #define DBUS_DOCUMENT_INTERFACE_PATH "/org/inkscape/document" -- cgit v1.2.3 From 5b3ed01dbaa86945e071db4103f39c5fe4b2f691 Mon Sep 17 00:00:00 2001 From: Diederik van Lierop Date: Fri, 4 Feb 2011 06:48:16 +0100 Subject: Fix a snap bug in which the snapped to the help path instead of the real path (bzr r10032) --- src/object-snapper.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/object-snapper.cpp b/src/object-snapper.cpp index e123173a5..1e2f71c95 100644 --- a/src/object-snapper.cpp +++ b/src/object-snapper.cpp @@ -414,8 +414,13 @@ void Inkscape::ObjectSnapper::_collectPaths(Geom::Point /*p*/, very_complex_path = sp_nodes_in_path(SP_PATH(root_item)) > 500; } - if (!very_lenghty_prose && !very_complex_path) { - SPCurve *curve = curve_for_item(root_item); + if (!very_lenghty_prose && !very_complex_path && root_item) { + SPCurve *curve = NULL; + if (SP_IS_SHAPE(root_item)) { + curve = SP_SHAPE(root_item)->getCurve(); + } else if (SP_IS_TEXT(root_item) || SP_IS_FLOWTEXT(root_item)) { + curve = te_get_layout(root_item)->convertToCurves(); + } if (curve) { // We will get our own copy of the pathvector, which must be freed at some point -- cgit v1.2.3 From 603193a32cdf3f3ae12a227fce8eec4d0b86f981 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Fri, 4 Feb 2011 23:29:16 +0100 Subject: temporary work around 2geom matrix bug to make inkscape more usable (bzr r10033) --- src/seltrans.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/seltrans.cpp b/src/seltrans.cpp index 848c0836a..049899e7a 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -424,7 +424,7 @@ void Inkscape::SelTrans::transform(Geom::Affine const &rel_affine, Geom::Point c g_return_if_fail(_grabbed); g_return_if_fail(!_empty); - Geom::Affine const affine( Geom::Translate(-norm) * rel_affine * Geom::Translate(norm) ); + Geom::Affine const affine( (Geom::Affine)Geom::Translate(-norm) * rel_affine * (Geom::Affine)Geom::Translate(norm) ); if (_show == SHOW_CONTENT) { // update the content @@ -1310,7 +1310,7 @@ gboolean Inkscape::SelTrans::rotateRequest(Geom::Point &pt, guint state) _relative_affine = r2 * r1.inverse(); // Update the handle position - pt = _point * Geom::Translate(-_origin) * _relative_affine * Geom::Translate(_origin); + pt = _point * (Geom::Affine)Geom::Translate(-_origin) * _relative_affine * (Geom::Affine)Geom::Translate(_origin); // Update the status text double degrees = mod360symm(Geom::rad_to_deg(radians)); @@ -1591,7 +1591,7 @@ Geom::Scale Inkscape::calcScaleFactors(Geom::Point const &initial_point, Geom::P // Only for scaling/stretching Geom::Point Inkscape::SelTrans::_calcAbsAffineDefault(Geom::Scale const default_scale) { - Geom::Affine abs_affine = Geom::Translate(-_origin) * Geom::Affine(default_scale) * Geom::Translate(_origin); + Geom::Affine abs_affine = (Geom::Affine)Geom::Translate(-_origin) * Geom::Affine(default_scale) * (Geom::Affine)Geom::Translate(_origin); Geom::Point new_bbox_min = _approximate_bbox->min() * abs_affine; Geom::Point new_bbox_max = _approximate_bbox->max() * abs_affine; @@ -1615,7 +1615,7 @@ Geom::Point Inkscape::SelTrans::_calcAbsAffineDefault(Geom::Scale const default_ Geom::Point Inkscape::SelTrans::_calcAbsAffineGeom(Geom::Scale const geom_scale) { _relative_affine = Geom::Affine(geom_scale); - _absolute_affine = Geom::Translate(-_origin_for_specpoints) * _relative_affine * Geom::Translate(_origin_for_specpoints); + _absolute_affine = (Geom::Affine)Geom::Translate(-_origin_for_specpoints) * _relative_affine * (Geom::Affine)Geom::Translate(_origin_for_specpoints); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool const transform_stroke = prefs->getBool("/options/transform/stroke", true); -- cgit v1.2.3 From f6809cd36481d5e20de106c23e3db527b026b417 Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 5 Feb 2011 02:06:18 +0100 Subject: Properly fix seltrans brokenness in 2Geom and pull updated files into Inkscape (bzr r10034) --- src/2geom/affine.h | 15 +++++++-------- src/2geom/point.cpp | 14 ++++++++++---- src/2geom/point.h | 13 +++++++------ src/2geom/transforms.cpp | 4 ++-- src/2geom/transforms.h | 3 --- src/2geom/utils.h | 17 ++++++++++++++++- src/seltrans.cpp | 8 ++++---- 7 files changed, 46 insertions(+), 28 deletions(-) (limited to 'src') diff --git a/src/2geom/affine.h b/src/2geom/affine.h index 9a6352f8b..277d8b4ee 100644 --- a/src/2geom/affine.h +++ b/src/2geom/affine.h @@ -16,6 +16,7 @@ #include #include <2geom/forward.h> #include <2geom/point.h> +#include <2geom/utils.h> namespace Geom { @@ -57,15 +58,13 @@ namespace Geom { */ class Affine : boost::equality_comparable< Affine // generates operator!= from operator== - , boost::multipliable< Affine - , boost::multipliable< Affine, Translate - , boost::multipliable< Affine, Scale - , boost::multipliable< Affine, Rotate - , boost::multipliable< Affine, HShear - , boost::multipliable< Affine, VShear + , boost::multipliable1< Affine + , MultipliableNoncommutative< Affine, Translate + , MultipliableNoncommutative< Affine, Scale + , MultipliableNoncommutative< Affine, Rotate + , MultipliableNoncommutative< Affine, HShear + , MultipliableNoncommutative< Affine, VShear > > > > > > > - // boost::multipliable< A, B > generates operator*(A const &, B const &) - // and operator*(B const &, A const &) from A::operator*=(B const &) { Coord _c[6]; public: diff --git a/src/2geom/point.cpp b/src/2geom/point.cpp index 9df88df92..a9005ef61 100644 --- a/src/2geom/point.cpp +++ b/src/2geom/point.cpp @@ -146,8 +146,8 @@ Point unit_vector(Point const &a) } /** @brief Return the "absolute value" of the point's vector. * This is defined in terms of the default lexicographical ordering. If the point is "larger" - * that the origin (0, 0), its negation is returned. This corresponds to making the Y coordinate - * positive. You can check whether the points' vectors have the same direction (e.g. lie + * 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. * To check with some margin of error, use @@ -158,8 +158,14 @@ Point unit_vector(Point const &a) * @relates Point */ Point abs(Point const &b) { - Point ret = b; - ret[Y] = fabs(ret[Y]); + Point ret; + if (b[Y] < 0.0) { + ret = -b; + } else if (b[Y] == 0.0) { + ret = b[X] < 0.0 ? -b : b; + } else { + ret = b; + } return ret; } diff --git a/src/2geom/point.h b/src/2geom/point.h index 97f5142e3..3c6e12eff 100644 --- a/src/2geom/point.h +++ b/src/2geom/point.h @@ -44,6 +44,7 @@ #include <2geom/coord.h> #include <2geom/isnan.h> //temporary fix for isnan() #include <2geom/math-utils.h> +#include <2geom/utils.h> namespace Geom { @@ -51,12 +52,12 @@ class Point : boost::additive< Point , boost::totally_ordered< Point , boost::multiplicative< Point, Coord - , boost::multiplicative< Point, Affine - , boost::multiplicative< Point, Translate - , boost::multiplicative< Point, Rotate - , boost::multiplicative< Point, Scale - , boost::multiplicative< Point, HShear - , boost::multiplicative< Point, VShear + , MultipliableNoncommutative< Point, Affine + , MultipliableNoncommutative< Point, Translate + , MultipliableNoncommutative< Point, Rotate + , MultipliableNoncommutative< Point, Scale + , MultipliableNoncommutative< Point, HShear + , MultipliableNoncommutative< Point, VShear > > > > > > > > > // this uses chaining so it looks weird, but works { Coord _pt[2]; diff --git a/src/2geom/transforms.cpp b/src/2geom/transforms.cpp index 2658719c4..3a1866c13 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[X]; + _pt[X] += h.f * _pt[Y]; return *this; } Point &Point::operator*=(VShear const &v) { - _pt[Y] += v.f * _pt[Y]; + _pt[Y] += v.f * _pt[X]; return *this; } diff --git a/src/2geom/transforms.h b/src/2geom/transforms.h index b8db82f14..1c965eb9f 100644 --- a/src/2geom/transforms.h +++ b/src/2geom/transforms.h @@ -56,12 +56,9 @@ struct TransformConcept { m = t * m; p *= t; p = p * t; - p = t * p; t *= t; t = t * t; t = pow(t, 3); - p /= t; // multiplication by inverse - p = p / t; bool_ = (t == t); bool_ = (t != t); t = T::identity(); diff --git a/src/2geom/utils.h b/src/2geom/utils.h index 31468a204..ecd1b7283 100644 --- a/src/2geom/utils.h +++ b/src/2geom/utils.h @@ -33,7 +33,6 @@ * */ -#include <2geom/math-utils.h> #include namespace Geom { @@ -43,6 +42,22 @@ inline bool logical_xor (bool a, bool b) { return (a || b) && !(a && b); } void binomial_coefficients(std::vector& bc, size_t n); +struct EmptyClass {}; + +/** + * @brief Noncommutative multiplication helper. + * Generates operator*(T, U) from operator*=(T, U). Does not generate operator*(U, T) + * like boost::multipliable does. This makes it suitable for noncommutative cases, + * such as transforms. + */ +template +struct MultipliableNoncommutative : B +{ + friend T operator*(T const &lhs, U const &rhs) { + T nrv(lhs); nrv *= rhs; return nrv; + } +}; + } #endif diff --git a/src/seltrans.cpp b/src/seltrans.cpp index 049899e7a..848c0836a 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -424,7 +424,7 @@ void Inkscape::SelTrans::transform(Geom::Affine const &rel_affine, Geom::Point c g_return_if_fail(_grabbed); g_return_if_fail(!_empty); - Geom::Affine const affine( (Geom::Affine)Geom::Translate(-norm) * rel_affine * (Geom::Affine)Geom::Translate(norm) ); + Geom::Affine const affine( Geom::Translate(-norm) * rel_affine * Geom::Translate(norm) ); if (_show == SHOW_CONTENT) { // update the content @@ -1310,7 +1310,7 @@ gboolean Inkscape::SelTrans::rotateRequest(Geom::Point &pt, guint state) _relative_affine = r2 * r1.inverse(); // Update the handle position - pt = _point * (Geom::Affine)Geom::Translate(-_origin) * _relative_affine * (Geom::Affine)Geom::Translate(_origin); + pt = _point * Geom::Translate(-_origin) * _relative_affine * Geom::Translate(_origin); // Update the status text double degrees = mod360symm(Geom::rad_to_deg(radians)); @@ -1591,7 +1591,7 @@ Geom::Scale Inkscape::calcScaleFactors(Geom::Point const &initial_point, Geom::P // Only for scaling/stretching Geom::Point Inkscape::SelTrans::_calcAbsAffineDefault(Geom::Scale const default_scale) { - Geom::Affine abs_affine = (Geom::Affine)Geom::Translate(-_origin) * Geom::Affine(default_scale) * (Geom::Affine)Geom::Translate(_origin); + Geom::Affine abs_affine = Geom::Translate(-_origin) * Geom::Affine(default_scale) * Geom::Translate(_origin); Geom::Point new_bbox_min = _approximate_bbox->min() * abs_affine; Geom::Point new_bbox_max = _approximate_bbox->max() * abs_affine; @@ -1615,7 +1615,7 @@ Geom::Point Inkscape::SelTrans::_calcAbsAffineDefault(Geom::Scale const default_ Geom::Point Inkscape::SelTrans::_calcAbsAffineGeom(Geom::Scale const geom_scale) { _relative_affine = Geom::Affine(geom_scale); - _absolute_affine = (Geom::Affine)Geom::Translate(-_origin_for_specpoints) * _relative_affine * (Geom::Affine)Geom::Translate(_origin_for_specpoints); + _absolute_affine = Geom::Translate(-_origin_for_specpoints) * _relative_affine * Geom::Translate(_origin_for_specpoints); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool const transform_stroke = prefs->getBool("/options/transform/stroke", true); -- cgit v1.2.3 From fb749ad5edae38b062e00d1593ec0d306bac4ada Mon Sep 17 00:00:00 2001 From: Krzysztof Kosi??ski Date: Sat, 5 Feb 2011 03:04:47 +0100 Subject: Fix node tool brokenness resulting from a switch to runtime order in 2Geom's BezierCurve (bzr r10035) --- src/helper/geom-curves.h | 18 ++++++++---------- src/helper/geom.cpp | 22 +++++++++++++--------- src/ui/tool/path-manipulator.cpp | 13 +++++++------ 3 files changed, 28 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/helper/geom-curves.h b/src/helper/geom-curves.h index f927634d8..5b921e572 100644 --- a/src/helper/geom-curves.h +++ b/src/helper/geom-curves.h @@ -26,17 +26,15 @@ inline bool is_straight_curve(Geom::Curve const & c) { } // the curve can be a quad/cubic bezier, but could still be a perfect straight line // if the control points are exactly on the line connecting the initial and final points. - else if ( Geom::QuadraticBezier const *quad = dynamic_cast(&c) ) { - Geom::Line line( quad->initialPoint(), quad->finalPoint() ); - if ( are_near((*quad)[1], line) ) { - return true; - } - } - else if ( Geom::CubicBezier const *cubic = dynamic_cast(&c) ) { - Geom::Line line( cubic->initialPoint(), cubic->finalPoint() ); - if ( are_near((*cubic)[1], line) && are_near((*cubic)[2], line) ) { - return true; + Geom::BezierCurve const *curve = dynamic_cast(&c); + if (curve) { + Geom::Line line(curve->initialPoint(), curve->finalPoint()); + std::vector pts = curve->points(); + for (unsigned i = 1; i < pts.size() - 1; ++i) { + if (!are_near(pts[i], line)) + return false; } + return true; } return false; diff --git a/src/helper/geom.cpp b/src/helper/geom.cpp index 4bf56f6c1..2420b43b4 100644 --- a/src/helper/geom.cpp +++ b/src/helper/geom.cpp @@ -476,15 +476,19 @@ pathv_to_linear_and_cubic_beziers( Geom::PathVector const &pathv ) output.back().close( pit->closed() ); for (Geom::Path::const_iterator cit = pit->begin(); cit != pit->end_open(); ++cit) { - if( dynamic_cast(&*cit) || - is_straight_curve(*cit) ) - { - output.back().append(*cit); - } - else { - // convert all other curve types to cubicbeziers - Geom::Path cubicbezier_path = Geom::cubicbezierpath_from_sbasis(cit->toSBasis(), 0.1); - output.back().append(cubicbezier_path); + if (is_straight_curve(*cit)) { + Geom::LineSegment l(cit->initialPoint(), cit->finalPoint()); + output.back().append(l); + } else { + Geom::BezierCurve const *curve = dynamic_cast(&*cit); + if (curve && curve->order() == 3) { + Geom::CubicBezier b((*curve)[0], (*curve)[1], (*curve)[2], (*curve)[3]); + output.back().append(b); + } else { + // convert all other curve types to cubicbeziers + Geom::Path cubicbezier_path = Geom::cubicbezierpath_from_sbasis(cit->toSBasis(), 0.1); + output.back().append(cubicbezier_path); + } } } } diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index 47e28a788..0e5705ee4 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -1039,13 +1039,14 @@ void PathManipulator::_createControlPointsFromGeometry() subpath->push_back(current_node); } // if this is a bezier segment, move handles appropriately - if (Geom::CubicBezier const *cubic_bezier = - dynamic_cast(&*cit)) + // TODO: I don't know why the dynamic cast below doesn't want to work + // when I replace BezierCurve with CubicBezier. Might be a bug + // somewhere in pathv_to_linear_and_cubic_beziers + Geom::BezierCurve const *bezier = dynamic_cast(&*cit); + if (bezier && bezier->order() == 3) { - std::vector points = cubic_bezier->points(); - - previous_node->front()->setPosition(points[1]); - current_node ->back() ->setPosition(points[2]); + previous_node->front()->setPosition((*bezier)[1]); + current_node ->back() ->setPosition((*bezier)[2]); } previous_node = current_node; } -- cgit v1.2.3 From 7e78bbdded33bc471e040aec15cd5135312f4637 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 7 Feb 2011 01:25:28 -0800 Subject: Fixed uninitialized member variables. (bzr r10037) --- src/ui/dialog/dialog.cpp | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/ui/dialog/dialog.cpp b/src/ui/dialog/dialog.cpp index 43863625f..88724a90c 100644 --- a/src/ui/dialog/dialog.cpp +++ b/src/ui/dialog/dialog.cpp @@ -93,15 +93,22 @@ void unhideCallback(GtkObject */*object*/, gpointer dlgPtr) Dialog::Dialog(Behavior::BehaviorFactory behavior_factory, const char *prefs_path, int verb_num, Glib::ustring const &apply_label) - : _hiddenF12 (false), - _prefs_path (prefs_path), + : _user_hidden(false), + _hiddenF12(false), + retransientize_suppress(false), + // + _prefs_path(prefs_path), _verb_num(verb_num), - _apply_label (apply_label) + _title(), + _apply_label(apply_label), + tooltips(), + _behavior(0) { gchar title[500]; - if (verb_num) + if (verb_num) { sp_ui_dialog_title_string (Inkscape::Verb::get(verb_num), title); + } _title = title; -- cgit v1.2.3 From 2dd7659790b8dcd3fbb77d80fd15450f5be08c32 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Wed, 9 Feb 2011 19:48:47 +0100 Subject: Extensions. New fix for Bug #668895 (Extensions with tags fail to load). (bzr r10038) --- src/extension/implementation/script.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'src') diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index 0f234c7d4..cc54194ec 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -189,7 +189,6 @@ Script::solve_reldir(Inkscape::XML::Node *reprin) { } Glib::ustring reldir = s; - for (unsigned int i=0; i < Inkscape::Extension::Extension::search_path.size(); i++) { @@ -200,7 +199,7 @@ Script::solve_reldir(Inkscape::XML::Node *reprin) { NULL); Glib::ustring filename = fname; g_free(fname); - + //printf("Filename: %s\n", filename.c_str()); if ( Inkscape::IO::file_test(filename.c_str(), G_FILE_TEST_EXISTS) ) { return Glib::filename_from_utf8(filename); } @@ -242,13 +241,11 @@ bool Script::check_existence(const std::string &command) return false; } } - - // First search in the extension path and the current directory - std::string path = INKSCAPE_EXTENSIONDIR; - path.append(";"); - path.append(G_SEARCHPATH_SEPARATOR_S); + + // First search in the current directory + std::string path = G_SEARCHPATH_SEPARATOR_S; path.append(";"); - // And then the PATH environment variable. + // And then in the PATH environment variable. path.append(Glib::getenv("PATH")); std::string::size_type pos = 0; @@ -379,8 +376,11 @@ Script::check(Inkscape::Extension::Extension *module) if (!command_text.empty()) { /* I've got the command */ bool existance = check_existence(command_text); - if (!existance) + if (!existance) { return false; + } + } else { + return false; } } -- cgit v1.2.3 From 19041cd22208d6740982d96d977029457155fe40 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Thu, 10 Feb 2011 22:50:09 +0100 Subject: add missing 2geom files. although they are not included in makefile builds, they are 'used' by other 2geom files that are included. so just to be safe i'll include them, to not cause build problems later (bzr r10043) --- src/2geom/conic_section_clipper.h | 59 ++++ src/2geom/conic_section_clipper_cr.h | 65 ++++ src/2geom/conic_section_clipper_impl.cpp | 590 +++++++++++++++++++++++++++++++ src/2geom/conic_section_clipper_impl.h | 356 +++++++++++++++++++ 4 files changed, 1070 insertions(+) create mode 100644 src/2geom/conic_section_clipper.h create mode 100644 src/2geom/conic_section_clipper_cr.h create mode 100644 src/2geom/conic_section_clipper_impl.cpp create mode 100644 src/2geom/conic_section_clipper_impl.h (limited to 'src') diff --git a/src/2geom/conic_section_clipper.h b/src/2geom/conic_section_clipper.h new file mode 100644 index 000000000..a02cda4d3 --- /dev/null +++ b/src/2geom/conic_section_clipper.h @@ -0,0 +1,59 @@ +/** + * \file + * \brief Conic section clipping with respect to a rectangle + * + * Authors: + * Marco Cecchetti + * + * Copyright 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 _2GEOM_CONIC_SECTION_CLIPPER_H_ +#define _2GEOM_CONIC_SECTION_CLIPPER_H_ + + +#undef CLIP_WITH_CAIRO_SUPPORT +#include <2geom/conic_section_clipper_impl.h> + + +#endif // _2GEOM_CONIC_SECTION_CLIPPER_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/conic_section_clipper_cr.h b/src/2geom/conic_section_clipper_cr.h new file mode 100644 index 000000000..31f5a4269 --- /dev/null +++ b/src/2geom/conic_section_clipper_cr.h @@ -0,0 +1,65 @@ +/** + * \file + * \brief Conic section clipping with respect to a rectangle + * + * Authors: + * Marco Cecchetti + * + * Copyright 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. + */ + + + + +//////////////////////////////////////////////////////////////////////////////// +// This header should be used for graphical debugging purpuse only. // +//////////////////////////////////////////////////////////////////////////////// + + +#ifndef _2GEOM_CONIC_SECTION_CLIPPER_CR_H_ +#define _2GEOM_CONIC_SECTION_CLIPPER_CR_H_ + + +#define CLIP_WITH_CAIRO_SUPPORT +#include "conic_section_clipper_impl.h" +#include "conic_section_clipper_impl.cpp" + + +#endif // _2GEOM_CONIC_SECTION_CLIPPER_CR_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/conic_section_clipper_impl.cpp b/src/2geom/conic_section_clipper_impl.cpp new file mode 100644 index 000000000..edfafb11c --- /dev/null +++ b/src/2geom/conic_section_clipper_impl.cpp @@ -0,0 +1,590 @@ +/** + * \file + * \brief Conic section clipping with respect to a rectangle + * + * Authors: + * Marco Cecchetti + * + * Copyright 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 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. + * The method returns true if the conic section intersects at least one + * of the four lines passing through rectangle edges, else it returns false. + */ +bool CLIPPER_CLASS::intersect (std::vector & crossing_points) const +{ + crossing_points.clear(); + + std::vector rts; + std::vector cpts; + // rectangle corners + enum {TOP_LEFT, TOP_RIGHT, BOTTOM_RIGHT, BOTTOM_LEFT}; + + bool no_crossing = true; + + // rigth edge + cs.roots (rts, R.right(), X); + if (rts.size() != 0) + { + no_crossing = false; + DBGPRINT ("CLIP: right: rts[0] = ", rts[0]) + DBGPRINTIF ((rts.size() == 2), "CLIP: right: rts[1] = ", rts[1]) + + Point corner1 = R.corner(TOP_RIGHT); + Point corner2 = R.corner(BOTTOM_RIGHT); + + for (size_t i = 0; i < rts.size(); ++i) + { + if (rts[i] < R.top() || rts[i] > R.bottom()) continue; + Point P (R.right(), rts[i]); + if (are_near (P, corner1)) + P = corner1; + else if (are_near (P, corner2)) + P = corner2; + + cpts.push_back (P); + } + if (cpts.size() == 2 && are_near (cpts[0], cpts[1])) + { + cpts[0] = middle_point (cpts[0], cpts[1]); + cpts.pop_back(); + } + } + + // top edge + cs.roots (rts, R.top(), Y); + if (rts.size() != 0) + { + no_crossing = false; + DBGPRINT ("CLIP: top: rts[0] = ", rts[0]) + DBGPRINTIF ((rts.size() == 2), "CLIP: top: rts[1] = ", rts[1]) + + Point corner1 = R.corner(TOP_RIGHT); + Point corner2 = R.corner(TOP_LEFT); + + for (size_t i = 0; i < rts.size(); ++i) + { + if (rts[i] < R.left() || rts[i] > R.right()) continue; + Point P (rts[i], R.top()); + if (are_near (P, corner1)) + P = corner1; + else if (are_near (P, corner2)) + P = corner2; + + cpts.push_back (P); + } + if (cpts.size() == 2 && are_near (cpts[0], cpts[1])) + { + cpts[0] = middle_point (cpts[0], cpts[1]); + cpts.pop_back(); + } + } + + // left edge + cs.roots (rts, R.left(), X); + if (rts.size() != 0) + { + no_crossing = false; + DBGPRINT ("CLIP: left: rts[0] = ", rts[0]) + DBGPRINTIF ((rts.size() == 2), "CLIP: left: rts[1] = ", rts[1]) + + Point corner1 = R.corner(TOP_LEFT); + Point corner2 = R.corner(BOTTOM_LEFT); + + for (size_t i = 0; i < rts.size(); ++i) + { + if (rts[i] < R.top() || rts[i] > R.bottom()) continue; + Point P (R.left(), rts[i]); + if (are_near (P, corner1)) + P = corner1; + else if (are_near (P, corner2)) + P = corner2; + + cpts.push_back (P); + } + if (cpts.size() == 2 && are_near (cpts[0], cpts[1])) + { + cpts[0] = middle_point (cpts[0], cpts[1]); + cpts.pop_back(); + } + } + + // bottom edge + cs.roots (rts, R.bottom(), Y); + if (rts.size() != 0) + { + no_crossing = false; + DBGPRINT ("CLIP: bottom: rts[0] = ", rts[0]) + DBGPRINTIF ((rts.size() == 2), "CLIP: bottom: rts[1] = ", rts[1]) + + Point corner1 = R.corner(BOTTOM_RIGHT); + Point corner2 = R.corner(BOTTOM_LEFT); + + for (size_t i = 0; i < rts.size(); ++i) + { + if (rts[i] < R.left() || rts[i] > R.right()) continue; + Point P (rts[i], R.bottom()); + if (are_near (P, corner1)) + P = corner1; + else if (are_near (P, corner2)) + P = corner2; + + cpts.push_back (P); + } + if (cpts.size() == 2 && are_near (cpts[0], cpts[1])) + { + cpts[0] = middle_point (cpts[0], cpts[1]); + cpts.pop_back(); + } + } + + DBGPRINT ("CLIP: intersect: crossing_points.size (with duplicates) = ", + cpts.size()) + + // remove duplicates + std::sort (cpts.begin(), cpts.end(), lex_lesser()); + cpts.erase (std::unique (cpts.begin(), cpts.end()), cpts.end()); + + + // Order crossing points on the rectangle edge clockwise, so two consecutive + // crossing points would be the end points of a conic arc all inside or all + // outside the rectangle. + std::map cp_angles; + for (size_t i = 0; i < cpts.size(); ++i) + { + cp_angles.insert (std::make_pair (cs.angle_at (cpts[i]), i)); + } + + std::map::const_iterator pos; + for (pos = cp_angles.begin(); pos != cp_angles.end(); ++pos) + { + crossing_points.push_back (cpts[pos->second]); + } + + DBGPRINT ("CLIP: intersect: crossing_points.size = ", crossing_points.size()) + DBGPRINTCOLL ("CLIP: intersect: crossing_points:", crossing_points) + + return no_crossing; +} // end function intersect + + + +inline +double signed_triangle_area (Point const& p1, Point const& p2, Point const& p3) +{ + return (cross(p3, p2) - cross(p3, p1) + cross(p2, p1)); +} + + +/* + * Test if two crossing points are the end points of a conic arc inner to the + * rectangle. In such a case the method returns true, else it returns false. + * Moreover by the parameter "M" it returns a point inner to the conic arc + * with the given end-points. + * + */ +bool CLIPPER_CLASS::are_paired (Point& M, const Point & P1, const Point & P2) const +{ + /* + * we looks for the points on the conic whose tangent is parallel to the + * arc chord P1P2, they will be extrema of the conic arc P1P2 wrt the + * direction orthogonal to the chord + */ + Point dir = P2 - P1; + DBGPRINT ("CLIP: are_paired: first point: ", P1) + DBGPRINT ("CLIP: are_paired: second point: ", P2) + + double grad0 = 2 * cs.coeff(0) * dir[0] + cs.coeff(1) * dir[1]; + double grad1 = cs.coeff(1) * dir[0] + 2 * cs.coeff(2) * dir[1]; + double grad2 = cs.coeff(3) * dir[0] + cs.coeff(4) * dir[1]; + + + /* + * such points are found intersecating the conic section with the line + * orthogonal to "grad": the derivative wrt the "dir" direction + */ + Line gl (grad0, grad1, grad2); + std::vector rts; + rts = cs.roots (gl); + DBGPRINT ("CLIP: are_paired: extrema: rts.size() = ", rts.size()) + + + + std::vector extrema; + for (size_t i = 0; i < rts.size(); ++i) + { + extrema.push_back (gl.pointAt (rts[i])); + } + + if (extrema.size() == 2) + { + // in case we are dealing with an hyperbola we could have two extrema + // on the same side wrt the line passing through P1 and P2, but + // only the nearer extremum is on the arc P1P2 + double side0 = signed_triangle_area (P1, extrema[0], P2); + double side1 = signed_triangle_area (P1, extrema[1], P2); + + if (sgn(side0) == sgn(side1)) + { + if (std::fabs(side0) > std::fabs(side1)) + { + std::swap (extrema[0], extrema[1]); + } + extrema.pop_back(); + } + } + + std::vector inner_points; + for (size_t i = 0; i < extrema.size(); ++i) + { + if (!R.contains (extrema[i])) continue; + // in case we are dealing with an ellipse tangent to two orthogonal + // rectangle edges we could have two extrema on opposite sides wrt the + // line passing through P1P2 and both inner the rectangle; anyway, since + // we order the crossing points clockwise we have only one extremum + // that follows such an ordering wrt P1 and P2; + // remark: the other arc will be selected when we test for the arc P2P1. + double P1angle = cs.angle_at (P1); + double P2angle = cs.angle_at (P2); + double Qangle = cs.angle_at (extrema[i]); + if (P1angle < P2angle && !(P1angle <= Qangle && Qangle <= P2angle)) + continue; + if (P1angle > P2angle && !(P1angle <= Qangle || Qangle <= P2angle)) + continue; + + inner_points.push_back (extrema[i]); + } + + if (inner_points.size() > 1) + { + THROW_LOGICALERROR ("conic section clipper: " + "more than one extremum found"); + } + else if (inner_points.size() == 1) + { + M = inner_points.front(); + return true; + } + + return false; +} + + +/* + * Pair the points contained in the "crossing_points" vector; the paired points + * are put in the paired_points vector so that given a point with an even index + * and the next one they are the end points of a conic arc that is inner to the + * rectangle. In the "inner_points" are returned points that are inner to the + * arc, where the inner point with index k is related to the arc with end + * points with indexes 2k, 2k+1. In case there are unpaired points the are put + * in to the "single_points" vector. + */ +void CLIPPER_CLASS::pairing (std::vector & paired_points, + std::vector & inner_points, + const std::vector & crossing_points) +{ + paired_points.clear(); + paired_points.reserve (crossing_points.size()); + + inner_points.clear(); + inner_points.reserve (crossing_points.size() / 2); + + single_points.clear(); + + // to keep trace of which crossing points have been paired + std::vector paired (crossing_points.size(), false); + + Point M; + + // by the way we have ordered crossing points we need to test one point wrt + // the next point only, for pairing; moreover the last point need to be + // tested wrt the first point; pay attention: one point can be paired both + // with the previous and the next one: this is not an error, think of + // crossing points that are tangent to the rectangle edge (and inner); + for (size_t i = 0; i < crossing_points.size(); ++i) + { + // we need to test the last point wrt the first one + size_t j = (i == 0) ? (crossing_points.size() - 1) : (i-1); + if (are_paired (M, crossing_points[j], crossing_points[i])) + { +#ifdef CLIP_WITH_CAIRO_SUPPORT + cairo_set_source_rgba(cr, 0.1, 0.1, 0.8, 1.0); + draw_line_seg (cr, crossing_points[j], crossing_points[i]); + draw_handle (cr, crossing_points[j]); + draw_handle (cr, crossing_points[i]); + draw_handle (cr, M); + cairo_stroke (cr); +#endif + paired[j] = paired[i] = true; + paired_points.push_back (crossing_points[j]); + paired_points.push_back (crossing_points[i]); + inner_points.push_back (M); + } + } + + // some point are not paired with any point, e.g. a crossing point tangent + // to a rectangle edge but with the conic arc outside the rectangle + for (size_t i = 0; i < paired.size(); ++i) + { + if (!paired[i]) + single_points.push_back (crossing_points[i]); + } + DBGPRINTCOLL ("single_points", single_points) + +} + + +/* + * This method clip the section conic wrt the rectangle and returns the inner + * conic arcs as a vector of RatQuad objects by the "arcs" parameter. + */ +bool CLIPPER_CLASS::clip (std::vector & arcs) +{ + arcs.clear(); + std::vector crossing_points; + std::vector paired_points; + std::vector inner_points; + + Line l1, l2; + if (cs.decompose (l1, l2)) + { + bool inner_empty = true; + + DBGINFO ("CLIP: degenerate section conic") + + boost::optional ls1 = Geom::clip (l1, R); + if (ls1) + { + if (ls1->isDegenerate()) + { + single_points.push_back (ls1->initialPoint()); + } + else + { + Point M = middle_point (*ls1); + arcs.push_back + (RatQuad (ls1->initialPoint(), M, ls1->finalPoint(), 1)); + inner_empty = false; + } + } + + boost::optional ls2 = Geom::clip (l2, R); + if (ls2) + { + if (ls2->isDegenerate()) + { + single_points.push_back (ls2->initialPoint()); + } + else + { + Point M = middle_point (*ls2); + arcs.push_back + (RatQuad (ls2->initialPoint(), M, ls2->finalPoint(), 1)); + inner_empty = false; + } + } + + return !inner_empty; + } + + + bool no_crossing = intersect (crossing_points); + + // if the only crossing point is a rectangle corner than the section conic + // is all outside the rectangle + if (crossing_points.size() == 1) + { + for (size_t i = 0; i < 4; ++i) + { + if (crossing_points[0] == R.corner(i)) + { + single_points.push_back (R.corner(i)); + return false; + } + } + } + + // if the conic does not cross any line passing through a rectangle edge or + // it is tangent to only one edge then it is an ellipse + if (no_crossing + || (crossing_points.size() == 1 && single_points.size() == 0)) + { + // if the ellipse centre is inside the rectangle + // then so it is the ellipse + boost::optional c = cs.centre(); + if (c && R.contains (*c)) + { + DBGPRINT ("CLIP: ellipse with centre", *c) + // we set paired and inner points by finding the ellipse + // intersection with its axes; this choice let us having a more + // accurate RatQuad parametric arc + paired_points.resize(4); + std::vector rts; + double angle = cs.axis_angle(); + Line axis1 (*c, angle); + rts = cs.roots (axis1); + if (rts[0] > rts[1]) std::swap (rts[0], rts[1]); + paired_points[0] = axis1.pointAt (rts[0]); + paired_points[1] = axis1.pointAt (rts[1]); + paired_points[2] = paired_points[1]; + paired_points[3] = paired_points[0]; + Line axis2 (*c, angle + M_PI/2); + rts = cs.roots (axis2); + if (rts[0] > rts[1]) std::swap (rts[0], rts[1]); + inner_points.push_back (axis2.pointAt (rts[0])); + inner_points.push_back (axis2.pointAt (rts[1])); + } + else if (crossing_points.size() == 1) + { + // so we have a tangent crossing point but the ellipse is outside + // the rectangle + single_points.push_back (crossing_points[0]); + } + } + else + { + // in case the conic section intersects any of the four lines passing + // through the rectangle edges but it does not cross any rectangle edge + // then the conic is all outer of the rectangle + if (crossing_points.size() == 0) return false; + // else we need to pair crossing points, and to find an arc inner point + // in order to generate a RatQuad object + pairing (paired_points, inner_points, crossing_points); + } + + + // we split arcs until the end-point distance is less than a given value, + // in this way the RatQuad parametrization is enough accurate + std::list points; + std::list::iterator sp, ip, fp; + for (size_t i = 0, j = 0; i < paired_points.size(); i += 2, ++j) + { + //DBGPRINT ("CLIP: clip: P = ", paired_points[i]) + //DBGPRINT ("CLIP: clip: M = ", inner_points[j]) + //DBGPRINT ("CLIP: clip: Q = ", paired_points[i+1]) + + // in case inner point and end points are near is better not split + // the conic arc further or we could get a degenerate RatQuad object + if (are_near (paired_points[i], inner_points[j], 1e-4) + && are_near (paired_points[i+1], inner_points[j], 1e-4)) + { + arcs.push_back (cs.toRatQuad (paired_points[i], + inner_points[j], + paired_points[i+1])); + continue; + } + + // populate the list + points.push_back(paired_points[i]); + points.push_back(inner_points[j]); + points.push_back(paired_points[i+1]); + + // an initial unconditioned splitting + sp = points.begin(); + ip = sp; ++ip; + fp = ip; ++fp; + rsplit (points, sp, ip, size_t(1u)); + rsplit (points, ip, fp, size_t(1u)); + + // length conditioned split + sp = points.begin(); + fp = sp; ++fp; + while (fp != points.end()) + { + rsplit (points, sp, fp, 100.0); + sp = fp; + ++fp; + } + + sp = points.begin(); + ip = sp; ++ip; + fp = ip; ++fp; + //DBGPRINT ("CLIP: points ", j) + //DBGPRINT ("CLIP: points.size = ", points.size()) + while (ip != points.end()) + { +#ifdef CLIP_WITH_CAIRO_SUPPORT + cairo_set_source_rgba(cr, 0.1, 0.1, 0.8, 1.0); + draw_handle (cr, *sp); + draw_handle (cr, *ip); + cairo_stroke (cr); +#endif + //std::cerr << "CLIP: arc: [" << *sp << ", " << *ip << ", " + // << *fp << "]" << std::endl; + arcs.push_back (cs.toRatQuad (*sp, *ip, *fp)); + sp = fp; + ip = sp; ++ip; + fp = ip; ++fp; + } + points.clear(); + } + DBGPRINT ("CLIP: arcs.size() = ", arcs.size()) + return (arcs.size() != 0); +} // end method clip + + +} // end 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:fileencoding=utf-8:textwidth=99 : diff --git a/src/2geom/conic_section_clipper_impl.h b/src/2geom/conic_section_clipper_impl.h new file mode 100644 index 000000000..7db4fca9f --- /dev/null +++ b/src/2geom/conic_section_clipper_impl.h @@ -0,0 +1,356 @@ +/** + * \file + * \brief Conic section clipping with respect to a rectangle + * + * Authors: + * Marco Cecchetti + * + * Copyright 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 _2GEOM_CONIC_SECTION_CLIPPER_IMPL_H_ +#define _2GEOM_CONIC_SECTION_CLIPPER_IMPL_H_ + + +#include <2geom/conicsec.h> +#include <2geom/line.h> + +#include +#include + + + +#ifdef CLIP_WITH_CAIRO_SUPPORT + #include <2geom/toys/path-cairo.h> + #define CLIPPER_CLASS clipper_cr +#else + #define CLIPPER_CLASS clipper +#endif + +//#define CLIPDBG + +#ifdef CLIPDBG +#include <2geom/toys/path-cairo.h> +#define DBGINFO(msg) \ + std::cerr << msg << std::endl; +#define DBGPRINT(msg, var) \ + std::cerr << msg << var << std::endl; +#define DBGPRINTIF(cond, msg, var) \ + if (cond) \ + std::cerr << msg << var << std::endl; + +#define DBGPRINT2(msg1, var1, msg2, var2) \ + std::cerr << msg1 << var1 << msg2 << var2 << std::endl; + +#define DBGPRINTCOLL(msg, coll) \ + if (coll.size() != 0) \ + std::cerr << msg << ":\n"; \ + for (size_t i = 0; i < coll.size(); ++i) \ + { \ + std::cerr << i << ": " << coll[i] << "\n"; \ + } + +#else +#define DBGINFO(msg) +#define DBGPRINT(msg, var) +#define DBGPRINTIF(cond, msg, var) +#define DBGPRINT2(msg1, var1, msg2, var2) +#define DBGPRINTCOLL(msg, coll) +#endif + + + + +namespace Geom +{ + +class CLIPPER_CLASS +{ + + public: + +#ifdef CLIP_WITH_CAIRO_SUPPORT + clipper_cr (cairo_t* _cr, const xAx & _cs, const Rect & _R) + : cr(_cr), cs(_cs), R(_R) + { + DBGPRINT ("CLIP: right side: ", R.right()) + DBGPRINT ("CLIP: top side: ", R.top()) + DBGPRINT ("CLIP: left side: ", R.left()) + DBGPRINT ("CLIP: bottom side: ", R.bottom()) + } +#else + clipper (const xAx & _cs, const Rect & _R) + : cs(_cs), R(_R) + { + } +#endif + + bool clip (std::vector & arcs); + + bool found_any_isolated_point() const + { + return (single_points.size() != 0); + } + + const std::vector & isolated_points() const + { + return single_points; + } + + + private: + bool intersect (std::vector & crossing_points) const; + + bool are_paired (Point & M, const Point & P1, const Point & P2) const; + void pairing (std::vector & paired_points, + std::vector & inner_points, + const std::vector & crossing_points); + + Point find_inner_point_by_bisector_line (const Point & P, + const Point & Q) const; + Point find_inner_point (const Point & P, const Point & Q) const; + + std::list::iterator split (std::list & points, + std::list::iterator sp, + std::list::iterator fp) const; + void rsplit (std::list & points, + std::list::iterator sp, + std::list::iterator fp, + size_t k) const; + + void rsplit (std::list & points, + std::list::iterator sp, + std::list::iterator fp, + double length) const; + + private: +#ifdef CLIP_WITH_CAIRO_SUPPORT + cairo_t* cr; +#endif + const xAx & cs; + const Rect & R; + std::vector single_points; +}; + + + + +/* + * Given two point "P", "Q" on the conic section the method computes + * a third point inner to the arc with end-point "P", "Q". + * The new point is found by intersecting the conic with the bisector line + * of the PQ line segment. + */ +inline +Point CLIPPER_CLASS::find_inner_point_by_bisector_line (const Point & P, + const Point & Q) const +{ + DBGPRINT ("CLIP: find_inner_point_by_bisector_line: P = ", P) + DBGPRINT ("CLIP: find_inner_point_by_bisector_line: Q = ", Q) + Line bl = make_bisector_line (LineSegment (P, Q)); + std::vector rts = cs.roots (bl); + //DBGPRINT ("CLIP: find_inner_point: rts.size = ", rts.size()) + double t; + if (rts.size() == 0) + { + THROW_LOGICALERROR ("clipper::find_inner_point_by_bisector_line: " + "no conic-bisector line intersection point"); + } + if (rts.size() == 2) + { + // we suppose that the searched point is the nearest + // to the line segment PQ + t = (std::fabs(rts[0]) < std::fabs(rts[1])) ? rts[0] : rts[1]; + } + else + { + t = rts[0]; + } + return bl.pointAt (t); +} + + +/* + * Given two point "P", "Q" on the conic section the method computes + * a third point inner to the arc with end-point "P", "Q". + * The new point is found by intersecting the conic with the line + * passing through the middle point of the PQ line segment and + * the intersection point of the tangent lines at points P and Q. + */ +inline +Point CLIPPER_CLASS::find_inner_point (const Point & P, const Point & Q) const +{ + + Line l1 = cs.tangent (P); + Line l2 = cs.tangent (Q); + Line l; + // in case we fail to find a crossing point we fall back to the bisector + // method + try + { + OptCrossing oc = intersection(l1, l2); + if (!oc) + { + return find_inner_point_by_bisector_line (P, Q); + } + l.setPoints (l1.pointAt (oc->ta), middle_point (P, Q)); + } + catch (Geom::InfiniteSolutions e) + { + return find_inner_point_by_bisector_line (P, Q); + } + + std::vector rts = cs.roots (l); + double t; + if (rts.size() == 0) + { + return find_inner_point_by_bisector_line (P, Q); + } + // the line "l" origin is set to the tangent crossing point so in case + // we find two intersection points only the nearest belongs to the given arc + // pay attention: in case we are dealing with an hyperbola (remember that + // end points are on the same branch, because they are paired) the tangent + // crossing point belongs to the angle delimited by hyperbola asymptotes + // and containing the given hyperbola branch, so the previous statement is + // still true + if (rts.size() == 2) + { + t = (std::fabs(rts[0]) < std::fabs(rts[1])) ? rts[0] : rts[1]; + } + else + { + t = rts[0]; + } + return l.pointAt (t); +} + + +/* + * Given a list of points on the conic section, and given two consecutive + * points belonging to the list and passed by two list iterators, the method + * finds a new point that is inner to the conic arc which has the two passed + * points as initial and final point. This new point is inserted into the list + * between the two passed points and an iterator pointing to the new point + * is returned. + */ +inline +std::list::iterator CLIPPER_CLASS::split (std::list & points, + std::list::iterator sp, + std::list::iterator fp) const +{ + Point new_point = find_inner_point (*sp, *fp); + std::list::iterator ip = points.insert (fp, new_point); + //std::cerr << "CLIP: split: [" << *sp << ", " << *ip << ", " + // << *fp << "]" << std::endl; + return ip; +} + + +/* + * Given a list of points on the conic section, and given two consecutive + * points belonging to the list and passed by two list iterators, the method + * recursively finds new points that are inner to the conic arc which has + * the two passed points as initial and final point. The recursion stop after + * "k" recursive calls. These new points are inserted into the list between + * the two passed points, and in the order we cross them going from + * the initial to the final arc point. + */ +inline +void CLIPPER_CLASS::rsplit (std::list & points, + std::list::iterator sp, + std::list::iterator fp, + size_t k) const +{ + if (k == 0) + { + //DBGINFO("CLIP: split: no further split") + return; + } + + std::list::iterator ip = split (points, sp, fp); + --k; + rsplit (points, sp, ip, k); + rsplit (points, ip, fp, k); +} + + +/* + * Given a list of points on the conic section, and given two consecutive + * points belonging to the list and passed by two list iterators, the method + * recursively finds new points that are inner to the conic arc which has + * the two passed points as initial and final point. The recursion stop when + * the max distance between the new computed inner point and the two passed + * arc end-points is less then the value specified by the "length" parameter. + * These new points are inserted into the list between the two passed points, + * and in the order we cross them going from the initial to the final arc point. + */ +inline +void CLIPPER_CLASS::rsplit (std::list & points, + std::list::iterator sp, + std::list::iterator fp, + double length) const +{ + std::list::iterator ip = split (points, sp, fp); + double d1 = distance (*sp, *ip); + double d2 = distance (*ip, *fp); + double mdist = std::max (d1, d2); + + if (mdist < length) + { + //DBGINFO("CLIP: split: no further split") + return; + } + + // they have to be called both to keep the number of points in the list + // in the form 2k+1 where k are the sub-arcs the initial arc is splitted in. + rsplit (points, sp, ip, length); + rsplit (points, ip, fp, length); +} + + +} // end namespace Geom + + + + +#endif // _2GEOM_CONIC_SECTION_CLIPPER_IMPL_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 : -- cgit v1.2.3 From 4f6c04e5bf97a27bb980c74fd7217881b3e769da Mon Sep 17 00:00:00 2001 From: Alvin Penner Date: Thu, 10 Feb 2011 18:52:26 -0500 Subject: emf import. support for unicode text (bzr r10045) --- src/extension/internal/emf-win32-inout.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/extension/internal/emf-win32-inout.cpp b/src/extension/internal/emf-win32-inout.cpp index c817f6d46..76a1132ca 100644 --- a/src/extension/internal/emf-win32-inout.cpp +++ b/src/extension/internal/emf-win32-inout.cpp @@ -1793,15 +1793,15 @@ myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD const * (gchar *) g_utf16_to_utf8( (gunichar2 *) wide_text, pEmr->emrtext.nChars, NULL, NULL, NULL ); if (ansi_text) { - gchar *p = ansi_text; - while (*p) { - if (*p < 32 || *p >= 127) { - g_free(ansi_text); - ansi_text = g_strdup(""); - break; - } - p++; - } +// gchar *p = ansi_text; +// while (*p) { +// if (*p < 32 || *p >= 127) { +// g_free(ansi_text); +// ansi_text = g_strdup(""); +// break; +// } +// p++; +// } SVGOStringStream ts; @@ -2379,7 +2379,7 @@ EmfWin32::open( Inkscape::Extension::Input * /*mod*/, const gchar *uri ) // std::cout << "SVG Output: " << std::endl << *(d.outsvg) << std::endl; - SPDocument *doc = SPDocument::createNewDocFromMem(d.outsvg->c_str(), d.outsvg->length(), TRUE); + SPDocument *doc = SPDocument::createNewDocFromMem(d.outsvg->c_str(), strlen(d.outsvg->c_str()), TRUE); delete d.outsvg; delete d.path; -- cgit v1.2.3 From 940bebdae2081d4455e26f2edfd0d8e9adb76542 Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Sat, 12 Feb 2011 23:43:10 +0100 Subject: calligraphy tool does not need to know the type of the end curves to add the cap. (bzr r10049) --- src/dyna-draw-context.cpp | 24 ++++++------------------ 1 file changed, 6 insertions(+), 18 deletions(-) (limited to 'src') diff --git a/src/dyna-draw-context.cpp b/src/dyna-draw-context.cpp index 6f0898d43..2988aea49 100644 --- a/src/dyna-draw-context.cpp +++ b/src/dyna-draw-context.cpp @@ -1086,32 +1086,20 @@ accumulate_calligraphic(SPDynaDrawContext *dc) return false; // failure } - Geom::CubicBezier const * dc_cal1_firstseg = dynamic_cast( dc->cal1->first_segment() ); - Geom::CubicBezier const * rev_cal2_firstseg = dynamic_cast( rev_cal2->first_segment() ); - Geom::CubicBezier const * dc_cal1_lastseg = dynamic_cast( dc->cal1->last_segment() ); - Geom::CubicBezier const * rev_cal2_lastseg = dynamic_cast( rev_cal2->last_segment() ); - - if ( - !dc_cal1_firstseg || - !rev_cal2_firstseg || - !dc_cal1_lastseg || - !rev_cal2_lastseg - ) { - rev_cal2->unref(); - dc->cal1->reset(); - dc->cal2->reset(); - return false; // failure - } + Geom::Curve const * dc_cal1_firstseg = dc->cal1->first_segment(); + Geom::Curve const * rev_cal2_firstseg = rev_cal2->first_segment(); + Geom::Curve const * dc_cal1_lastseg = dc->cal1->last_segment(); + Geom::Curve const * rev_cal2_lastseg = rev_cal2->last_segment(); dc->accumulated->reset(); /* Is this required ?? */ dc->accumulated->append(dc->cal1, false); - add_cap(dc->accumulated, (*dc_cal1_lastseg)[3], (*rev_cal2_firstseg)[0], dc->cap_rounding); + add_cap(dc->accumulated, dc_cal1_lastseg->finalPoint(), rev_cal2_firstseg->initialPoint(), dc->cap_rounding); dc->accumulated->append(rev_cal2, true); - add_cap(dc->accumulated, (*rev_cal2_lastseg)[3], (*dc_cal1_firstseg)[0], dc->cap_rounding); + add_cap(dc->accumulated, rev_cal2_lastseg->finalPoint(), dc_cal1_firstseg->initialPoint(), dc->cap_rounding); dc->accumulated->closepath(); -- cgit v1.2.3 From c8ec8ac8c5a3665adf39b1a939404027395ace0e Mon Sep 17 00:00:00 2001 From: "Johan B. C. Engelen" Date: Sun, 13 Feb 2011 21:06:36 +0100 Subject: update to latest 2geom. fixes bezier curve casts. (bzr r10050) --- src/2geom/bezier-curve.cpp | 123 +++--------------- src/2geom/bezier-curve.h | 257 +++++++++++++++++++++----------------- src/2geom/forward.h | 5 +- src/2geom/numeric/fitting-model.h | 17 +-- src/ui/tool/path-manipulator.cpp | 2 +- 5 files changed, 170 insertions(+), 234 deletions(-) (limited to 'src') diff --git a/src/2geom/bezier-curve.cpp b/src/2geom/bezier-curve.cpp index 1a2e079bf..bde0e3ef1 100644 --- a/src/2geom/bezier-curve.cpp +++ b/src/2geom/bezier-curve.cpp @@ -41,7 +41,7 @@ namespace Geom /** * @class BezierCurve - * @brief Two-dimensional Bezier curve of arbitrary order. + * @brief Two-dimensional Bezier curve of arbitrary order. (this is an abstract class) * * 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. @@ -85,69 +85,25 @@ namespace Geom * 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. - * Note that if you create a generic BezierCurve, you cannot use a dynamic cast to those more - * specific types, and you might face a slight preformance penalty relative to the more specific - * classes. To obtain an instance of the correct optimized type, use the optimize() - * or duplicate() methods. The difference is that optimize() will not create a new object - * if it can't be optimized or is already an instance of one of the specific types, while - * duplicate() will always create a new object. + * 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. * + * @relates BezierCurveN * @ingroup Curves */ -/** @brief Create an optimized instance of the curve. - * If the curve was created as a generic Bezier curve but has an order between 1 and 3, - * this method will create a newly allocated curve that is a LineSegment, a QuadraticBezier, - * or a CubicBezier. For other cases it returns the pointer to the current curve, to avoid - * allocating extra memory. Be careful when you use this method, because whether you have - * to delete the returned object or not depends on its return value! If easier deletion - * semantics are required, you can use the duplicate() method instead, which returns - * optimized objects by default. - * @return Pointer to a curve that is an instance of LineSegment, QuadraticBezier - * or CubicBezier based on the order. If the object is already an instance - * of te more specific types or the order is above 3, a pointer to the original - * object is returned instead, and no memory is allocated. */ -BezierCurve *BezierCurve::optimize() const -{ - switch(order()) { - case 1: - if (!dynamic_cast(this)) - return new LineSegment((*this)[0], (*this)[1]); - break; - case 2: - if (!dynamic_cast(this)) - return new QuadraticBezier((*this)[0], (*this)[1], (*this)[2]); - break; - case 3: - if (!dynamic_cast(this)) - return new CubicBezier((*this)[0], (*this)[1], (*this)[2], (*this)[3]); - break; - } - return const_cast(this); -} -Curve *BezierCurve::duplicate() const -{ - switch(order()) { - case 1: - return new LineSegment((*this)[0], (*this)[1]); - case 2: - return new QuadraticBezier((*this)[0], (*this)[1], (*this)[2]); - case 3: - return new CubicBezier((*this)[0], (*this)[1], (*this)[2], (*this)[3]); - } - return new BezierCurve(*this); -} - -Curve *BezierCurve::derivative() const -{ - if (order() == 1) { - double dx = inner[X][1] - inner[X][0], dy = inner[Y][1] - inner[Y][0]; - return new LineSegment(Point(dx,dy),Point(dx,dy)); - } - return new BezierCurve(Geom::derivative(inner[X]), Geom::derivative(inner[Y])); -} + /** + * @class BezierCurveN + * @tparam degree unsigned value indicating the order of the bezier curve + * @brief Two-dimensional Bezier curve of specific order. + * + * @relates BezierCurve + * @ingroup Curves + */ + Coord BezierCurve::length(Coord tolerance) const { switch (order()) @@ -171,55 +127,6 @@ Coord BezierCurve::length(Coord tolerance) const } } -/** - * @class LineSegment - * @brief Linear segment, a special case of a Bezier curve. - * - * This class uses some optimizations for a linear segment (a Bezier curve of order 1). - * Note that if you created a BezierCurve, you will not be able to cast it to a LineSegment - * using a dynamic cast regardless of its order - use the optimize() method. - * - * @ingroup Curves */ -Coord LineSegment::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); -} - - -/** - * @class QuadraticBezier - * @brief Quadratic Bezier curve. - * Note that if you created a BezierCurve, you will not be able to cast it to a QuadraticBezier - * using a dynamic cast regardless of its order - use the optimize() method. - * @ingroup Curves */ - -Coord QuadraticBezier::length(Coord tolerance) const -{ - std::vector pts = points(); - return bezier_length(pts[0], pts[1], pts[2], tolerance); -} - -/** - * @class CubicBezier - * @brief Cubic Bezier curve. - * Note that if you created a BezierCurve, you will not be able to cast it to a CubicBezier - * using a dynamic cast regardless of its order - use the optimize() method. - * @ingroup Curves */ - -Coord CubicBezier::length(Coord tolerance) const -{ - std::vector pts = points(); - return bezier_length(pts[0], pts[1], pts[2], pts[3], tolerance); -} - static Coord bezier_length_internal(std::vector &v1, Coord tolerance) { /* The Bezier length algorithm used in 2Geom utilizes a simple fact: diff --git a/src/2geom/bezier-curve.h b/src/2geom/bezier-curve.h index 1014c79f0..40da6f366 100644 --- a/src/2geom/bezier-curve.h +++ b/src/2geom/bezier-curve.h @@ -49,57 +49,7 @@ protected: D2 inner; public: - /// @name Construct the curve - /// @{ - /** @brief Construct a Bezier curve of the specified order with all points zero. */ - explicit BezierCurve(unsigned order) - : inner(Bezier::Order(order), Bezier::Order(order)) - {} - /** @brief Construct from 2D Bezier polynomial. */ - explicit BezierCurve(D2 const &x) - : inner(x) - { - if (inner[X].order() != inner[Y].order()) - THROW_LOGICALERROR("Beziers used to construct a BezierCurve " - "are not of the same order"); - } - /** @brief Construct from two 1D Bezier polynomials of the same order. */ - BezierCurve(Bezier x, Bezier y) - : inner(x, y) - { - // throw an error if the orders do not match - if (x.order() != y.order()) - THROW_LOGICALERROR("Beziers used to construct a BezierCurve " - "are not of the same order"); - } - /** @brief Construct a linear segment from its endpoints. */ - BezierCurve(Point c0, Point c1) { - for(unsigned d = 0; d < 2; d++) - inner[d] = Bezier(c0[d], c1[d]); - } - /** @brief Construct a quadratic Bezier curve from its control points. */ - BezierCurve(Point c0, Point c1, Point c2) { - for(unsigned d = 0; d < 2; d++) - inner[d] = Bezier(c0[d], c1[d], c2[d]); - } - /** @brief Construct a cubic Bezier curve from its control points. */ - BezierCurve(Point c0, Point c1, Point c2, Point c3) { - for(unsigned d = 0; d < 2; d++) - inner[d] = Bezier(c0[d], c1[d], c2[d], c3[d]); - } - /** @brief Construct a Bezier curve from a vector of its control points. */ - BezierCurve(std::vector const &points) { - unsigned ord = points.size() - 1; - if (ord < 1) THROW_LOGICALERROR("Not enough points to construct a Bezier curve"); - for (unsigned d = 0; d < 2; ++d) { - inner[d] = Bezier(Bezier::Order(ord)); - for(unsigned i = 0; i <= ord; i++) - inner[d][i] = points[i][d]; - } - } - /// @} - - // methods new to BezierCurve go here + /// No constructors allowed! /// @name Access and modify control points /// @{ @@ -110,14 +60,14 @@ public: * @return Vector with order() + 1 control points. */ std::vector points() const { return bezier_points(inner); } /** @brief Modify a control point. - * @param ix The zero-based index of the point to modify + * @param ix The zero-based index of the point to modify. Note that the caller is responsible for checking that this value is <= order(). * @param v The new value of the point */ void setPoint(unsigned ix, Point v) { 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. */ + * @param ps Vector which must contain order() + 1 points. Note that the caller is responsible for checking the size of this vector. */ virtual void setPoints(std::vector const &ps) { // must be virtual, because HLineSegment will need to redefine it if (ps.size() != order() + 1) @@ -127,27 +77,13 @@ public: } } /** Access control points of the curve. - * @param ix Index of the control point + * @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]); } /// @} - /** @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 subdivide(Coord t) const { - std::pair sx = inner[X].subdivide(t), sy = inner[Y].subdivide(t); - return std::make_pair( - BezierCurve(sx.first, sy.first), - BezierCurve(sx.second, sy.second)); - } - BezierCurve *optimize() const; - // implementation of virtual methods goes here #ifndef DOXYGEN_SHOULD_SKIP_THIS - virtual Curve *duplicate() const; virtual Point initialPoint() const { return inner.at0(); } virtual Point finalPoint() const { return inner.at1(); } virtual bool isDegenerate() const { return inner.isConstant(); } @@ -170,20 +106,6 @@ public: virtual std::vector roots(Coord v, Dim2 d) const { return (inner[d] - v).roots(); } - Curve *portion(Coord f, Coord t) const { - return new BezierCurve(Geom::portion(inner, f, t)); - } - Curve *reverse() const { - return new BezierCurve(Geom::reverse(inner)); - } - virtual Curve *transformed(Affine const &m) const { - BezierCurve *ret = new BezierCurve(order()); - std::vector ps = points(); - for(unsigned i = 0; i <= order(); i++) ps[i] = ps[i] * m; - ret->setPoints(ps); - return ret; - } - virtual Curve *derivative() const; virtual Coord length(Coord tolerance) const; virtual Point pointAt(Coord t) const { return inner.valueAt(t); } virtual std::vector pointAndDerivatives(Coord t, unsigned n) const { return inner.valueAndDerivatives(t, n); } @@ -192,51 +114,154 @@ public: #endif }; -class LineSegment : public BezierCurve { +template +class BezierCurveN : public BezierCurve { + public: - LineSegment() : BezierCurve(1) {} - LineSegment(Point c0, Point c1) : BezierCurve(c0, c1) {} + template + static void assert_degree(BezierCurveN const *) {} -#ifndef DOXYGEN_SHOULD_SKIP_THIS - virtual Curve *duplicate() const { return new LineSegment(*this); } - virtual Rect boundsFast() const { return Rect(initialPoint(), finalPoint()); } - virtual Rect boundsExact() const { return boundsFast(); } - virtual Coord nearestPoint(Point const& p, Coord from = 0, Coord to = 1) const; + /// @name Construct the curve + /// @{ + /** @brief Construct a Bezier curve of the specified order with all points zero. */ + BezierCurveN() { + inner = D2 (Bezier::Order(degree), Bezier::Order(degree)); + } + + /** @brief Construct from 2D Bezier polynomial. */ + explicit BezierCurveN(D2 const &x) { + inner = x; + } + + /** @brief Construct from two 1D Bezier polynomials of the same order. */ + BezierCurveN(Bezier x, Bezier y) { + inner = D2 (x,y); + } + + /** @brief Construct a Bezier curve from a vector of its control points. */ + BezierCurveN(std::vector const &points) { + unsigned ord = points.size() - 1; + if (ord != degree) THROW_LOGICALERROR("BezierCurve does not match number of points"); + for (unsigned d = 0; d < 2; ++d) { + inner[d] = Bezier(Bezier::Order(ord)); + for(unsigned i = 0; i <= ord; i++) + inner[d][i] = points[i][d]; + } + } + + /** @brief Construct a linear segment from its endpoints. */ + BezierCurveN(Point c0, Point c1) { + assert_degree<1>(this); + for(unsigned d = 0; d < 2; d++) + inner[d] = Bezier(c0[d], c1[d]); + } + + /** @brief Construct a quadratic Bezier curve from its control points. */ + BezierCurveN(Point c0, Point c1, Point c2) { + assert_degree<2>(this); + for(unsigned d = 0; d < 2; d++) + inner[d] = Bezier(c0[d], c1[d], c2[d]); + } + + /** @brief Construct a cubic Bezier curve from its control points. */ + BezierCurveN(Point c0, Point c1, Point c2, Point c3) { + assert_degree<3>(this); + for(unsigned d = 0; d < 2; d++) + inner[d] = Bezier(c0[d], c1[d], c2[d], c3[d]); + } + + // default copy + // default assign + + /// @} + + + virtual Curve *duplicate() const { + return new BezierCurveN(*this); + } virtual Curve *portion(Coord f, Coord t) const { - return new LineSegment(pointAt(f), pointAt(t)); + if (degree == 1) { + return new BezierCurveN<1>(pointAt(f), pointAt(t)); + } else { + return new BezierCurveN(Geom::portion(inner, f, t)); + } + } + virtual Curve *reverse() const { + if (degree == 1) { + return new BezierCurveN<1>(finalPoint(), initialPoint()); + } else { + return new BezierCurveN(Geom::reverse(inner)); + } } - virtual Curve *reverse() const { return new LineSegment(finalPoint(), initialPoint()); } virtual Curve *transformed(Affine const &m) const { - return new LineSegment(initialPoint() * m, finalPoint() * m); + if (degree == 1) { + return new BezierCurveN<1>(initialPoint() * m, finalPoint() * m); + } else { + BezierCurveN *ret = new BezierCurveN(); + std::vector ps = points(); + for (unsigned i = 0; i <= degree; i++) { + ps[i] = ps[i] * m; + } + ret->setPoints(ps); + return ret; + } } - virtual Curve *derivative() const { - Coord dx = inner[X][1] - inner[X][0], dy = inner[Y][1] - inner[Y][0]; - return new LineSegment(Point(dx,dy),Point(dx,dy)); + 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 subdivide(Coord t) const { + std::pair sx = inner[X].subdivide(t), sy = inner[Y].subdivide(t); + return std::make_pair( + BezierCurveN(sx.first, sy.first), + BezierCurveN(sx.second, sy.second)); } - virtual Coord length(Coord) const { return distance(initialPoint(), finalPoint()); } -#endif -}; -class QuadraticBezier : public BezierCurve { -public: - QuadraticBezier(Point c0, Point c1, Point c2) : BezierCurve(c0, c1, c2) {} -#ifndef DOXYGEN_SHOULD_SKIP_THIS - virtual Coord length(Coord tolerance) const; -#endif -}; + double nearestPoint( Point const& p, double from = 0, double to = 1 ) const { + return Curve::nearestPoint(p, from, to); + } -/** @brief Cubic Bezier curve. - * Note that if you created a BezierCurve, you will not be able to cast it to a CubicBezier - * using a dynamic cast regardless of its order - use the optimize() method. - * @ingroup Curves */ -class CubicBezier : public BezierCurve { -public: - CubicBezier(Point c0, Point c1, Point c2, Point c3) : BezierCurve(c0, c1, c2, c3) {} -#ifndef DOXYGEN_SHOULD_SKIP_THIS - virtual Coord length(Coord tolerance) const; -#endif }; +// BezierCurveN<0> is meaningless; specialize it out +template<> class BezierCurveN<0> : public BezierCurveN<1> { public: BezierCurveN();}; + +// provide convenient names for common degree bezier curves +typedef BezierCurveN<1> LineSegment; +typedef BezierCurveN<2> QuadraticBezier; +typedef BezierCurveN<3> CubicBezier; + +template +inline +Curve *BezierCurveN::derivative() const { + return new BezierCurveN(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); +} + inline Point middle_point(LineSegment const& _segment) { return ( _segment.initialPoint() + _segment.finalPoint() ) / 2; } diff --git a/src/2geom/forward.h b/src/2geom/forward.h index 93a762022..399344dda 100644 --- a/src/2geom/forward.h +++ b/src/2geom/forward.h @@ -58,7 +58,10 @@ class SBasisCurve; class BezierCurve; class HLineSegment; class VLineSegment; -class LineSegment; +template class BezierCurveN; +typedef BezierCurveN<1> LineSegment; +typedef BezierCurveN<2> QuadraticBezier; +typedef BezierCurveN<3> CubicBezier; class EllipticalArc; class SVGEllipticalArc; diff --git a/src/2geom/numeric/fitting-model.h b/src/2geom/numeric/fitting-model.h index b1ecbe92c..a44c1ddac 100644 --- a/src/2geom/numeric/fitting-model.h +++ b/src/2geom/numeric/fitting-model.h @@ -470,12 +470,13 @@ class LFMBezier // this model generates Bezier curves -class LFMBezierCurve - : public LinearFittingModel< double, Point, BezierCurve > +template +class LFMBezierCurveN + : public LinearFittingModel< double, Point, BezierCurveN > { public: - LFMBezierCurve( size_t _order ) - : mob(_order) + LFMBezierCurveN() + : mob(degree+1) { } @@ -489,13 +490,13 @@ class LFMBezierCurve return mob.size(); } - void instance(BezierCurve & bc, ConstMatrixView const& raw_data) const + void instance(BezierCurveN & bc, ConstMatrixView const& raw_data) const { - Bezier bx(size()-1); - Bezier by(size()-1); + Bezier bx(degree); + Bezier by(degree); mob.instance(bx, raw_data.column_const_view(X)); mob.instance(by, raw_data.column_const_view(Y)); - bc = BezierCurve(bx, by); + bc = BezierCurveN(bx, by); } private: diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index 0e5705ee4..1e0dc85a4 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -894,7 +894,7 @@ NodeList::iterator PathManipulator::subdivideSegment(NodeList::iterator first, d // build bezier curve and subdivide Geom::CubicBezier temp(first->position(), first->front()->position(), second->back()->position(), second->position()); - std::pair div = temp.subdivide(t); + std::pair div = temp.subdivide(t); std::vector seg1 = div.first.points(), seg2 = div.second.points(); // set new handle positions -- cgit v1.2.3 From db451544150359dab56c14150a58f58ec76798b4 Mon Sep 17 00:00:00 2001 From: Adib Taraben Date: Tue, 15 Feb 2011 00:36:45 +0100 Subject: preview dialogue for pdf-import-cairo (bzr r10049.1.1) --- src/extension/implementation/script.cpp | 2 +- src/extension/internal/pdf-input-cairo.cpp | 573 ++++++++++++++++++++++++++++- src/extension/internal/pdf-input-cairo.h | 82 +++++ 3 files changed, 652 insertions(+), 5 deletions(-) (limited to 'src') diff --git a/src/extension/implementation/script.cpp b/src/extension/implementation/script.cpp index cc54194ec..2f3e2cd65 100644 --- a/src/extension/implementation/script.cpp +++ b/src/extension/implementation/script.cpp @@ -603,7 +603,7 @@ void Script::save(Inkscape::Extension::Output *module, file_listener fileout; int data_read = execute(command, params, tempfilename_in, fileout); - + bool success = false; if (data_read > 0) { diff --git a/src/extension/internal/pdf-input-cairo.cpp b/src/extension/internal/pdf-input-cairo.cpp index 6657ea222..048b26bed 100644 --- a/src/extension/internal/pdf-input-cairo.cpp +++ b/src/extension/internal/pdf-input-cairo.cpp @@ -16,12 +16,16 @@ #endif #ifdef HAVE_POPPLER_GLIB +#ifdef HAVE_POPPLER_CAIRO #include "pdf-input-cairo.h" #include "extension/system.h" #include "extension/input.h" +#include "dialogs/dialog-events.h" #include "document.h" +#include "inkscape.h" + #include #include #include @@ -31,21 +35,581 @@ namespace Inkscape { namespace Extension { namespace Internal { + +/** + * \brief The PDF import dialog + * FIXME: Probably this should be placed into src/ui/dialog + */ + +static const gchar * crop_setting_choices[] = { + //TRANSLATORS: The following are document crop settings for PDF import + // more info: http://www.acrobatusers.com/tech_corners/javascript_corner/tips/2006/page_bounds/ + N_("media box"), + N_("crop box"), + N_("trim box"), + N_("bleed box"), + N_("art box") +}; + +PdfImportCairoDialog::PdfImportCairoDialog(PopplerDocument *doc) +{ + if(doc == NULL) { + // if there is no document, throw exception here + throw; + } + + _poppler_doc = doc; + + cancelbutton = Gtk::manage(new class Gtk::Button(Gtk::StockID("gtk-cancel"))); + okbutton = Gtk::manage(new class Gtk::Button(Gtk::StockID("gtk-ok"))); + _labelSelect = Gtk::manage(new class Gtk::Label(_("Select page:"))); + + // Page number + int num_pages = poppler_document_get_n_pages(_poppler_doc); + Gtk::Adjustment *_pageNumberSpin_adj = Gtk::manage(new class Gtk::Adjustment(1, 1, num_pages, 1, 10, 0)); + _pageNumberSpin = Gtk::manage(new class Gtk::SpinButton(*_pageNumberSpin_adj, 1, 1)); + _labelTotalPages = Gtk::manage(new class Gtk::Label()); + hbox2 = Gtk::manage(new class Gtk::HBox(false, 0)); + // Disable the page selector when there's only one page + if ( num_pages == 1 ) { + _pageNumberSpin->set_sensitive(false); + } else { + // Display total number of pages + gchar *label_text = g_strdup_printf(_("out of %i"), num_pages); + _labelTotalPages->set_label(label_text); + g_free(label_text); + } + + // Crop settings + _cropCheck = Gtk::manage(new class Gtk::CheckButton(_("Clip to:"))); + _cropTypeCombo = Gtk::manage(new class Gtk::ComboBoxText()); + int num_crop_choices = sizeof(crop_setting_choices) / sizeof(crop_setting_choices[0]); + for ( int i = 0 ; i < num_crop_choices ; i++ ) { + _cropTypeCombo->append_text(_(crop_setting_choices[i])); + } + _cropTypeCombo->set_active_text(_(crop_setting_choices[0])); + _cropTypeCombo->set_sensitive(false); + + hbox3 = Gtk::manage(new class Gtk::HBox(false, 4)); + vbox2 = Gtk::manage(new class Gtk::VBox(false, 4)); + alignment3 = Gtk::manage(new class Gtk::Alignment(0.5, 0.5, 1, 1)); + _labelPageSettings = Gtk::manage(new class Gtk::Label(_("Page settings"))); + _pageSettingsFrame = Gtk::manage(new class Gtk::Frame()); + _labelPrecision = Gtk::manage(new class Gtk::Label(_("Precision of approximating gradient meshes:"))); + _labelPrecisionWarning = Gtk::manage(new class Gtk::Label(_("Note: setting the precision too high may result in a large SVG file and slow performance."))); + + _fallbackPrecisionSlider_adj = Gtk::manage(new class Gtk::Adjustment(2, 1, 256, 1, 10, 10)); + _fallbackPrecisionSlider = Gtk::manage(new class Gtk::HScale(*_fallbackPrecisionSlider_adj)); + _fallbackPrecisionSlider->set_value(2.0); + _labelPrecisionComment = Gtk::manage(new class Gtk::Label(_("rough"))); + hbox6 = Gtk::manage(new class Gtk::HBox(false, 4)); + + // Text options + _labelText = Gtk::manage(new class Gtk::Label(_("Text handling:"))); + _textHandlingCombo = Gtk::manage(new class Gtk::ComboBoxText()); + _textHandlingCombo->append_text(_("Import text as text")); + _textHandlingCombo->set_active_text(_("Import text as text")); + _localFontsCheck = Gtk::manage(new class Gtk::CheckButton(_("Replace PDF fonts by closest-named installed fonts"))); + + hbox5 = Gtk::manage(new class Gtk::HBox(false, 4)); + _embedImagesCheck = Gtk::manage(new class Gtk::CheckButton(_("Embed images"))); + vbox3 = Gtk::manage(new class Gtk::VBox(false, 4)); + alignment4 = Gtk::manage(new class Gtk::Alignment(0.5, 0.5, 1, 1)); + _labelImportSettings = Gtk::manage(new class Gtk::Label(_("Import settings"))); + _importSettingsFrame = Gtk::manage(new class Gtk::Frame()); + vbox1 = Gtk::manage(new class Gtk::VBox(false, 4)); + _previewArea = Gtk::manage(new class Gtk::DrawingArea()); + hbox1 = Gtk::manage(new class Gtk::HBox(false, 4)); + cancelbutton->set_flags(Gtk::CAN_FOCUS); + cancelbutton->set_flags(Gtk::CAN_DEFAULT); + cancelbutton->set_relief(Gtk::RELIEF_NORMAL); + okbutton->set_flags(Gtk::CAN_FOCUS); + okbutton->set_flags(Gtk::CAN_DEFAULT); + okbutton->set_relief(Gtk::RELIEF_NORMAL); + this->get_action_area()->property_layout_style().set_value(Gtk::BUTTONBOX_END); + _labelSelect->set_alignment(0.5,0.5); + _labelSelect->set_padding(4,0); + _labelSelect->set_justify(Gtk::JUSTIFY_LEFT); + _labelSelect->set_line_wrap(false); + _labelSelect->set_use_markup(false); + _labelSelect->set_selectable(false); + _pageNumberSpin->set_flags(Gtk::CAN_FOCUS); + _pageNumberSpin->set_update_policy(Gtk::UPDATE_ALWAYS); + _pageNumberSpin->set_numeric(true); + _pageNumberSpin->set_digits(0); + _pageNumberSpin->set_wrap(false); + _labelTotalPages->set_alignment(0.5,0.5); + _labelTotalPages->set_padding(4,0); + _labelTotalPages->set_justify(Gtk::JUSTIFY_LEFT); + _labelTotalPages->set_line_wrap(false); + _labelTotalPages->set_use_markup(false); + _labelTotalPages->set_selectable(false); + hbox2->pack_start(*_labelSelect, Gtk::PACK_SHRINK, 4); + hbox2->pack_start(*_pageNumberSpin, Gtk::PACK_SHRINK, 4); + hbox2->pack_start(*_labelTotalPages, Gtk::PACK_SHRINK, 4); + _cropCheck->set_flags(Gtk::CAN_FOCUS); + _cropCheck->set_relief(Gtk::RELIEF_NORMAL); + _cropCheck->set_mode(true); + _cropCheck->set_active(false); + _cropTypeCombo->set_border_width(1); + hbox3->pack_start(*_cropCheck, Gtk::PACK_SHRINK, 4); + hbox3->pack_start(*_cropTypeCombo, Gtk::PACK_SHRINK, 0); + vbox2->pack_start(*hbox2); + vbox2->pack_start(*hbox3); + alignment3->add(*vbox2); + _labelPageSettings->set_alignment(0.5,0.5); + _labelPageSettings->set_padding(4,0); + _labelPageSettings->set_justify(Gtk::JUSTIFY_LEFT); + _labelPageSettings->set_line_wrap(false); + _labelPageSettings->set_use_markup(true); + _labelPageSettings->set_selectable(false); + _pageSettingsFrame->set_border_width(4); + _pageSettingsFrame->set_shadow_type(Gtk::SHADOW_ETCHED_IN); + _pageSettingsFrame->set_label_align(0,0.5); + _pageSettingsFrame->add(*alignment3); + _pageSettingsFrame->set_label_widget(*_labelPageSettings); + _labelPrecision->set_alignment(0,0.5); + _labelPrecision->set_padding(4,0); + _labelPrecision->set_justify(Gtk::JUSTIFY_LEFT); + _labelPrecision->set_line_wrap(true); + _labelPrecision->set_use_markup(false); + _labelPrecision->set_selectable(false); + _labelPrecisionWarning->set_alignment(0,0.5); + _labelPrecisionWarning->set_padding(4,0); + _labelPrecisionWarning->set_justify(Gtk::JUSTIFY_LEFT); + _labelPrecisionWarning->set_line_wrap(true); + _labelPrecisionWarning->set_use_markup(true); + _labelPrecisionWarning->set_selectable(false); + _fallbackPrecisionSlider->set_size_request(180,-1); + _fallbackPrecisionSlider->set_flags(Gtk::CAN_FOCUS); + _fallbackPrecisionSlider->set_update_policy(Gtk::UPDATE_CONTINUOUS); + _fallbackPrecisionSlider->set_inverted(false); + _fallbackPrecisionSlider->set_digits(1); + _fallbackPrecisionSlider->set_draw_value(true); + _fallbackPrecisionSlider->set_value_pos(Gtk::POS_TOP); + _labelPrecisionComment->set_size_request(90,-1); + _labelPrecisionComment->set_alignment(0.5,0.5); + _labelPrecisionComment->set_padding(4,0); + _labelPrecisionComment->set_justify(Gtk::JUSTIFY_LEFT); + _labelPrecisionComment->set_line_wrap(false); + _labelPrecisionComment->set_use_markup(false); + _labelPrecisionComment->set_selectable(false); + hbox6->pack_start(*_fallbackPrecisionSlider, Gtk::PACK_SHRINK, 4); + hbox6->pack_start(*_labelPrecisionComment, Gtk::PACK_SHRINK, 0); + _labelText->set_alignment(0.5,0.5); + _labelText->set_padding(4,0); + _labelText->set_justify(Gtk::JUSTIFY_LEFT); + _labelText->set_line_wrap(false); + _labelText->set_use_markup(false); + _labelText->set_selectable(false); + hbox5->pack_start(*_labelText, Gtk::PACK_SHRINK, 0); + hbox5->pack_start(*_textHandlingCombo, Gtk::PACK_SHRINK, 0); + _localFontsCheck->set_flags(Gtk::CAN_FOCUS); + _localFontsCheck->set_relief(Gtk::RELIEF_NORMAL); + _localFontsCheck->set_mode(true); + _localFontsCheck->set_active(true); + _embedImagesCheck->set_flags(Gtk::CAN_FOCUS); + _embedImagesCheck->set_relief(Gtk::RELIEF_NORMAL); + _embedImagesCheck->set_mode(true); + _embedImagesCheck->set_active(true); + vbox3->pack_start(*_labelPrecision, Gtk::PACK_SHRINK, 0); + vbox3->pack_start(*hbox6, Gtk::PACK_SHRINK, 0); + vbox3->pack_start(*_labelPrecisionWarning, Gtk::PACK_SHRINK, 0); + vbox3->pack_start(*hbox5, Gtk::PACK_SHRINK, 4); + vbox3->pack_start(*_localFontsCheck, Gtk::PACK_SHRINK, 0); + vbox3->pack_start(*_embedImagesCheck, Gtk::PACK_SHRINK, 0); + alignment4->add(*vbox3); + _labelImportSettings->set_alignment(0.5,0.5); + _labelImportSettings->set_padding(4,0); + _labelImportSettings->set_justify(Gtk::JUSTIFY_LEFT); + _labelImportSettings->set_line_wrap(false); + _labelImportSettings->set_use_markup(true); + _labelImportSettings->set_selectable(false); + _importSettingsFrame->set_border_width(4); + _importSettingsFrame->set_shadow_type(Gtk::SHADOW_ETCHED_IN); + _importSettingsFrame->set_label_align(0,0.5); + _importSettingsFrame->add(*alignment4); + _importSettingsFrame->set_label_widget(*_labelImportSettings); + vbox1->pack_start(*_pageSettingsFrame, Gtk::PACK_EXPAND_PADDING, 0); + vbox1->pack_start(*_importSettingsFrame, Gtk::PACK_EXPAND_PADDING, 0); + hbox1->pack_start(*vbox1); + hbox1->pack_start(*_previewArea, Gtk::PACK_EXPAND_WIDGET, 4); + this->get_vbox()->set_homogeneous(false); + this->get_vbox()->set_spacing(0); + this->get_vbox()->pack_start(*hbox1); + this->set_title(_("PDF Import Settings")); + this->set_modal(true); + sp_transientize((GtkWidget *)this->gobj()); //Make transient + this->property_window_position().set_value(Gtk::WIN_POS_NONE); + this->set_resizable(true); + this->property_destroy_with_parent().set_value(false); + this->set_has_separator(true); + this->add_action_widget(*cancelbutton, -6); + this->add_action_widget(*okbutton, -5); + cancelbutton->show(); + okbutton->show(); + _labelSelect->show(); + _pageNumberSpin->show(); + _labelTotalPages->show(); + hbox2->show(); + _cropCheck->show(); + _cropTypeCombo->show(); + hbox3->show(); + vbox2->show(); + alignment3->show(); + _labelPageSettings->show(); + _pageSettingsFrame->show(); + _labelPrecision->show(); + _labelPrecisionWarning->show(); + _fallbackPrecisionSlider->show(); + _labelPrecisionComment->show(); + hbox6->show(); + _labelText->show(); + _textHandlingCombo->show(); + hbox5->show(); + _localFontsCheck->show(); + _embedImagesCheck->show(); + vbox3->show(); + alignment4->show(); + _labelImportSettings->show(); + _importSettingsFrame->show(); + vbox1->show(); + _previewArea->show(); + hbox1->show(); + + // Connect signals + _previewArea->signal_expose_event().connect(sigc::mem_fun(*this, &PdfImportCairoDialog::_onExposePreview)); + _pageNumberSpin_adj->signal_value_changed().connect(sigc::mem_fun(*this, &PdfImportCairoDialog::_onPageNumberChanged)); + _cropCheck->signal_toggled().connect(sigc::mem_fun(*this, &PdfImportCairoDialog::_onToggleCropping)); + _fallbackPrecisionSlider_adj->signal_value_changed().connect(sigc::mem_fun(*this, &PdfImportCairoDialog::_onPrecisionChanged)); + + _render_thumb = false; + _cairo_surface = NULL; + _render_thumb = true; + + // Set default preview size + _preview_width = 200; + _preview_height = 300; + + // Init preview + _thumb_data = NULL; + _pageNumberSpin_adj->set_value(1.0); + _current_page = 1; + _setPreviewPage(_current_page); + + set_default (*okbutton); + set_focus (*okbutton); +} + +PdfImportCairoDialog::~PdfImportCairoDialog() { + if (_cairo_surface) { + cairo_surface_destroy(_cairo_surface); + } + if (_thumb_data) { + if (_render_thumb) { + delete _thumb_data; + } else { + // -->gfree(_thumb_data); + delete _thumb_data; + } + } +} + +bool PdfImportCairoDialog::showDialog() { + show(); + gint b = run(); + hide(); + if ( b == Gtk::RESPONSE_OK ) { + return TRUE; + } else { + return FALSE; + } +} + +int PdfImportCairoDialog::getSelectedPage() { + return _current_page; +} + +/** + * \brief Retrieves the current settings into a repr which SvgBuilder will use + * for determining the behaviour desired by the user + */ +void PdfImportCairoDialog::getImportSettings(Inkscape::XML::Node *prefs) { + sp_repr_set_svg_double(prefs, "selectedPage", (double)_current_page); + if (_cropCheck->get_active()) { + Glib::ustring current_choice = _cropTypeCombo->get_active_text(); + int num_crop_choices = sizeof(crop_setting_choices) / sizeof(crop_setting_choices[0]); + int i = 0; + for ( ; i < num_crop_choices ; i++ ) { + if ( current_choice == _(crop_setting_choices[i]) ) { + break; + } + } + sp_repr_set_svg_double(prefs, "cropTo", (double)i); + } else { + sp_repr_set_svg_double(prefs, "cropTo", -1.0); + } + sp_repr_set_svg_double(prefs, "approximationPrecision", + _fallbackPrecisionSlider->get_value()); + if (_localFontsCheck->get_active()) { + prefs->setAttribute("localFonts", "1"); + } else { + prefs->setAttribute("localFonts", "0"); + } + if (_embedImagesCheck->get_active()) { + prefs->setAttribute("embedImages", "1"); + } else { + prefs->setAttribute("embedImages", "0"); + } +} + +/** + * \brief Redisplay the comment on the current approximation precision setting + * Evenly divides the interval of possible values between the available labels. + */ +void PdfImportCairoDialog::_onPrecisionChanged() { + + static Glib::ustring precision_comments[] = { + Glib::ustring(C_("PDF input precision", "rough")), + Glib::ustring(C_("PDF input precision", "medium")), + Glib::ustring(C_("PDF input precision", "fine")), + Glib::ustring(C_("PDF input precision", "very fine")) + }; + + double min = _fallbackPrecisionSlider_adj->get_lower(); + double max = _fallbackPrecisionSlider_adj->get_upper(); + int num_intervals = sizeof(precision_comments) / sizeof(precision_comments[0]); + double interval_len = ( max - min ) / (double)num_intervals; + double value = _fallbackPrecisionSlider_adj->get_value(); + int comment_idx = (int)floor( ( value - min ) / interval_len ); + _labelPrecisionComment->set_label(precision_comments[comment_idx]); +} + +void PdfImportCairoDialog::_onToggleCropping() { + _cropTypeCombo->set_sensitive(_cropCheck->get_active()); +} + +void PdfImportCairoDialog::_onPageNumberChanged() { + int page = _pageNumberSpin->get_value_as_int(); + _current_page = CLAMP(page, 1, poppler_document_get_n_pages(_poppler_doc)); + _setPreviewPage(_current_page); +} + +/** + * \brief Copies image data from a Cairo surface to a pixbuf + * + * Borrowed from libpoppler, from the file poppler-page.cc + * Copyright (C) 2005, Red Hat, Inc. + * + */ +static void copy_cairo_surface_to_pixbuf (cairo_surface_t *surface, + unsigned char *data, + GdkPixbuf *pixbuf) +{ + int cairo_width, cairo_height, cairo_rowstride; + unsigned char *pixbuf_data, *dst, *cairo_data; + int pixbuf_rowstride, pixbuf_n_channels; + unsigned int *src; + int x, y; + + cairo_width = cairo_image_surface_get_width (surface); + cairo_height = cairo_image_surface_get_height (surface); + cairo_rowstride = cairo_width * 4; + cairo_data = data; + + pixbuf_data = gdk_pixbuf_get_pixels (pixbuf); + pixbuf_rowstride = gdk_pixbuf_get_rowstride (pixbuf); + pixbuf_n_channels = gdk_pixbuf_get_n_channels (pixbuf); + + if (cairo_width > gdk_pixbuf_get_width (pixbuf)) + cairo_width = gdk_pixbuf_get_width (pixbuf); + if (cairo_height > gdk_pixbuf_get_height (pixbuf)) + cairo_height = gdk_pixbuf_get_height (pixbuf); + for (y = 0; y < cairo_height; y++) + { + src = (unsigned int *) (cairo_data + y * cairo_rowstride); + dst = pixbuf_data + y * pixbuf_rowstride; + for (x = 0; x < cairo_width; x++) + { + dst[0] = (*src >> 16) & 0xff; + dst[1] = (*src >> 8) & 0xff; + dst[2] = (*src >> 0) & 0xff; + if (pixbuf_n_channels == 4) + dst[3] = (*src >> 24) & 0xff; + dst += pixbuf_n_channels; + src++; + } + } +} + +/** + * \brief Updates the preview area with the previously rendered thumbnail + */ +bool PdfImportCairoDialog::_onExposePreview(GdkEventExpose */*event*/) { + + // Check if we have a thumbnail at all + if (!_thumb_data) { + return true; + } + + // Create the pixbuf for the thumbnail + Glib::RefPtr thumb; + if (_render_thumb) { + thumb = Gdk::Pixbuf::create(Gdk::COLORSPACE_RGB, true, + 8, _thumb_width, _thumb_height); + } else { + thumb = Gdk::Pixbuf::create_from_data(_thumb_data, Gdk::COLORSPACE_RGB, + false, 8, _thumb_width, _thumb_height, _thumb_rowstride); + } + if (!thumb) { + return true; + } + + // Set background to white + if (_render_thumb) { + thumb->fill(0xffffffff); + Glib::RefPtr back_pixmap = Gdk::Pixmap::create( + _previewArea->get_window(), _thumb_width, _thumb_height, -1); + if (!back_pixmap) { + return true; + } + back_pixmap->draw_pixbuf(Glib::RefPtr(), thumb, 0, 0, 0, 0, + _thumb_width, _thumb_height, + Gdk::RGB_DITHER_NONE, 0, 0); + _previewArea->get_window()->set_back_pixmap(back_pixmap, false); + _previewArea->get_window()->clear(); + } + + // Copy the thumbnail image from the Cairo surface + if (_render_thumb) { + copy_cairo_surface_to_pixbuf(_cairo_surface, _thumb_data, thumb->gobj()); + } + _previewArea->get_window()->draw_pixbuf(Glib::RefPtr(), thumb, + 0, 0, 0, _render_thumb ? 0 : 20, + -1, -1, Gdk::RGB_DITHER_NONE, 0, 0); + + return true; +} + +/** + * \brief Renders the given page's thumbnail using Cairo + */ +void PdfImportCairoDialog::_setPreviewPage(int page) { + + PopplerPage *_previewed_page = poppler_document_get_page(_poppler_doc, page); + + // Try to get a thumbnail from the PDF if possible + if (!_render_thumb) { + if (_thumb_data) { + // --> gfree(_thumb_data); + free(_thumb_data); + _thumb_data = NULL; + } + +/* +--> if (!_previewed_page->loadThumb(&_thumb_data, + &_thumb_width, &_thumb_height, &_thumb_rowstride)) { + return; + } +*/ + // Redraw preview area + _previewArea->set_size_request(_thumb_width, _thumb_height + 20); + _previewArea->queue_draw(); + return; + } + + // Get page size by accounting for rotation + double width, height; + // --> int rotate = _previewed_page->getRotate(); + int rotate = 0; + if ( rotate == 90 || rotate == 270 ) { +// --> height = _previewed_page->getCropWidth(); +// --> width = _previewed_page->getCropHeight(); + } else { + poppler_page_get_size (_previewed_page, &width, &height); +// --> width = _previewed_page->getCropWidth(); +// --> height = _previewed_page->getCropHeight(); + } + // Calculate the needed scaling for the page + double scale_x = (double)_preview_width / width; + double scale_y = (double)_preview_height / height; + double scale_factor = ( scale_x > scale_y ) ? scale_y : scale_x; + // Create new Cairo surface + _thumb_width = (int)ceil( width * scale_factor ); + _thumb_height = (int)ceil( height * scale_factor ); + _thumb_rowstride = _thumb_width * 4; + if (_thumb_data) { + delete _thumb_data; + } + _thumb_data = new unsigned char[ _thumb_rowstride * _thumb_height ]; + if (_cairo_surface) { + cairo_surface_destroy(_cairo_surface); + } + _cairo_surface = cairo_image_surface_create_for_data(_thumb_data, + CAIRO_FORMAT_ARGB32, _thumb_width, _thumb_height, _thumb_rowstride); + cairo_t *cr = cairo_create(_cairo_surface); + cairo_set_source_rgba(cr, 1.0, 1.0, 1.0, 1.0); // Set fill color to white + cairo_paint(cr); // Clear it + cairo_scale(cr, scale_factor, scale_factor); // Use Cairo for resizing the image + // Render page + if (_poppler_doc != NULL) { + PopplerPage *poppler_page = poppler_document_get_page(_poppler_doc, page - 1); + poppler_page_render(poppler_page, cr); + g_object_unref(G_OBJECT(poppler_page)); + } + // Clean up + cairo_destroy(cr); + // Redraw preview area + _previewArea->set_size_request(_preview_width, _preview_height); + _previewArea->queue_draw(); + +} + + static cairo_status_t _write_ustring_cb(void *closure, const unsigned char *data, unsigned int length); SPDocument * PdfInputCairo::open(Inkscape::Extension::Input * /*mod*/, const gchar * uri) { - printf("Attempting to open using PdfInputCairo\n"); + g_message("Attempting to open using PdfInputCairo\n"); gchar* filename_uri = g_filename_to_uri(uri, NULL, NULL); - PopplerDocument* document = poppler_document_new_from_file(filename_uri, NULL, NULL); - if (document == NULL) + GError *error = NULL; + /// @todo handle passwort + /// @todo check if win32 unicode needs special attention + PopplerDocument* document = poppler_document_new_from_file(filename_uri, NULL, &error); + + if(error != NULL) { + g_message("Unable to read file: %s\n", error->message); + g_error_free (error); + } + + if (document == NULL) { return NULL; + } + + // create and show the import dialog + PdfImportCairoDialog *dlg = NULL; + if (inkscape_use_gui()) { + dlg = new PdfImportCairoDialog(document); + if (!dlg->showDialog()) { + delete dlg; + return NULL; + } + } + + // Get needed page + int page_num; + if (dlg) { + page_num = dlg->getSelectedPage(); + delete dlg; + } + else + page_num = 1; double width, height; - PopplerPage* page = poppler_document_get_page(document, 0); + PopplerPage* page = poppler_document_get_page(document, page_num - 1); poppler_page_get_size(page, &width, &height); Glib::ustring* output = new Glib::ustring(""); @@ -99,6 +663,7 @@ PdfInputCairo::init(void) { } } } /* namespace Inkscape, Extension, Implementation */ +#endif /* HAVE_POPPLER_CAIRO */ #endif /* HAVE_POPPLER_GLIB */ /* diff --git a/src/extension/internal/pdf-input-cairo.h b/src/extension/internal/pdf-input-cairo.h index 5715b57c9..b0e196468 100644 --- a/src/extension/internal/pdf-input-cairo.h +++ b/src/extension/internal/pdf-input-cairo.h @@ -16,7 +16,25 @@ # include #endif +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + #ifdef HAVE_POPPLER_GLIB +#ifdef HAVE_POPPLER_CAIRO + +#include #include "../implementation/implementation.h" @@ -24,6 +42,69 @@ namespace Inkscape { namespace Extension { namespace Internal { +class PdfImportCairoDialog : public Gtk::Dialog +{ +public: + PdfImportCairoDialog(PopplerDocument* doc); + virtual ~PdfImportCairoDialog(); + + bool showDialog(); + int getSelectedPage(); + void getImportSettings(Inkscape::XML::Node *prefs); + +private: + void _setPreviewPage(int page); + + // Signal handlers + bool _onExposePreview(GdkEventExpose *event); + void _onPageNumberChanged(); + void _onToggleCropping(); + void _onPrecisionChanged(); + + class Gtk::Button * cancelbutton; + class Gtk::Button * okbutton; + class Gtk::Label * _labelSelect; + class Gtk::SpinButton * _pageNumberSpin; + class Gtk::Label * _labelTotalPages; + class Gtk::HBox * hbox2; + class Gtk::CheckButton * _cropCheck; + class Gtk::ComboBoxText * _cropTypeCombo; + class Gtk::HBox * hbox3; + class Gtk::VBox * vbox2; + class Gtk::Alignment * alignment3; + class Gtk::Label * _labelPageSettings; + class Gtk::Frame * _pageSettingsFrame; + class Gtk::Label * _labelPrecision; + class Gtk::Label * _labelPrecisionWarning; + class Gtk::HScale * _fallbackPrecisionSlider; + class Gtk::Adjustment *_fallbackPrecisionSlider_adj; + class Gtk::Label * _labelPrecisionComment; + class Gtk::HBox * hbox6; + class Gtk::Label * _labelText; + class Gtk::ComboBoxText * _textHandlingCombo; + class Gtk::HBox * hbox5; + class Gtk::CheckButton * _localFontsCheck; + class Gtk::CheckButton * _embedImagesCheck; + class Gtk::VBox * vbox3; + class Gtk::Alignment * alignment4; + class Gtk::Label * _labelImportSettings; + class Gtk::Frame * _importSettingsFrame; + class Gtk::VBox * vbox1; + class Gtk::DrawingArea * _previewArea; + class Gtk::HBox * hbox1; + + PopplerDocument *_poppler_doc; + // PopplerPage *_previewed_page; + int _current_page; // Current selected page + unsigned char *_thumb_data; // Thumbnail image data + int _thumb_width, _thumb_height; // Thumbnail size + int _thumb_rowstride; + int _preview_width, _preview_height; // Size of the preview area + bool _render_thumb; // Whether we can/shall render thumbnails + cairo_surface_t *_cairo_surface; // this cairo surface is used for preview +}; + + class PdfInputCairo: public Inkscape::Extension::Implementation::Implementation { PdfInputCairo () { }; public: @@ -35,6 +116,7 @@ public: } } } /* namespace Inkscape, Extension, Implementation */ +#endif /* HAVE_POPPLER_CAIRO */ #endif /* HAVE_POPPLER_GLIB */ #endif /* __EXTENSION_INTERNAL_PDFINPUTCAIRO_H__ */ -- cgit v1.2.3 From bfa43feb53fb231402a36db7da69fc9e69523b54 Mon Sep 17 00:00:00 2001 From: Adib Taraben Date: Wed, 16 Feb 2011 00:28:31 +0100 Subject: pdf-import via poppler-cairo fix win32 compilation (bzr r10053.1.1) --- src/extension/internal/pdf-input-cairo.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/extension/internal/pdf-input-cairo.h b/src/extension/internal/pdf-input-cairo.h index b0e196468..ad7c884cb 100644 --- a/src/extension/internal/pdf-input-cairo.h +++ b/src/extension/internal/pdf-input-cairo.h @@ -34,7 +34,7 @@ #ifdef HAVE_POPPLER_GLIB #ifdef HAVE_POPPLER_CAIRO -#include +#include #include "../implementation/implementation.h" -- cgit v1.2.3 From 4adb50d2573ca55d83551222799e43acdc440dc2 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Fri, 18 Feb 2011 20:03:23 +0100 Subject: Bucket. Lowering the maximum shrink value (see Bug #587769, Paint Bucket: Upper/lower value in context menu of Grow/shrink are unrealistic). (bzr r10057) --- src/widgets/toolbox.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src') diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index da919e42e..b488a0280 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -8447,7 +8447,7 @@ static void sp_paintbucket_toolbox_prep(SPDesktop *desktop, GtkActionGroup* main _("Grow/shrink by"), _("Grow/shrink by:"), _("The amount to grow (positive) or shrink (negative) the created fill path"), "/tools/paintbucket/offset", 0, GTK_WIDGET(desktop->canvas), NULL/*us*/, holder, TRUE, - "inkscape:paintbucket-offset", -1e6, 1e6, 0.1, 0.5, + "inkscape:paintbucket-offset", -1e4, 1e4, 0.1, 0.5, 0, 0, 0, paintbucket_offset_changed, 1, 2); tracker->addAdjustment( ege_adjustment_action_get_adjustment(eact) ); -- cgit v1.2.3 From 5591416acb4dda87305c3329b66eefb940ddde5c Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sat, 19 Feb 2011 12:10:53 -0800 Subject: Fix the zoom changed signal to no longer be sent out before the values have finished changing. (bzr r10058) --- src/desktop.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/desktop.cpp b/src/desktop.cpp index b382a1d91..8a4122e78 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -769,6 +769,7 @@ void SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double border, bool log) { g_assert(_widget); + bool zoomChanged = false; // save the zoom if (log) { @@ -802,7 +803,7 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double _w2d = Geom::Scale(1/newscale, 1/-newscale); sp_canvas_item_affine_absolute(SP_CANVAS_ITEM(main), _d2w); clear = TRUE; - signal_zoom_changed.emit(_d2w.descrim()); + zoomChanged = true; } /* Calculate top left corner (in document pixels) */ @@ -818,6 +819,11 @@ SPDesktop::set_display_area (double x0, double y0, double x1, double y1, double _widget->updateRulers(); _widget->updateScrollbars(_d2w.descrim()); _widget->updateZoom(); + + + if ( zoomChanged ) { + signal_zoom_changed.emit(_d2w.descrim()); + } } void SPDesktop::set_display_area(Geom::Rect const &a, Geom::Coord b, bool log) -- cgit v1.2.3 From 60119035d8b8cf1f32cce97a4a4b9b181ba91cf8 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 20 Feb 2011 02:37:24 -0800 Subject: Pass removing some outdated C-macro use. (bzr r10059) --- src/box3d-side.cpp | 12 +-- src/box3d.cpp | 30 +++---- src/color-profile.cpp | 2 +- src/conditions.cpp | 2 +- src/conn-avoid-ref.cpp | 15 ++-- src/desktop-events.cpp | 2 +- src/desktop.cpp | 8 +- src/document.cpp | 6 +- src/filters/componenttransfer-funcnode.cpp | 11 ++- src/filters/distantlight.cpp | 8 +- src/filters/pointlight.cpp | 8 +- src/filters/spotlight.cpp | 8 +- src/gradient-chemistry.cpp | 139 +++++++++++++++-------------- src/gradient-context.cpp | 16 ++-- src/gradient-drag.cpp | 54 +++++------ src/sp-root.cpp | 2 +- 16 files changed, 160 insertions(+), 163 deletions(-) (limited to 'src') diff --git a/src/box3d-side.cpp b/src/box3d-side.cpp index 72a479ca4..0c74a8f7e 100644 --- a/src/box3d-side.cpp +++ b/src/box3d-side.cpp @@ -209,21 +209,21 @@ void box3d_side_position_set (Box3DSide *side) { box3d_side_set_shape (SP_SHAPE (side)); - /* This call is responsible for live update of the sides during the initial drag */ - SP_OBJECT(side)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + // This call is responsible for live update of the sides during the initial drag + side->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } void box3d_side_set_shape (SPShape *shape) { Box3DSide *side = SP_BOX3D_SIDE (shape); - if (!SP_OBJECT_DOCUMENT(side)->root) { + if (!side->document->root) { // avoid a warning caused by sp_document_height() (which is called from sp_item_i2d_affine() below) // when reading a file containing 3D boxes return; } - SPObject *parent = SP_OBJECT(side)->parent; + SPObject *parent = side->parent; if (!SP_IS_BOX3D(parent)) { g_warning ("Parent of 3D box side is not a 3D box.\n"); return; @@ -306,12 +306,12 @@ box3d_side_compute_corner_ids(Box3DSide *side, unsigned int corners[4]) { Persp3D * box3d_side_perspective(Box3DSide *side) { - return SP_BOX3D(SP_OBJECT(side)->parent)->persp_ref->getObject(); + return SP_BOX3D(side->parent)->persp_ref->getObject(); } Inkscape::XML::Node *box3d_side_convert_to_path(Box3DSide *side) { // TODO: Copy over all important attributes (see sp_selected_item_to_curved_repr() for an example) - SPDocument *doc = SP_OBJECT_DOCUMENT(side); + SPDocument *doc = side->document; Inkscape::XML::Document *xml_doc = doc->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); diff --git a/src/box3d.cpp b/src/box3d.cpp index cc3280150..a1ac84f14 100644 --- a/src/box3d.cpp +++ b/src/box3d.cpp @@ -105,11 +105,10 @@ static void box3d_init(SPBox3D *box) { box->persp_href = NULL; - box->persp_ref = new Persp3DReference(SP_OBJECT(box)); + box->persp_ref = new Persp3DReference(box); } -static void -box3d_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr) +static void box3d_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr) { if (((SPObjectClass *) (parent_class))->build) { ((SPObjectClass *) (parent_class))->build(object, document, repr); @@ -125,15 +124,14 @@ box3d_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr) // TODO: Create/link to the correct perspective - SPDocument *doc = SP_OBJECT_DOCUMENT(box); - if (!doc) - return; - - box->persp_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(box3d_ref_changed), box)); + SPDocument *doc = box->document; + if ( doc ) { + box->persp_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(box3d_ref_changed), box)); - object->readAttr( "inkscape:perspectiveID" ); - object->readAttr( "inkscape:corner0" ); - object->readAttr( "inkscape:corner7" ); + object->readAttr( "inkscape:perspectiveID" ); + object->readAttr( "inkscape:corner0" ); + object->readAttr( "inkscape:corner7" ); + } } /** @@ -168,7 +166,7 @@ box3d_release(SPObject *object) // by the following code and then again by the redo mechanism! Perhaps we should perform // deletion of the perspective from another location "outside" the undo/redo mechanism? if (persp->perspective_impl->boxes.empty()) { - SPDocument *doc = SP_OBJECT_DOCUMENT(box); + SPDocument *doc = box->document; persp->deleteObject(); doc->setCurrentPersp3D(persp3d_document_first_persp(doc)); } @@ -283,7 +281,7 @@ static Inkscape::XML::Node * box3d_write(SPObject *object, Inkscape::XML::Docume repr->setAttribute("inkscape:perspectiveID", box->persp_href); } else { /* box is not yet linked to a perspective; use the document's current perspective */ - SPDocument *doc = SP_OBJECT_DOCUMENT(object); + SPDocument *doc = object->document; if (box->persp_ref->getURI()) { gchar *uri_string = box->persp_ref->getURI()->toString(); repr->setAttribute("inkscape:perspectiveID", uri_string); @@ -1344,7 +1342,7 @@ box3d_switch_perspectives(SPBox3D *box, Persp3D *old_persp, Persp3D *new_persp, the original box and deletes the latter */ SPGroup *box3d_convert_to_group(SPBox3D *box) { - SPDocument *doc = SP_OBJECT_DOCUMENT(box); + SPDocument *doc = box->document; Inkscape::XML::Document *xml_doc = doc->getReprDoc(); // remember position of the box @@ -1369,7 +1367,7 @@ SPGroup *box3d_convert_to_group(SPBox3D *box) } // add the new group to the box's parent and set remembered position - SPObject *parent = SP_OBJECT_PARENT(box); + SPObject *parent = box->parent; parent->appendChild(grepr); grepr->setPosition(pos); grepr->setAttribute("style", style); @@ -1378,7 +1376,7 @@ SPGroup *box3d_convert_to_group(SPBox3D *box) if (clip_path) grepr->setAttribute("clip-path", clip_path); - SP_OBJECT(box)->deleteObject(true); + box->deleteObject(true); grepr->setAttribute("id", id); diff --git a/src/color-profile.cpp b/src/color-profile.cpp index e08a416d3..f06ebab88 100644 --- a/src/color-profile.cpp +++ b/src/color-profile.cpp @@ -283,7 +283,7 @@ void ColorProfile::set( SPObject *object, unsigned key, gchar const *value ) //LCMSAPI cmsHPROFILE LCMSEXPORT cmsOpenProfileFromMem(LPVOID MemPtr, DWORD dwSize); // Try to open relative - SPDocument *doc = SP_OBJECT_DOCUMENT(object); + SPDocument *doc = object->document; if (!doc) { doc = SP_ACTIVE_DOCUMENT; g_warning("object has no document. using active"); diff --git a/src/conditions.cpp b/src/conditions.cpp index d35f18cf1..21218831a 100644 --- a/src/conditions.cpp +++ b/src/conditions.cpp @@ -103,7 +103,7 @@ static bool evaluateSystemLanguage(SPItem const *item, gchar const *value) { if (language_codes.empty()) return false; - SPDocument *document = SP_OBJECT_DOCUMENT(item); + SPDocument *document = item->document; Glib::ustring document_language = document->getLanguage(); if (document_language.size() == 0) diff --git a/src/conn-avoid-ref.cpp b/src/conn-avoid-ref.cpp index 410090e22..4c6139672 100644 --- a/src/conn-avoid-ref.cpp +++ b/src/conn-avoid-ref.cpp @@ -75,13 +75,12 @@ SPAvoidRef::~SPAvoidRef() void SPAvoidRef::setAvoid(char const *value) { - if (SP_OBJECT_IS_CLONED(item)) { - // Don't keep avoidance information for cloned objects. - return; - } - new_setting = false; - if (value && (strcmp(value, "true") == 0)) { - new_setting = true; + // Don't keep avoidance information for cloned objects. + if ( !item->cloned ) { + new_setting = false; + if (value && (strcmp(value, "true") == 0)) { + new_setting = true; + } } } @@ -194,7 +193,7 @@ void SPAvoidRef::setConnectionPoints(gchar const *value) void SPAvoidRef::setConnectionPointsAttrUndoable(const gchar* value, const gchar* action) { - SPDocument* doc = SP_OBJECT_DOCUMENT(item); + SPDocument* doc = item->document; item->setAttribute( "inkscape:connection-points", value, 0 ); item->updateRepr(); diff --git a/src/desktop-events.cpp b/src/desktop-events.cpp index 71c865879..b458827f0 100644 --- a/src/desktop-events.cpp +++ b/src/desktop-events.cpp @@ -453,7 +453,7 @@ gint sp_dt_guide_event(SPCanvasItem *item, GdkEvent *event, gpointer data) case GDK_KP_Delete: case GDK_BackSpace: { - SPDocument *doc = SP_OBJECT_DOCUMENT(guide); + SPDocument *doc = guide->document; sp_guide_remove(guide); DocumentUndo::done(doc, SP_VERB_NONE, _("Delete guide")); ret = TRUE; diff --git a/src/desktop.cpp b/src/desktop.cpp index 8a4122e78..b5e7cdd33 100644 --- a/src/desktop.cpp +++ b/src/desktop.cpp @@ -185,7 +185,7 @@ SPDesktop::init (SPNamedView *nv, SPCanvas *aCanvas, Inkscape::UI::View::EditWid namedview = nv; canvas = aCanvas; - SPDocument *document = SP_OBJECT_DOCUMENT (namedview); + SPDocument *document = namedview->document; /* Kill flicker */ document->ensureUpToDate(); @@ -532,9 +532,9 @@ SPObject *SPDesktop::layerForObject(SPObject *object) { g_return_val_if_fail(object != NULL, NULL); SPObject *root=currentRoot(); - object = SP_OBJECT_PARENT(object); + object = object->parent; while ( object && object != root && !isLayer(object) ) { - object = SP_OBJECT_PARENT(object); + object = object->parent; } return object; } @@ -1686,7 +1686,7 @@ _reconstruction_finish (SPDesktop * desktop) if (desktop->_reconstruction_old_layer_id == NULL) return; - SPObject * newLayer = SP_OBJECT_DOCUMENT(desktop->namedview)->getObjectById(desktop->_reconstruction_old_layer_id); + SPObject * newLayer = desktop->namedview->document->getObjectById(desktop->_reconstruction_old_layer_id); if (newLayer != NULL) desktop->setCurrentLayer(newLayer); diff --git a/src/document.cpp b/src/document.cpp index a473daa3c..2a9ad9144 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -267,7 +267,7 @@ unsigned long SPDocument::serial() const { void SPDocument::queueForOrphanCollection(SPObject *object) { g_return_if_fail(object != NULL); - g_return_if_fail(SP_OBJECT_DOCUMENT(object) == this); + g_return_if_fail(object->document == this); sp_object_ref(object, NULL); _collection_queue = g_slist_prepend(_collection_queue, object); @@ -550,7 +550,7 @@ void SPDocument::setWidth(gdouble width, const SPUnit *unit) root->viewBox.x1 = root->viewBox.x0 + (root->width.computed / old_computed) * (root->viewBox.x1 - root->viewBox.x0); } - SP_OBJECT (root)->updateRepr(); + root->updateRepr(); } void SPDocument::setHeight(gdouble height, const SPUnit *unit) @@ -576,7 +576,7 @@ void SPDocument::setHeight(gdouble height, const SPUnit *unit) root->viewBox.y1 = root->viewBox.y0 + (root->height.computed / old_computed) * (root->viewBox.y1 - root->viewBox.y0); } - SP_OBJECT (root)->updateRepr(); + root->updateRepr(); } gdouble SPDocument::getHeight() const diff --git a/src/filters/componenttransfer-funcnode.cpp b/src/filters/componenttransfer-funcnode.cpp index a245e1c89..446009e1d 100644 --- a/src/filters/componenttransfer-funcnode.cpp +++ b/src/filters/componenttransfer-funcnode.cpp @@ -183,14 +183,13 @@ sp_fefuncnode_build(SPObject *object, SPDocument *document, Inkscape::XML::Node /** * Drops any allocated memory. */ -static void -sp_fefuncnode_release(SPObject *object) +static void sp_fefuncnode_release(SPObject *object) { //SPFeFuncNode *fefuncnode = SP_FEFUNCNODE(object); - if (SP_OBJECT_DOCUMENT(object)) { - /* Unregister ourselves */ - SP_OBJECT_DOCUMENT(object)->removeResource("fefuncnode", SP_OBJECT(object)); + if ( object->document ) { + // Unregister ourselves + object->document->removeResource("fefuncnode", object); } //TODO: release resources here @@ -313,7 +312,7 @@ sp_fefuncnode_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XM SPFeFuncNode *fefuncnode = SP_FEFUNCNODE(object); if (!repr) { - repr = SP_OBJECT_REPR(object)->duplicate(doc); + repr = object->getRepr()->duplicate(doc); } (void)fefuncnode; diff --git a/src/filters/distantlight.cpp b/src/filters/distantlight.cpp index 2207bc8e4..88c2a21ff 100644 --- a/src/filters/distantlight.cpp +++ b/src/filters/distantlight.cpp @@ -115,9 +115,9 @@ sp_fedistantlight_release(SPObject *object) { //SPFeDistantLight *fedistantlight = SP_FEDISTANTLIGHT(object); - if (SP_OBJECT_DOCUMENT(object)) { - /* Unregister ourselves */ - SP_OBJECT_DOCUMENT(object)->removeResource("fedistantlight", SP_OBJECT(object)); + if ( object->document ) { + // Unregister ourselves + object->document->removeResource("fedistantlight", object); } //TODO: release resources here @@ -206,7 +206,7 @@ sp_fedistantlight_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape SPFeDistantLight *fedistantlight = SP_FEDISTANTLIGHT(object); if (!repr) { - repr = SP_OBJECT_REPR(object)->duplicate(doc); + repr = object->getRepr()->duplicate(doc); } if (fedistantlight->azimuth_set) diff --git a/src/filters/pointlight.cpp b/src/filters/pointlight.cpp index c9eebcb18..28b3ee165 100644 --- a/src/filters/pointlight.cpp +++ b/src/filters/pointlight.cpp @@ -119,9 +119,9 @@ sp_fepointlight_release(SPObject *object) { //SPFePointLight *fepointlight = SP_FEPOINTLIGHT(object); - if (SP_OBJECT_DOCUMENT(object)) { - /* Unregister ourselves */ - SP_OBJECT_DOCUMENT(object)->removeResource("fepointlight", SP_OBJECT(object)); + if ( object->document ) { + // Unregister ourselves + object->document->removeResource("fepointlight", object); } //TODO: release resources here @@ -229,7 +229,7 @@ sp_fepointlight_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape:: SPFePointLight *fepointlight = SP_FEPOINTLIGHT(object); if (!repr) { - repr = SP_OBJECT_REPR(object)->duplicate(doc); + repr = object->getRepr()->duplicate(doc); } if (fepointlight->x_set) diff --git a/src/filters/spotlight.cpp b/src/filters/spotlight.cpp index dac9b87e7..b6753a1f1 100644 --- a/src/filters/spotlight.cpp +++ b/src/filters/spotlight.cpp @@ -134,9 +134,9 @@ sp_fespotlight_release(SPObject *object) { //SPFeSpotLight *fespotlight = SP_FESPOTLIGHT(object); - if (SP_OBJECT_DOCUMENT(object)) { - /* Unregister ourselves */ - SP_OBJECT_DOCUMENT(object)->removeResource("fespotlight", SP_OBJECT(object)); + if ( object->document ) { + // Unregister ourselves + object->document->removeResource("fespotlight", object); } //TODO: release resources here @@ -332,7 +332,7 @@ sp_fespotlight_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::X SPFeSpotLight *fespotlight = SP_FESPOTLIGHT(object); if (!repr) { - repr = SP_OBJECT_REPR(object)->duplicate(doc); + repr = object->getRepr()->duplicate(doc); } if (fespotlight->x_set) diff --git a/src/gradient-chemistry.cpp b/src/gradient-chemistry.cpp index d99a57208..86b63855b 100644 --- a/src/gradient-chemistry.cpp +++ b/src/gradient-chemistry.cpp @@ -81,9 +81,9 @@ SPGradient *sp_gradient_ensure_vector_normalized(SPGradient *gr) /* If gr hrefs some other gradient, remove the href */ if (gr->ref->getObject()) { - /* We are hrefing someone, so require flattening */ - SP_OBJECT(gr)->updateRepr(SP_OBJECT_WRITE_EXT | SP_OBJECT_WRITE_ALL); - sp_gradient_repr_set_link(SP_OBJECT_REPR(gr), NULL); + // We are hrefing someone, so require flattening + gr->updateRepr(SP_OBJECT_WRITE_EXT | SP_OBJECT_WRITE_ALL); + sp_gradient_repr_set_link(gr->getRepr(), NULL); } /* Everything is OK, set state flag */ @@ -124,7 +124,7 @@ static SPGradient *sp_gradient_get_private_normalized(SPDocument *document, SPGr sp_gradient_repr_set_link(repr, vector); /* Append the new private gradient to defs */ - SP_OBJECT_REPR(defs)->appendChild(repr); + defs->getRepr()->appendChild(repr); Inkscape::GC::release(repr); // get corresponding object @@ -145,7 +145,7 @@ guint count_gradient_hrefs(SPObject *o, SPGradient *gr) guint i = 0; - SPStyle *style = SP_OBJECT_STYLE(o); + SPStyle *style = o->style; if (style && style->fill.isPaintserver() && SP_IS_GRADIENT(SP_STYLE_FILL_SERVER(style)) @@ -193,7 +193,7 @@ SPGradient *sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradient *ve // texts. SPObject *user = o; while (SP_IS_TSPAN(user)) { - user = SP_OBJECT_PARENT(user); + user = user->parent; } // Check the number of uses of the gradient within this object; @@ -202,17 +202,17 @@ SPGradient *sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradient *ve // check vector if ( gr != vector && gr->ref->getObject() != vector ) { /* our href is not the vector, and vector is different from gr; relink */ - sp_gradient_repr_set_link(SP_OBJECT_REPR(gr), vector); + sp_gradient_repr_set_link(gr->getRepr(), vector); } return gr; } - SPDocument *doc = SP_OBJECT_DOCUMENT(gr); + SPDocument *doc = gr->document; SPObject *defs = SP_DOCUMENT_DEFS(doc); if ((gr->hasStops()) || (gr->state != SP_GRADIENT_STATE_UNKNOWN) || - (SP_OBJECT_PARENT(gr) != SP_OBJECT(defs)) || + (gr->parent != SP_OBJECT(defs)) || (gr->hrefcount > 1)) { // we have to clone a fresh new private gradient for the given vector @@ -220,8 +220,8 @@ SPGradient *sp_gradient_fork_private_if_necessary(SPGradient *gr, SPGradient *ve SPGradient *gr_new = sp_gradient_get_private_normalized(doc, vector, type); // copy all the attributes to it - Inkscape::XML::Node *repr_new = SP_OBJECT_REPR(gr_new); - Inkscape::XML::Node *repr = SP_OBJECT_REPR(gr); + Inkscape::XML::Node *repr_new = gr_new->getRepr(); + Inkscape::XML::Node *repr = gr->getRepr(); repr_new->setAttribute("gradientUnits", repr->attribute("gradientUnits")); repr_new->setAttribute("gradientTransform", repr->attribute("gradientTransform")); repr_new->setAttribute("spreadMethod", repr->attribute("spreadMethod")); @@ -255,11 +255,11 @@ SPGradient *sp_gradient_fork_vector_if_necessary(SPGradient *gr) return gr; if (gr->hrefcount > 1) { - SPDocument *doc = SP_OBJECT_DOCUMENT(gr); + SPDocument *doc = gr->document; Inkscape::XML::Document *xml_doc = doc->getReprDoc(); - Inkscape::XML::Node *repr = SP_OBJECT_REPR (gr)->duplicate(xml_doc); - SP_OBJECT_REPR (SP_DOCUMENT_DEFS (doc))->addChild(repr, NULL); + Inkscape::XML::Node *repr = gr->getRepr()->duplicate(xml_doc); + SP_DOCUMENT_DEFS(doc)->getRepr()->addChild(repr, NULL); SPGradient *gr_new = (SPGradient *) doc->getObjectByRepr(repr); gr_new = sp_gradient_ensure_vector_normalized (gr_new); Inkscape::GC::release(repr); @@ -279,7 +279,7 @@ SPGradient *sp_gradient_get_forked_vector_if_necessary(SPGradient *gradient, boo SPGradient *vector = gradient->getVector(force_vector); vector = sp_gradient_fork_vector_if_necessary (vector); if ( gradient != vector && gradient->ref->getObject() != vector ) { - sp_gradient_repr_set_link(SP_OBJECT_REPR(gradient), vector); + sp_gradient_repr_set_link(gradient->getRepr(), vector); } return vector; } @@ -295,10 +295,10 @@ SPGradient *sp_gradient_reset_to_userspace(SPGradient *gr, SPItem *item) #ifdef SP_GR_VERBOSE g_message("sp_gradient_reset_to_userspace(%p, %p)", gr, item); #endif - Inkscape::XML::Node *repr = SP_OBJECT_REPR(gr); + Inkscape::XML::Node *repr = gr->getRepr(); // calculate the bbox of the item - SP_OBJECT_DOCUMENT(item)->ensureUpToDate(); + item->document->ensureUpToDate(); Geom::OptRect bbox = item->getBounds(Geom::identity()); // we need "true" bbox without item_i2d_affine if (!bbox) @@ -324,7 +324,7 @@ SPGradient *sp_gradient_reset_to_userspace(SPGradient *gr, SPItem *item) gr->gradientTransform = squeeze; { gchar *c=sp_svg_transform_write(gr->gradientTransform); - SP_OBJECT_REPR(gr)->setAttribute("gradientTransform", c); + gr->getRepr()->setAttribute("gradientTransform", c); g_free(c); } } else { @@ -357,14 +357,14 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar // First, fork it if it is shared gr = sp_gradient_fork_private_if_necessary(gr, gr->getVector(), - SP_IS_RADIALGRADIENT(gr) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, SP_OBJECT(item)); + SP_IS_RADIALGRADIENT(gr) ? SP_GRADIENT_TYPE_RADIAL : SP_GRADIENT_TYPE_LINEAR, item); if (gr->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR(gr); + Inkscape::XML::Node *repr = gr->getRepr(); // calculate the bbox of the item - SP_OBJECT_DOCUMENT(item)->ensureUpToDate(); + item->document->ensureUpToDate(); Geom::Affine bbox2user; Geom::OptRect bbox = item->getBounds(Geom::identity()); // we need "true" bbox without item_i2d_affine if ( bbox ) { @@ -403,7 +403,7 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar gr->gradientTransform = skew; { gchar *c=sp_svg_transform_write(gr->gradientTransform); - SP_OBJECT_REPR(gr)->setAttribute("gradientTransform", c); + gr->getRepr()->setAttribute("gradientTransform", c); g_free(c); } @@ -454,10 +454,11 @@ SPGradient *sp_gradient_convert_to_userspace(SPGradient *gr, SPItem *item, gchar // from sp_item_adjust_paint_recursive); however text and all its children should all // refer to one gradient, hence the recursive call for text (because we can't/don't // want to access tspans and set gradients on them separately) - if (SP_IS_TEXT(item)) - sp_style_set_property_url(SP_OBJECT(item), property, SP_OBJECT(gr), true); - else - sp_style_set_property_url(SP_OBJECT(item), property, SP_OBJECT(gr), false); + if (SP_IS_TEXT(item)) { + sp_style_set_property_url(item, property, gr, true); + } else { + sp_style_set_property_url(item, property, gr, false); + } return gr; } @@ -475,7 +476,7 @@ void sp_gradient_transform_multiply(SPGradient *gradient, Geom::Affine postmul, gradient->gradientTransform_set = TRUE; gchar *c=sp_svg_transform_write(gradient->gradientTransform); - SP_OBJECT_REPR(gradient)->setAttribute("gradientTransform", c); + gradient->getRepr()->setAttribute("gradientTransform", c); g_free(c); } @@ -549,12 +550,12 @@ SPStop *sp_vector_add_stop(SPGradient *vector, SPStop* prev_stop, SPStop* next_s #endif Inkscape::XML::Node *new_stop_repr = NULL; - new_stop_repr = SP_OBJECT_REPR(prev_stop)->duplicate(SP_OBJECT_REPR(vector)->document()); - SP_OBJECT_REPR(vector)->addChild(new_stop_repr, SP_OBJECT_REPR(prev_stop)); + new_stop_repr = prev_stop->getRepr()->duplicate(vector->getRepr()->document()); + vector->getRepr()->addChild(new_stop_repr, prev_stop->getRepr()); - SPStop *newstop = (SPStop *) SP_OBJECT_DOCUMENT(vector)->getObjectByRepr(new_stop_repr); + SPStop *newstop = reinterpret_cast(vector->document->getObjectByRepr(new_stop_repr)); newstop->offset = offset; - sp_repr_set_css_double( SP_OBJECT_REPR(newstop), "offset", (double)offset); + sp_repr_set_css_double( newstop->getRepr(), "offset", (double)offset); guint32 const c1 = sp_stop_get_rgba32(prev_stop); guint32 const c2 = sp_stop_get_rgba32(next_stop); guint32 cnew = average_color (c1, c2, (offset - prev_stop->offset) / (next_stop->offset - prev_stop->offset)); @@ -563,7 +564,7 @@ SPStop *sp_vector_add_stop(SPGradient *vector, SPStop* prev_stop, SPStop* next_s sp_svg_write_color (c, sizeof(c), cnew); gdouble opacity = (gdouble) SP_RGBA32_A_F (cnew); os << "stop-color:" << c << ";stop-opacity:" << opacity <<";"; - SP_OBJECT_REPR (newstop)->setAttribute("style", os.str().c_str()); + newstop->getRepr()->setAttribute("style", os.str().c_str()); Inkscape::GC::release(new_stop_repr); return newstop; @@ -678,7 +679,7 @@ void sp_item_gradient_stop_set_style(SPItem *item, guint point_type, guint point vector = sp_gradient_fork_vector_if_necessary (vector); if ( gradient != vector && gradient->ref->getObject() != vector ) { - sp_gradient_repr_set_link(SP_OBJECT_REPR(gradient), vector); + sp_gradient_repr_set_link(gradient->getRepr(), vector); } switch (point_type) { @@ -688,7 +689,7 @@ void sp_item_gradient_stop_set_style(SPItem *item, guint point_type, guint point { SPStop *first = vector->getFirstStop(); if (first) { - sp_repr_css_change (SP_OBJECT_REPR (first), stop, "style"); + sp_repr_css_change(first->getRepr(), stop, "style"); } } break; @@ -699,7 +700,7 @@ void sp_item_gradient_stop_set_style(SPItem *item, guint point_type, guint point { SPStop *last = sp_last_stop (vector); if (last) { - sp_repr_css_change (SP_OBJECT_REPR (last), stop, "style"); + sp_repr_css_change(last->getRepr(), stop, "style"); } } break; @@ -710,7 +711,7 @@ void sp_item_gradient_stop_set_style(SPItem *item, guint point_type, guint point { SPStop *stopi = sp_get_stop_i (vector, point_i); if (stopi) { - sp_repr_css_change (SP_OBJECT_REPR (stopi), stop, "style"); + sp_repr_css_change(stopi->getRepr(), stop, "style"); } } break; @@ -735,22 +736,22 @@ void sp_item_gradient_reverse_vector(SPItem *item, bool fill_or_stroke) vector = sp_gradient_fork_vector_if_necessary (vector); if ( gradient != vector && gradient->ref->getObject() != vector ) { - sp_gradient_repr_set_link(SP_OBJECT_REPR(gradient), vector); + sp_gradient_repr_set_link(gradient->getRepr(), vector); } GSList *child_reprs = NULL; GSList *child_objects = NULL; std::vector offsets; for ( SPObject *child = vector->firstChild(); child; child = child->getNext()) { - child_reprs = g_slist_prepend (child_reprs, SP_OBJECT_REPR(child)); + child_reprs = g_slist_prepend (child_reprs, child->getRepr()); child_objects = g_slist_prepend (child_objects, child); - offsets.push_back(sp_repr_get_double_attribute(SP_OBJECT_REPR(child), "offset", 0)); + offsets.push_back(sp_repr_get_double_attribute(child->getRepr(), "offset", 0)); } GSList *child_copies = NULL; for (GSList *i = child_reprs; i != NULL; i = i->next) { Inkscape::XML::Node *repr = (Inkscape::XML::Node *) i->data; - Inkscape::XML::Document *xml_doc = SP_OBJECT_REPR(vector)->document(); + Inkscape::XML::Document *xml_doc = vector->getRepr()->document(); child_copies = g_slist_append (child_copies, repr->duplicate(xml_doc)); } @@ -796,7 +797,7 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i, p *= (gradient->gradientTransform).inverse(); // now p is in gradient's original coordinates - Inkscape::XML::Node *repr = SP_OBJECT_REPR(gradient); + Inkscape::XML::Node *repr = gradient->getRepr(); if (SP_IS_LINEARGRADIENT(gradient)) { SPLinearGradient *lg = SP_LINEARGRADIENT(gradient); @@ -816,7 +817,7 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i, sp_repr_set_svg_double(repr, "x1", lg->x1.computed); sp_repr_set_svg_double(repr, "y1", lg->y1.computed); } else { - SP_OBJECT (gradient)->requestModified(SP_OBJECT_MODIFIED_FLAG); + gradient->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; case POINT_LG_END: @@ -834,7 +835,7 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i, sp_repr_set_svg_double(repr, "x2", lg->x2.computed); sp_repr_set_svg_double(repr, "y2", lg->y2.computed); } else { - SP_OBJECT (gradient)->requestModified(SP_OBJECT_MODIFIED_FLAG); + gradient->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; case POINT_LG_MID: @@ -847,9 +848,9 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i, SPStop* stopi = sp_get_stop_i(vector, point_i); stopi->offset = offset; if (write_repr) { - sp_repr_set_css_double(SP_OBJECT_REPR(stopi), "offset", stopi->offset); + sp_repr_set_css_double(stopi->getRepr(), "offset", stopi->offset); } else { - SP_OBJECT (stopi)->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); + stopi->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); } } break; @@ -879,7 +880,7 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i, sp_repr_set_svg_double(repr, "cx", rg->cx.computed); sp_repr_set_svg_double(repr, "cy", rg->cy.computed); } else { - SP_OBJECT (gradient)->requestModified(SP_OBJECT_MODIFIED_FLAG); + gradient->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; case POINT_RG_FOCUS: @@ -889,7 +890,7 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i, sp_repr_set_svg_double(repr, "fx", rg->fx.computed); sp_repr_set_svg_double(repr, "fy", rg->fy.computed); } else { - SP_OBJECT (gradient)->requestModified(SP_OBJECT_MODIFIED_FLAG); + gradient->requestModified(SP_OBJECT_MODIFIED_FLAG); } break; case POINT_RG_R1: @@ -941,9 +942,9 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i, SPStop* stopi = sp_get_stop_i(vector, point_i); stopi->offset = offset; if (write_repr) { - sp_repr_set_css_double(SP_OBJECT_REPR(stopi), "offset", stopi->offset); + sp_repr_set_css_double(stopi->getRepr(), "offset", stopi->offset); } else { - SP_OBJECT (stopi)->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); + stopi->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); } break; } @@ -957,9 +958,9 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i, SPStop* stopi = sp_get_stop_i(vector, point_i); stopi->offset = offset; if (write_repr) { - sp_repr_set_css_double(SP_OBJECT_REPR(stopi), "offset", stopi->offset); + sp_repr_set_css_double(stopi->getRepr(), "offset", stopi->offset); } else { - SP_OBJECT (stopi)->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); + stopi->requestModified(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); } break; } @@ -969,10 +970,10 @@ void sp_item_gradient_set_coords(SPItem *item, guint point_type, guint point_i, gradient->gradientTransform_set = TRUE; if (write_repr) { gchar *s=sp_svg_transform_write(gradient->gradientTransform); - SP_OBJECT_REPR(gradient)->setAttribute("gradientTransform", s); + gradient->getRepr()->setAttribute("gradientTransform", s); g_free(s); } else { - SP_OBJECT (gradient)->requestModified(SP_OBJECT_MODIFIED_FLAG); + gradient->requestModified(SP_OBJECT_MODIFIED_FLAG); } } } @@ -1064,7 +1065,7 @@ Geom::Point sp_item_gradient_get_coords(SPItem *item, guint point_type, guint po } if (SP_GRADIENT(gradient)->getUnits() == SP_GRADIENT_UNITS_OBJECTBOUNDINGBOX) { - SP_OBJECT_DOCUMENT(item)->ensureUpToDate(); + item->document->ensureUpToDate(); Geom::OptRect bbox = item->getBounds(Geom::identity()); // we need "true" bbox without item_i2d_affine if (bbox) { p *= Geom::Affine(bbox->dimensions()[Geom::X], 0, @@ -1094,7 +1095,7 @@ SPGradient *sp_item_set_gradient(SPItem *item, SPGradient *gr, SPGradientType ty g_return_val_if_fail(SP_IS_GRADIENT(gr), NULL); g_return_val_if_fail(gr->state == SP_GRADIENT_STATE_VECTOR, NULL); - SPStyle *style = SP_OBJECT_STYLE(item); + SPStyle *style = item->style; g_assert(style != NULL); SPPaintServer *ps = NULL; @@ -1109,20 +1110,20 @@ SPGradient *sp_item_set_gradient(SPItem *item, SPGradient *gr, SPGradientType ty /* Current fill style is the gradient of the required type */ SPGradient *current = SP_GRADIENT(ps); - //g_message("hrefcount %d count %d\n", current->hrefcount, count_gradient_hrefs(SP_OBJECT(item), current)); + //g_message("hrefcount %d count %d\n", current->hrefcount, count_gradient_hrefs(item, current)); if (!current->isSwatch() && (current->hrefcount == 1 || - current->hrefcount == count_gradient_hrefs(SP_OBJECT(item), current))) { + current->hrefcount == count_gradient_hrefs(item, current))) { // current is private and it's either used once, or all its uses are by children of item; // so just change its href to vector if ( current != gr && current->getVector() != gr ) { - /* href is not the vector */ - sp_gradient_repr_set_link(SP_OBJECT_REPR(current), gr); + // href is not the vector + sp_gradient_repr_set_link(current->getRepr(), gr); } - SP_OBJECT(item)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); + item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); return current; } else { @@ -1137,19 +1138,19 @@ SPGradient *sp_item_set_gradient(SPItem *item, SPGradient *gr, SPGradientType ty /* We have to change object style here; recursive because this is used from * fill&stroke and must work for groups etc. */ - sp_style_set_property_url(SP_OBJECT(item), is_fill? "fill" : "stroke", SP_OBJECT(normalized), true); + sp_style_set_property_url(item, is_fill? "fill" : "stroke", normalized, true); } - SP_OBJECT(item)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); + item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); return normalized; } } else { /* Current fill style is not a gradient or wrong type, so construct everything */ - SPGradient *constructed = sp_gradient_get_private_normalized(SP_OBJECT_DOCUMENT(item), gr, type); + SPGradient *constructed = sp_gradient_get_private_normalized(item->document, gr, type); constructed = sp_gradient_reset_to_userspace(constructed, item); - sp_style_set_property_url(SP_OBJECT(item), ( is_fill ? "fill" : "stroke" ), SP_OBJECT(constructed), true); - SP_OBJECT(item)->requestDisplayUpdate(( SP_OBJECT_MODIFIED_FLAG | - SP_OBJECT_STYLE_MODIFIED_FLAG )); + sp_style_set_property_url(item, ( is_fill ? "fill" : "stroke" ), constructed, true); + item->requestDisplayUpdate(( SP_OBJECT_MODIFIED_FLAG | + SP_OBJECT_STYLE_MODIFIED_FLAG )); return constructed; } } @@ -1216,7 +1217,7 @@ SPGradient *sp_document_default_gradient_vector( SPDocument *document, SPColor c addStop( repr, colorStr, 0, "1" ); } - SP_OBJECT_REPR(defs)->addChild(repr, NULL); + defs->getRepr()->addChild(repr, NULL); Inkscape::GC::release(repr); /* fixme: This does not look like nice */ @@ -1237,11 +1238,11 @@ SPGradient *sp_gradient_vector_for_object( SPDocument *const doc, SPDesktop *con SPObject *const o, bool const is_fill, bool singleStop ) { SPColor color; - if (o == NULL || SP_OBJECT_STYLE(o) == NULL) { + if ( (o == NULL) || (o->style == NULL) ) { color = sp_desktop_get_color(desktop, is_fill); } else { // take the color of the object - SPStyle const &style = *SP_OBJECT_STYLE(o); + SPStyle const &style = *(o->style); SPIPaint const &paint = ( is_fill ? style.fill : style.stroke ); diff --git a/src/gradient-context.cpp b/src/gradient-context.cpp index d37e9b022..b98ae09fc 100644 --- a/src/gradient-context.cpp +++ b/src/gradient-context.cpp @@ -377,9 +377,9 @@ sp_gradient_context_add_stops_between_selected_stops (SPGradientContext *rc) SPStop *this_stop = (SPStop *) i->data; SPStop *next_stop = (SPStop *) j->data; gfloat offset = 0.5*(this_stop->offset + next_stop->offset); - SPObject *parent = SP_OBJECT_PARENT(this_stop); + SPObject *parent = this_stop->parent; if (SP_IS_GRADIENT (parent)) { - doc = SP_OBJECT_DOCUMENT (parent); + doc = parent->document; sp_vector_add_stop (SP_GRADIENT (parent), this_stop, next_stop, offset); SP_GRADIENT(parent)->ensureVector(); } @@ -448,9 +448,9 @@ sp_gradient_simplify(SPGradientContext *rc, double tolerance) for (i = todel; i != NULL; i = i->next) { SPStop *stop = (SPStop*) i->data; - doc = SP_OBJECT_DOCUMENT (stop); - Inkscape::XML::Node * parent = SP_OBJECT_REPR(stop)->parent(); - parent->removeChild(SP_OBJECT_REPR(stop)); + doc = stop->document; + Inkscape::XML::Node * parent = stop->getRepr()->parent(); + parent->removeChild( stop->getRepr() ); } if (g_slist_length(todel) > 0) { @@ -524,7 +524,7 @@ sp_gradient_context_root_handler(SPEventContext *event_context, GdkEvent *event) SPGradientType new_type = (SPGradientType) prefs->getInt("/tools/gradient/newgradient", SP_GRADIENT_TYPE_LINEAR); guint new_fill = prefs->getInt("/tools/gradient/newfillorstroke", 1); - SPGradient *vector = sp_gradient_vector_for_object(sp_desktop_document(desktop), desktop, SP_OBJECT (item), new_fill); + SPGradient *vector = sp_gradient_vector_for_object(sp_desktop_document(desktop), desktop, item, new_fill); SPGradient *priv = sp_item_set_gradient(item, vector, new_type, new_fill); sp_gradient_reset_to_userspace(priv, item); @@ -902,7 +902,7 @@ static void sp_gradient_drag(SPGradientContext &rc, Geom::Point const pt, guint for (GSList const *i = selection->itemList(); i != NULL; i = i->next) { //FIXME: see above - sp_repr_css_change_recursive(SP_OBJECT_REPR(i->data), css, "style"); + sp_repr_css_change_recursive(SP_OBJECT(i->data)->getRepr(), css, "style"); sp_item_set_gradient(SP_ITEM(i->data), vector, (SPGradientType) type, fill_or_stroke); @@ -913,7 +913,7 @@ static void sp_gradient_drag(SPGradientContext &rc, Geom::Point const pt, guint sp_item_gradient_set_coords (SP_ITEM(i->data), POINT_RG_CENTER, 0, rc.origin, fill_or_stroke, true, false); sp_item_gradient_set_coords (SP_ITEM(i->data), POINT_RG_R1, 0, pt, fill_or_stroke, true, false); } - SP_OBJECT (i->data)->requestModified(SP_OBJECT_MODIFIED_FLAG); + SP_OBJECT(i->data)->requestModified(SP_OBJECT_MODIFIED_FLAG); } if (ec->_grdrag) { ec->_grdrag->updateDraggers(); diff --git a/src/gradient-drag.cpp b/src/gradient-drag.cpp index fe8297286..8f7effe43 100644 --- a/src/gradient-drag.cpp +++ b/src/gradient-drag.cpp @@ -450,7 +450,7 @@ GrDrag::dropColor(SPItem */*item*/, gchar const *c, Geom::Point p) SPCSSAttr *css = sp_repr_css_attr_new (); sp_repr_css_set_property( css, "stop-color", stopIsNull ? 0 : toUse.c_str() ); sp_repr_css_set_property( css, "stop-opacity", "1" ); - sp_repr_css_change (SP_OBJECT_REPR (stop), css, "style"); + sp_repr_css_change(stop->getRepr(), css, "style"); return true; } } @@ -960,7 +960,7 @@ gr_knot_clicked_handler(SPKnot */*knot*/, guint state, gpointer data) SPStop *next = stop->getNextStop(); if (next) { next->offset = 0; - sp_repr_set_css_double (SP_OBJECT_REPR (next), "offset", 0); + sp_repr_set_css_double(next->getRepr(), "offset", 0); } } break; @@ -972,7 +972,7 @@ gr_knot_clicked_handler(SPKnot */*knot*/, guint state, gpointer data) SPStop *prev = stop->getPrevStop(); if (prev) { prev->offset = 1; - sp_repr_set_css_double (SP_OBJECT_REPR (prev), "offset", 1); + sp_repr_set_css_double(prev->getRepr(), "offset", 1); } } break; @@ -983,8 +983,8 @@ gr_knot_clicked_handler(SPKnot */*knot*/, guint state, gpointer data) break; } - SP_OBJECT_REPR(gradient)->removeChild(SP_OBJECT_REPR(stop)); - DocumentUndo::done(SP_OBJECT_DOCUMENT (gradient), SP_VERB_CONTEXT_GRADIENT, + gradient->getRepr()->removeChild(stop->getRepr()); + DocumentUndo::done(gradient->document, SP_VERB_CONTEXT_GRADIENT, _("Delete gradient stop")); } } else { @@ -1745,7 +1745,7 @@ GrDrag::updateLines () SPItem *item = SP_ITEM(i->data); - SPStyle *style = SP_OBJECT_STYLE (item); + SPStyle *style = item->style; if (style && (style->fill.isPaintserver())) { SPPaintServer *server = item->style->getFillPaintServer(); @@ -2038,14 +2038,14 @@ GrDrag::deleteSelected (bool just_one) } while (midstoplist) { SPStop *stop = (SPStop*) midstoplist->data; - document = SP_OBJECT_DOCUMENT (stop); - Inkscape::XML::Node * parent = SP_OBJECT_REPR(stop)->parent(); - parent->removeChild(SP_OBJECT_REPR(stop)); + document = stop->document; + Inkscape::XML::Node * parent = stop->getRepr()->parent(); + parent->removeChild(stop->getRepr()); midstoplist = g_slist_remove(midstoplist, stop); } while (endstoplist) { StructStopInfo *stopinfo = (StructStopInfo*) endstoplist->data; - document = SP_OBJECT_DOCUMENT (stopinfo->spstop); + document = stopinfo->spstop->document; // 2 is the minimum, cannot delete more than that without deleting the whole vector // cannot use vector->vector.stops.size() because the vector might be invalidated by deletion of a midstop @@ -2062,7 +2062,7 @@ GrDrag::deleteSelected (bool just_one) switch (stopinfo->draggable->point_type) { case POINT_LG_BEGIN: { - SP_OBJECT_REPR(stopinfo->vector)->removeChild(SP_OBJECT_REPR(stopinfo->spstop)); + stopinfo->vector->getRepr()->removeChild(stopinfo->spstop->getRepr()); SPLinearGradient *lg = SP_LINEARGRADIENT(stopinfo->gradient); Geom::Point oldbegin = Geom::Point (lg->x1.computed, lg->y1.computed); @@ -2073,25 +2073,25 @@ GrDrag::deleteSelected (bool just_one) lg->x1.computed = newbegin[Geom::X]; lg->y1.computed = newbegin[Geom::Y]; - Inkscape::XML::Node *repr = SP_OBJECT_REPR(stopinfo->gradient); + Inkscape::XML::Node *repr = stopinfo->gradient->getRepr(); sp_repr_set_svg_double(repr, "x1", lg->x1.computed); sp_repr_set_svg_double(repr, "y1", lg->y1.computed); stop->offset = 0; - sp_repr_set_css_double (SP_OBJECT_REPR (stop), "offset", 0); + sp_repr_set_css_double(stop->getRepr(), "offset", 0); // iterate through midstops to set new offset values such that they won't move on canvas. SPStop *laststop = sp_last_stop(stopinfo->vector); stop = stop->getNextStop(); while ( stop != laststop ) { stop->offset = (stop->offset - offset)/(1 - offset); - sp_repr_set_css_double (SP_OBJECT_REPR (stop), "offset", stop->offset); + sp_repr_set_css_double(stop->getRepr(), "offset", stop->offset); stop = stop->getNextStop(); } } break; case POINT_LG_END: { - SP_OBJECT_REPR(stopinfo->vector)->removeChild(SP_OBJECT_REPR(stopinfo->spstop)); + stopinfo->vector->getRepr()->removeChild(stopinfo->spstop->getRepr()); SPLinearGradient *lg = SP_LINEARGRADIENT(stopinfo->gradient); Geom::Point begin = Geom::Point (lg->x1.computed, lg->y1.computed); @@ -2102,18 +2102,18 @@ GrDrag::deleteSelected (bool just_one) lg->x2.computed = newend[Geom::X]; lg->y2.computed = newend[Geom::Y]; - Inkscape::XML::Node *repr = SP_OBJECT_REPR(stopinfo->gradient); + Inkscape::XML::Node *repr = stopinfo->gradient->getRepr(); sp_repr_set_svg_double(repr, "x2", lg->x2.computed); sp_repr_set_svg_double(repr, "y2", lg->y2.computed); laststop->offset = 1; - sp_repr_set_css_double (SP_OBJECT_REPR (laststop), "offset", 1); + sp_repr_set_css_double(laststop->getRepr(), "offset", 1); // iterate through midstops to set new offset values such that they won't move on canvas. SPStop *stop = stopinfo->vector->getFirstStop(); stop = stop->getNextStop(); while ( stop != laststop ) { stop->offset = stop->offset / offset; - sp_repr_set_css_double (SP_OBJECT_REPR (stop), "offset", stop->offset); + sp_repr_set_css_double(stop->getRepr(), "offset", stop->offset); stop = stop->getNextStop(); } } @@ -2123,14 +2123,14 @@ GrDrag::deleteSelected (bool just_one) SPStop *newfirst = stopinfo->spstop->getNextStop(); if (newfirst) { newfirst->offset = 0; - sp_repr_set_css_double (SP_OBJECT_REPR (newfirst), "offset", 0); + sp_repr_set_css_double(newfirst->getRepr(), "offset", 0); } - SP_OBJECT_REPR(stopinfo->vector)->removeChild(SP_OBJECT_REPR(stopinfo->spstop)); + stopinfo->vector->getRepr()->removeChild(stopinfo->spstop->getRepr()); } break; case POINT_RG_R1: case POINT_RG_R2: - SP_OBJECT_REPR(stopinfo->vector)->removeChild(SP_OBJECT_REPR(stopinfo->spstop)); + stopinfo->vector->getRepr()->removeChild(stopinfo->spstop->getRepr()); SPRadialGradient *rg = SP_RADIALGRADIENT(stopinfo->gradient); double oldradius = rg->r.computed; @@ -2139,17 +2139,17 @@ GrDrag::deleteSelected (bool just_one) double newradius = offset * oldradius; rg->r.computed = newradius; - Inkscape::XML::Node *repr = SP_OBJECT_REPR(rg); + Inkscape::XML::Node *repr = rg->getRepr(); sp_repr_set_svg_double(repr, "r", rg->r.computed); laststop->offset = 1; - sp_repr_set_css_double (SP_OBJECT_REPR (laststop), "offset", 1); + sp_repr_set_css_double(laststop->getRepr(), "offset", 1); // iterate through midstops to set new offset values such that they won't move on canvas. SPStop *stop = stopinfo->vector->getFirstStop(); stop = stop->getNextStop(); while ( stop != laststop ) { stop->offset = stop->offset / offset; - sp_repr_set_css_double (SP_OBJECT_REPR (stop), "offset", stop->offset); + sp_repr_set_css_double(stop->getRepr(), "offset", stop->offset); stop = stop->getNextStop(); } break; @@ -2160,8 +2160,8 @@ GrDrag::deleteSelected (bool just_one) SPCSSAttr *css = sp_repr_css_attr_new (); // stopinfo->spstop is the selected stop - Inkscape::XML::Node *unselectedrepr = SP_OBJECT_REPR(stopinfo->vector)->firstChild(); - if (unselectedrepr == SP_OBJECT_REPR(stopinfo->spstop) ) { + Inkscape::XML::Node *unselectedrepr = stopinfo->vector->getRepr()->firstChild(); + if (unselectedrepr == stopinfo->spstop->getRepr() ) { unselectedrepr = unselectedrepr->next(); } @@ -2183,7 +2183,7 @@ GrDrag::deleteSelected (bool just_one) sp_repr_css_attr_unref (stopcss); } - sp_repr_css_change (SP_OBJECT_REPR (stopinfo->draggable->item), css, "style"); + sp_repr_css_change(stopinfo->draggable->item->getRepr(), css, "style"); sp_repr_css_attr_unref (css); } diff --git a/src/sp-root.cpp b/src/sp-root.cpp index 61b5fda5b..5b0bf4cde 100644 --- a/src/sp-root.cpp +++ b/src/sp-root.cpp @@ -567,7 +567,7 @@ sp_root_modified(SPObject *object, guint flags) /* fixme: (Lauris) */ if (!object->parent && (flags & SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { - SP_OBJECT_DOCUMENT(root)->emitResizedSignal(root->width.computed, root->height.computed); + root->document->emitResizedSignal(root->width.computed, root->height.computed); } } -- cgit v1.2.3 From ccba415bc620a21239f11361078c8c30006106c7 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Sun, 20 Feb 2011 23:59:34 -0800 Subject: Finished cleanup of outated SP_OBJECT_DOCUMENT C macro. (bzr r10060) --- src/knotholder.cpp | 12 +- src/layer-fns.cpp | 47 ++--- src/live_effects/effect.cpp | 18 +- src/live_effects/lpe-line_segment.cpp | 2 +- src/live_effects/lpeobject.cpp | 12 +- src/select-context.cpp | 14 +- src/selection-chemistry.cpp | 104 +++++----- src/seltrans.cpp | 22 +-- src/sp-clippath.cpp | 12 +- src/sp-filter.cpp | 18 +- src/sp-flowtext.cpp | 26 +-- src/sp-font.cpp | 4 +- src/sp-gradient.cpp | 22 +-- src/sp-image.cpp | 18 +- src/sp-item-group.cpp | 93 ++++----- src/sp-mask.cpp | 33 ++-- src/sp-namedview.cpp | 20 +- src/sp-object.h | 1 - src/sp-pattern.cpp | 68 ++++--- src/sp-script.cpp | 9 +- src/sp-shape.cpp | 33 ++-- src/sp-text.cpp | 37 ++-- src/sp-tref.cpp | 78 ++++---- src/spray-context.cpp | 16 +- src/style.cpp | 56 +++--- src/text-context.cpp | 25 ++- src/text-editing.cpp | 347 ++++++++++++++++++++-------------- src/tweak-context.cpp | 34 ++-- src/ui/context-menu.cpp | 22 +-- src/ui/dialog/guides.cpp | 6 +- src/ui/dialog/icon-preview.cpp | 4 +- src/uri-references.cpp | 2 +- src/widgets/gradient-selector.cpp | 12 +- src/widgets/gradient-vector.cpp | 76 ++++---- src/widgets/paint-selector.cpp | 10 +- src/widgets/sp-attribute-widget.cpp | 20 +- src/widgets/stroke-style.cpp | 66 ++++--- src/widgets/swatch-selector.cpp | 6 +- src/widgets/toolbox.cpp | 103 +++++----- 39 files changed, 796 insertions(+), 712 deletions(-) (limited to 'src') diff --git a/src/knotholder.cpp b/src/knotholder.cpp index 5ff42a7c6..59059c2a8 100644 --- a/src/knotholder.cpp +++ b/src/knotholder.cpp @@ -44,7 +44,7 @@ class SPDesktop; KnotHolder::KnotHolder(SPDesktop *desktop, SPItem *item, SPKnotHolderReleasedFunc relhandler) { //XML Tree being used directly here while it shouldn't be... - Inkscape::XML::Node *repr = SP_OBJECT(item)->getRepr(); + Inkscape::XML::Node *repr = item->getRepr(); if (!desktop || !item || !SP_IS_ITEM(item)) { g_print ("Error! Throw an exception, please!\n"); @@ -148,7 +148,7 @@ KnotHolder::knot_clicked_handler(SPKnot *knot, guint state) } // for drag, this is done by ungrabbed_handler, but for click we must do it here - DocumentUndo::done(SP_OBJECT_DOCUMENT(item), object_verb, + DocumentUndo::done(item->document, object_verb, _("Change handle")); } @@ -204,7 +204,7 @@ KnotHolder::knot_ungrabbed_handler(SPKnot */*knot*/) Inkscape::LivePathEffect::Effect *lpe = sp_lpe_item_get_current_lpe(SP_LPE_ITEM(object)); if (lpe) { LivePathEffectObject *lpeobj = lpe->getLPEObj(); - SP_OBJECT(lpeobj)->updateRepr(); + lpeobj->updateRepr(); } } @@ -227,7 +227,7 @@ KnotHolder::knot_ungrabbed_handler(SPKnot */*knot*/) object_verb = SP_VERB_SELECTION_DYNAMIC_OFFSET; } - DocumentUndo::done(SP_OBJECT_DOCUMENT (object), object_verb, + DocumentUndo::done(object->document, object_verb, _("Move handle")); } } @@ -241,8 +241,8 @@ KnotHolder::add(KnotHolderEntity *e) void KnotHolder::add_pattern_knotholder() { - if ((SP_OBJECT(item)->style->fill.isPaintserver()) - && SP_IS_PATTERN(SP_STYLE_FILL_SERVER(SP_OBJECT(item)->style))) + if ((item->style->fill.isPaintserver()) + && SP_IS_PATTERN(item->style->getFillPaintServer())) { PatternKnotHolderEntityXY *entity_xy = new PatternKnotHolderEntityXY(); PatternKnotHolderEntityAngle *entity_angle = new PatternKnotHolderEntityAngle(); diff --git a/src/layer-fns.cpp b/src/layer-fns.cpp index 84f21cd97..3637c11f1 100644 --- a/src/layer-fns.cpp +++ b/src/layer-fns.cpp @@ -51,7 +51,7 @@ SPObject *previous_sibling_layer(SPObject *layer) { using Inkscape::Algorithms::find_last_if; SPObject *sibling(find_last_if( - SP_OBJECT_PARENT(layer)->firstChild(), layer, &is_layer + layer->parent->firstChild(), layer, &is_layer )); return ( sibling != layer ) ? sibling : NULL; @@ -91,16 +91,18 @@ SPObject *last_child_layer(SPObject *layer) { SPObject *last_elder_layer(SPObject *root, SPObject *layer) { using Inkscape::Algorithms::find_last_if; + SPObject *result = 0; while ( layer != root ) { SPObject *sibling(previous_sibling_layer(layer)); if (sibling) { - return sibling; + result = sibling; + break; } - layer = SP_OBJECT_PARENT(layer); + layer = layer->parent; } - return NULL; + return result; } } @@ -114,23 +116,21 @@ SPObject *next_layer(SPObject *root, SPObject *layer) { using std::find_if; g_return_val_if_fail(layer != NULL, NULL); + SPObject *result = 0; - SPObject *sibling(next_sibling_layer(layer)); + SPObject *sibling = next_sibling_layer(layer); if (sibling) { SPObject *descendant(first_descendant_layer(sibling)); if (descendant) { - return descendant; + result = descendant; } else { - return sibling; - } - } else { - SPObject *parent=SP_OBJECT_PARENT(layer); - if ( parent != root ) { - return parent; - } else { - return NULL; + result = sibling; } + } else if ( layer->parent != root ) { + result = layer->parent; } + + return result; } @@ -143,20 +143,21 @@ SPObject *previous_layer(SPObject *root, SPObject *layer) { using Inkscape::Algorithms::find_last_if; g_return_val_if_fail(layer != NULL, NULL); + SPObject *result = 0; - SPObject *child(last_child_layer(layer)); + SPObject *child = last_child_layer(layer); if (child) { - return child; + result = child; } else if ( layer != root ) { - SPObject *sibling(previous_sibling_layer(layer)); + SPObject *sibling = previous_sibling_layer(layer); if (sibling) { - return sibling; + result = sibling; } else { - return last_elder_layer(root, SP_OBJECT_PARENT(layer)); + result = last_elder_layer(root, layer->parent); } } - return NULL; + return result; } /** @@ -168,7 +169,7 @@ SPObject *previous_layer(SPObject *root, SPObject *layer) { * \pre \a root should be either \a layer or an ancestor of it */ SPObject *create_layer(SPObject *root, SPObject *layer, LayerRelativePosition position) { - SPDocument *document=SP_OBJECT_DOCUMENT(root); + SPDocument *document = root->document; static int layer_suffix=1; gchar *id=NULL; @@ -192,9 +193,9 @@ SPObject *create_layer(SPObject *root, SPObject *layer, LayerRelativePosition po } if ( root == layer ) { - SP_OBJECT_REPR(root)->appendChild(repr); + root->getRepr()->appendChild(repr); } else { - Inkscape::XML::Node *layer_repr=SP_OBJECT_REPR(layer); + Inkscape::XML::Node *layer_repr = layer->getRepr(); sp_repr_parent(layer_repr)->addChild(repr, layer_repr); if ( LPOS_BELOW == position ) { diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index f59a38fac..ed0d162ac 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -249,7 +249,7 @@ Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj) } if (neweffect) { - neweffect->readallParameters(SP_OBJECT_REPR(lpeobj)); + neweffect->readallParameters(lpeobj->getRepr()); } return neweffect; @@ -262,7 +262,7 @@ void Effect::createAndApply(const char* name, SPDocument *doc, SPItem *item) Inkscape::XML::Node *repr = xml_doc->createElement("inkscape:path-effect"); repr->setAttribute("effect", name); - SP_OBJECT_REPR(SP_DOCUMENT_DEFS(doc))->addChild(repr, NULL); // adds to and assigns the 'id' attribute + SP_DOCUMENT_DEFS(doc)->getRepr()->addChild(repr, NULL); // adds to and assigns the 'id' attribute const gchar * repr_id = repr->attribute("id"); Inkscape::GC::release(repr); @@ -579,17 +579,17 @@ Effect::newWidget(Gtk::Tooltips * tooltips) } -Inkscape::XML::Node * -Effect::getRepr() +Inkscape::XML::Node *Effect::getRepr() { - return SP_OBJECT_REPR(lpeobj); + return lpeobj->getRepr(); } -SPDocument * -Effect::getSPDoc() +SPDocument *Effect::getSPDoc() { - if (SP_OBJECT_DOCUMENT(lpeobj) == NULL) g_message("Effect::getSPDoc() returns NULL"); - return SP_OBJECT_DOCUMENT(lpeobj); + if (lpeobj->document == NULL) { + g_message("Effect::getSPDoc() returns NULL"); + } + return lpeobj->document; } Parameter * diff --git a/src/live_effects/lpe-line_segment.cpp b/src/live_effects/lpe-line_segment.cpp index df5619002..da30cd32c 100644 --- a/src/live_effects/lpe-line_segment.cpp +++ b/src/live_effects/lpe-line_segment.cpp @@ -47,7 +47,7 @@ LPELineSegment::~LPELineSegment() void LPELineSegment::doBeforeEffect (SPLPEItem *lpeitem) { - lpetool_get_limiting_bbox_corners(SP_OBJECT_DOCUMENT(lpeitem), bboxA, bboxB); + lpetool_get_limiting_bbox_corners(lpeitem->document, bboxA, bboxB); } std::vector diff --git a/src/live_effects/lpeobject.cpp b/src/live_effects/lpeobject.cpp index 389e18d20..1b5ed1d49 100644 --- a/src/live_effects/lpeobject.cpp +++ b/src/live_effects/lpeobject.cpp @@ -125,13 +125,13 @@ LivePathEffectObject::livepatheffect_release(SPObject *object) LivePathEffectObject *lpeobj = LIVEPATHEFFECT(object); - SP_OBJECT_REPR(object)->removeListenerByData(object); + object->getRepr()->removeListenerByData(object); /* - if (SP_OBJECT_DOCUMENT(object)) { + if (object->document) { // Unregister ourselves - sp_document_removeResource(SP_OBJECT_DOCUMENT(object), "livepatheffect", SP_OBJECT(object)); + sp_document_removeResource(object->document, "livepatheffect", object); } if (gradient->ref) { @@ -249,11 +249,11 @@ livepatheffect_on_repr_attr_changed ( Inkscape::XML::Node * /*repr*/, LivePathEffectObject *LivePathEffectObject::fork_private_if_necessary(unsigned int nr_of_allowed_users) { if (hrefcount > nr_of_allowed_users) { - SPDocument *doc = SP_OBJECT_DOCUMENT(this); + SPDocument *doc = this->document; Inkscape::XML::Document *xml_doc = doc->getReprDoc(); - Inkscape::XML::Node *dup_repr = SP_OBJECT_REPR (this)->duplicate(xml_doc); + Inkscape::XML::Node *dup_repr = this->getRepr()->duplicate(xml_doc); - SP_OBJECT_REPR (SP_DOCUMENT_DEFS (doc))->addChild(dup_repr, NULL); + SP_DOCUMENT_DEFS(doc)->getRepr()->addChild(dup_repr, NULL); LivePathEffectObject *lpeobj_new = LIVEPATHEFFECT( doc->getObjectByRepr(dup_repr) ); Inkscape::GC::release(dup_repr); diff --git a/src/select-context.cpp b/src/select-context.cpp index 4d1d06fe3..e6d78975b 100644 --- a/src/select-context.cpp +++ b/src/select-context.cpp @@ -230,11 +230,11 @@ sp_select_context_abort(SPEventContext *event_context) if (sc->item) { // only undo if the item is still valid - if (SP_OBJECT_DOCUMENT( SP_OBJECT(sc->item))) { + if (sc->item->document) { DocumentUndo::undo(sp_desktop_document(desktop)); } - sp_object_unref( SP_OBJECT(sc->item), NULL); + sp_object_unref( sc->item, NULL); } else if (sc->button_press_ctrl) { // NOTE: This is a workaround to a bug. // When the ctrl key is held, sc->item is not defined @@ -286,9 +286,9 @@ sp_select_context_up_one_layer(SPDesktop *desktop) */ SPObject *const current_layer = desktop->currentLayer(); if (current_layer) { - SPObject *const parent = SP_OBJECT_PARENT(current_layer); + SPObject *const parent = current_layer->parent; if ( parent - && ( SP_OBJECT_PARENT(parent) + && ( parent->parent || !( SP_IS_GROUP(current_layer) && ( SPGroup::LAYER == SP_GROUP(current_layer)->layerMode() ) ) ) ) @@ -313,7 +313,7 @@ sp_select_context_item_handler(SPEventContext *event_context, SPItem *item, GdkE tolerance = prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); // make sure we still have valid objects to move around - if (sc->item && SP_OBJECT_DOCUMENT( SP_OBJECT(sc->item))==NULL) { + if (sc->item && sc->item->document == NULL) { sp_select_context_abort(event_context); } @@ -460,7 +460,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) Inkscape::Preferences *prefs = Inkscape::Preferences::get(); // make sure we still have valid objects to move around - if (sc->item && SP_OBJECT_DOCUMENT( SP_OBJECT(sc->item))==NULL) { + if (sc->item && sc->item->document == NULL) { sp_select_context_abort(event_context); } @@ -652,7 +652,7 @@ sp_select_context_root_handler(SPEventContext *event_context, GdkEvent *event) sp_canvas_end_forced_full_redraws(desktop->canvas); if (sc->item) { - sp_object_unref( SP_OBJECT(sc->item), NULL); + sp_object_unref( sc->item, NULL); } sc->item = NULL; } else { diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index 9acacf7d5..5ae4205bb 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -243,7 +243,7 @@ void sp_selection_copy_impl(GSList const *items, GSList **clip, Inkscape::XML::D // Copy item reprs: for (GSList *i = (GSList *) sorted_items; i != NULL; i = i->next) { - sp_selection_copy_one(SP_OBJECT_REPR(i->data), SP_ITEM(i->data)->i2doc_affine(), clip, xml_doc); + sp_selection_copy_one(SP_OBJECT(i->data)->getRepr(), SP_ITEM(i->data)->i2doc_affine(), clip, xml_doc); } *clip = g_slist_reverse(*clip); @@ -412,7 +412,7 @@ void sp_selection_duplicate(SPDesktop *desktop, bool suppressDone) // std::cout << id << " old, its ori: " << orig->getId() << "; will relink:" << new_ids[i] << " to " << new_ids[j] << "\n"; gchar *newref = g_strdup_printf("#%s", new_ids[j]); SPObject *new_clone = doc->getObjectById(new_ids[i]); - SP_OBJECT_REPR(new_clone)->setAttribute("xlink:href", newref); + new_clone->getRepr()->setAttribute("xlink:href", newref); new_clone->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); g_free(newref); } @@ -695,7 +695,7 @@ void sp_selection_ungroup(SPDesktop *desktop) } /* We do not allow ungrouping etc. (lauris) */ - if (strcmp(SP_OBJECT_REPR(group)->name(), "svg:g") && strcmp(SP_OBJECT_REPR(group)->name(), "svg:switch")) { + if (strcmp(group->getRepr()->name(), "svg:g") && strcmp(group->getRepr()->name(), "svg:switch")) { // keep the non-group item in the new selection new_select = g_slist_append(new_select, group); continue; @@ -759,13 +759,13 @@ sp_item_list_common_parent_group(GSList const *items) if (!items) { return NULL; } - SPObject *parent = SP_OBJECT_PARENT(items->data); - /* Strictly speaking this CAN happen, if user selects from Inkscape::XML editor */ + SPObject *parent = SP_OBJECT(items->data)->parent; + // Strictly speaking this CAN happen, if user selects from Inkscape::XML editor if (!SP_IS_GROUP(parent)) { return NULL; } for (items = items->next; items; items = items->next) { - if (SP_OBJECT_PARENT(items->data) != parent) { + if (SP_OBJECT(items->data)->parent != parent) { return NULL; } } @@ -816,7 +816,7 @@ sp_selection_raise(SPDesktop *desktop) return; } - Inkscape::XML::Node *grepr = SP_OBJECT_REPR(group); + Inkscape::XML::Node *grepr = const_cast(group->getRepr()); /* Construct reverse-ordered list of selected children. */ GSList *rev = g_slist_copy((GSList *) items); @@ -838,7 +838,7 @@ sp_selection_raise(SPDesktop *desktop) // AND if it's not one of our selected objects, if (!g_slist_find((GSList *) items, newref)) { // move the selected object after that sibling - grepr->changeOrder(SP_OBJECT_REPR(child), SP_OBJECT_REPR(newref)); + grepr->changeOrder(child->getRepr(), newref->getRepr()); } break; } @@ -910,7 +910,7 @@ sp_selection_lower(SPDesktop *desktop) return; } - Inkscape::XML::Node *grepr = SP_OBJECT_REPR(group); + Inkscape::XML::Node *grepr = const_cast(group->getRepr()); // Determine the common bbox of the selected items. Geom::OptRect selected = enclose_items(items); @@ -935,9 +935,9 @@ sp_selection_lower(SPDesktop *desktop) // move the selected object before that sibling SPObject *put_after = prev_sibling(newref); if (put_after) - grepr->changeOrder(SP_OBJECT_REPR(child), SP_OBJECT_REPR(put_after)); + grepr->changeOrder(child->getRepr(), put_after->getRepr()); else - SP_OBJECT_REPR(child)->setPosition(0); + child->getRepr()->setPosition(0); } break; } @@ -1320,7 +1320,7 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons std::list selboxes = selection->box3DList(persp); // create a new perspective as a copy of the current one and link the selected boxes to it - transf_persp = persp3d_create_xml_element (SP_OBJECT_DOCUMENT(persp), persp->perspective_impl); + transf_persp = persp3d_create_xml_element (persp->document, persp->perspective_impl); for (std::list::iterator b = selboxes.begin(); b != selboxes.end(); ++b) box3d_switch_perspectives(*b, persp, transf_persp); @@ -1381,7 +1381,7 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons * Same for linked offset if we are also moving its source: do not move it. */ if (transform_textpath_with_path || transform_offset_with_source) { // Restore item->transform field from the repr, in case it was changed by seltrans. - SP_OBJECT(item)->readAttr( "transform" ); + item->readAttr( "transform" ); } else if (transform_flowtext_with_frame) { // apply the inverse of the region's transform to the so that the flow remains // the same (even though the output itself gets transformed) @@ -1400,10 +1400,10 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons // transform and its move compensation are both cancelled out. // restore item->transform field from the repr, in case it was changed by seltrans - SP_OBJECT(item)->readAttr( "transform" ); + item->readAttr( "transform" ); // calculate the matrix we need to apply to the clone to cancel its induced transform from its original - Geom::Affine parent2dt = SP_ITEM(SP_OBJECT_PARENT(item))->i2d_affine(); + Geom::Affine parent2dt = SP_ITEM(item->parent)->i2d_affine(); Geom::Affine t = parent2dt * affine * parent2dt.inverse(); Geom::Affine t_inv = t.inverse(); Geom::Affine result = t_inv * item->transform * t; @@ -1417,25 +1417,25 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Affine cons if (prefs_parallel) { Geom::Affine move = result * clone_move * t_inv; - item->doWriteTransform(SP_OBJECT_REPR(item), move, &move, compensate); + item->doWriteTransform(item->getRepr(), move, &move, compensate); } else if (prefs_unmoved) { //if (SP_IS_USE(sp_use_get_original(SP_USE(item)))) // clone_move = Geom::identity(); Geom::Affine move = result * clone_move; - item->doWriteTransform(SP_OBJECT_REPR(item), move, &t, compensate); + item->doWriteTransform(item->getRepr(), move, &t, compensate); } } else { // just apply the result - item->doWriteTransform(SP_OBJECT_REPR(item), result, &t, compensate); + item->doWriteTransform(item->getRepr(), result, &t, compensate); } } else { if (set_i2d) { item->set_i2d_affine(item->i2d_affine() * (Geom::Affine)affine); } - item->doWriteTransform(SP_OBJECT_REPR(item), item->transform, NULL, compensate); + item->doWriteTransform(item->getRepr(), item->transform, NULL, compensate); } // if we're moving the actual object, not just updating the repr, we can transform the @@ -1766,7 +1766,7 @@ struct ListReverse { return make_list(o->firstChild(), NULL); } static Iterator siblings_after(SPObject *o) { - return make_list(SP_OBJECT_PARENT(o)->firstChild(), o); + return make_list(o->parent->firstChild(), o); } static void dispose(Iterator i) { g_slist_free(i); @@ -1897,8 +1897,8 @@ void sp_selection_edit_clip_or_mask(SPDesktop * /*dt*/, bool /*clip*/) for (GSList *i = const_cast(items); i; i= i->next) { SPItem *item = SP_ITEM(i->data); SPObject *search = clip - ? SP_OBJECT(item->clip_ref ? item->clip_ref->getObject() : NULL) - : SP_OBJECT(item->mask_ref ? item->mask_ref->getObject() : NULL); + ? (item->clip_ref ? item->clip_ref->getObject() : NULL) + : item->mask_ref ? item->mask_ref->getObject() : NULL; has_path |= has_path_recursive(search); if (has_path) break; } @@ -1939,7 +1939,7 @@ SPItem *next_item_from_list(SPDesktop *desktop, GSList const *items, GSList *path=NULL; while ( current != root ) { path = g_slist_prepend(path, current); - current = SP_OBJECT_PARENT(current); + current = current->parent; } SPItem *next; @@ -1965,7 +1965,7 @@ SPItem *next_item(SPDesktop *desktop, GSList *path, SPObject *root, if (path) { SPObject *object=reinterpret_cast(path->data); - g_assert(SP_OBJECT_PARENT(object) == root); + g_assert(object->parent == root); if (desktop->isLayer(object)) { found = next_item(desktop, path->next, object, only_in_viewport, inlayer, onlyvisible, onlysensitive); } @@ -2105,7 +2105,7 @@ sp_selection_relink(SPDesktop *desktop) if (!SP_IS_USE(item)) continue; - SP_OBJECT_REPR(item)->setAttribute("xlink:href", newref); + item->getRepr()->setAttribute("xlink:href", newref); item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); relinked = true; } @@ -2215,7 +2215,7 @@ sp_select_clone_original(SPDesktop *desktop) } else if (SP_IS_OFFSET(item) && SP_OFFSET(item)->sourceHref) { original = sp_offset_get_source(SP_OFFSET(item)); } else if (SP_IS_TEXT_TEXTPATH(item)) { - original = sp_textpath_get_path_item(SP_TEXTPATH(SP_OBJECT(item)->firstChild())); + original = sp_textpath_get_path_item(SP_TEXTPATH(item->firstChild())); } else if (SP_IS_FLOWTEXT(item)) { original = SP_FLOWTEXT(item)->get_frame(NULL); // first frame only } else { // it's an object that we don't know what to do with @@ -2228,7 +2228,7 @@ sp_select_clone_original(SPDesktop *desktop) return; } - for (SPObject *o = original; o && !SP_IS_ROOT(o); o = SP_OBJECT_PARENT(o)) { + for (SPObject *o = original; o && !SP_IS_ROOT(o); o = o->parent) { if (SP_IS_DEFS(o)) { desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, _("The object you're trying to select is not visible (it is in <defs>)")); return; @@ -2298,18 +2298,18 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply) items = g_slist_sort(items, (GCompareFunc) sp_object_compare_position); // bottommost object, after sorting - SPObject *parent = SP_OBJECT_PARENT(items->data); + SPObject *parent = SP_OBJECT(items->data)->parent; Geom::Affine parent_transform(SP_ITEM(parent)->i2doc_affine()); // remember the position of the first item - gint pos = SP_OBJECT_REPR(items->data)->position(); + gint pos = SP_OBJECT(items->data)->getRepr()->position(); (void)pos; // TODO check why this was remembered // create a list of duplicates GSList *repr_copies = NULL; for (GSList *i = items; i != NULL; i = i->next) { - Inkscape::XML::Node *dup = (SP_OBJECT_REPR(i->data))->duplicate(xml_doc); + Inkscape::XML::Node *dup = SP_OBJECT(i->data)->getRepr()->duplicate(xml_doc); repr_copies = g_slist_prepend(repr_copies, dup); } @@ -2422,17 +2422,17 @@ sp_selection_tile(SPDesktop *desktop, bool apply) items = g_slist_sort(items, (GCompareFunc) sp_object_compare_position); // bottommost object, after sorting - SPObject *parent = SP_OBJECT_PARENT(items->data); + SPObject *parent = SP_OBJECT(items->data)->parent; Geom::Affine parent_transform(SP_ITEM(parent)->i2doc_affine()); // remember the position of the first item - gint pos = SP_OBJECT_REPR(items->data)->position(); + gint pos = SP_OBJECT(items->data)->getRepr()->position(); // create a list of duplicates GSList *repr_copies = NULL; for (GSList *i = items; i != NULL; i = i->next) { - Inkscape::XML::Node *dup = (SP_OBJECT_REPR(i->data))->duplicate(xml_doc); + Inkscape::XML::Node *dup = SP_OBJECT(i->data)->getRepr()->duplicate(xml_doc); repr_copies = g_slist_prepend(repr_copies, dup); } // restore the z-order after prepends @@ -2477,7 +2477,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply) sp_repr_set_svg_double(rect, "y", min[Geom::Y]); // restore parent and position - SP_OBJECT_REPR(parent)->appendChild(rect); + parent->getRepr()->appendChild(rect); rect->setPosition(pos > 0 ? pos : 0); SPItem *rectangle = (SPItem *) sp_desktop_document(desktop)->getObjectByRepr(rect); @@ -2538,7 +2538,7 @@ void sp_selection_untile(SPDesktop *desktop) pat_transform *= item->transform; for (SPObject *child = pattern->firstChild() ; child != NULL; child = child->next ) { - Inkscape::XML::Node *copy = SP_OBJECT_REPR(child)->duplicate(xml_doc); + Inkscape::XML::Node *copy = child->getRepr()->duplicate(xml_doc); SPItem *i = SP_ITEM(desktop->currentLayer()->appendChildRepr(copy)); // FIXME: relink clones to the new canvas objects @@ -2548,14 +2548,14 @@ void sp_selection_untile(SPDesktop *desktop) doc->ensureUpToDate(); Geom::Affine transform( i->transform * pat_transform ); - i->doWriteTransform(SP_OBJECT_REPR(i), transform); + i->doWriteTransform(i->getRepr(), transform); new_select = g_slist_prepend(new_select, i); } SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_set_property(css, "fill", "none"); - sp_repr_css_change(SP_OBJECT_REPR(item), css, "style"); + sp_repr_css_change(item->getRepr(), css, "style"); } if (!did) { @@ -2676,7 +2676,7 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop) // Create the filename. gchar *const basename = g_strdup_printf("%s-%s-%u.png", document->getName(), - SP_OBJECT_REPR(items->data)->attribute("id"), + SP_OBJECT(items->data)->getRepr()->attribute("id"), current); // Imagemagick is known not to handle spaces in filenames, so we replace anything but letters, // digits, and a few other chars, with "_" @@ -2695,9 +2695,9 @@ void sp_selection_create_bitmap_copy(SPDesktop *desktop) //g_print("%s\n", filepath); // Remember parent and z-order of the topmost one - gint pos = SP_OBJECT_REPR(g_slist_last(items)->data)->position(); - SPObject *parent_object = SP_OBJECT_PARENT(g_slist_last(items)->data); - Inkscape::XML::Node *parent = SP_OBJECT_REPR(parent_object); + gint pos = SP_OBJECT(g_slist_last(items)->data)->getRepr()->position(); + SPObject *parent_object = SP_OBJECT(g_slist_last(items)->data)->parent; + Inkscape::XML::Node *parent = parent_object->getRepr(); // Calculate resolution Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -2894,7 +2894,7 @@ void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_ apply_to_items = g_slist_prepend(apply_to_items, desktop->currentLayer()); for (GSList *i = items; i != NULL; i = i->next) { - Inkscape::XML::Node *dup = (SP_OBJECT_REPR(i->data))->duplicate(xml_doc); + Inkscape::XML::Node *dup = SP_OBJECT(i->data)->getRepr()->duplicate(xml_doc); mask_items = g_slist_prepend(mask_items, dup); SPObject *item = reinterpret_cast(i->data); @@ -2908,7 +2908,7 @@ void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_ } else if (!topmost) { // topmost item is used as a mask, which is applied to other items in a selection GSList *i = items; - Inkscape::XML::Node *dup = (SP_OBJECT_REPR(i->data))->duplicate(xml_doc); + Inkscape::XML::Node *dup = SP_OBJECT(i->data)->getRepr()->duplicate(xml_doc); mask_items = g_slist_prepend(mask_items, dup); if (remove_original) { @@ -2927,7 +2927,7 @@ void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_ items_to_select = g_slist_prepend(items_to_select, i->data); } - Inkscape::XML::Node *dup = (SP_OBJECT_REPR(i->data))->duplicate(xml_doc); + Inkscape::XML::Node *dup = SP_OBJECT(i->data)->getRepr()->duplicate(xml_doc); mask_items = g_slist_prepend(mask_items, dup); if (remove_original) { @@ -2950,8 +2950,8 @@ void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_ GSList *reprs_to_group = NULL; for (GSList *i = apply_to_items ; NULL != i ; i = i->next) { - reprs_to_group = g_slist_prepend(reprs_to_group, SP_OBJECT_REPR(i->data)); - items_to_select = g_slist_remove(items_to_select, i->data); + reprs_to_group = g_slist_prepend(reprs_to_group, SP_OBJECT(i->data)->getRepr()); + items_to_select = g_slist_remove(items_to_select, i->data); } reprs_to_group = g_slist_reverse(reprs_to_group); @@ -2992,7 +2992,7 @@ void sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_ g_slist_free(mask_items_dup); mask_items_dup = NULL; - Inkscape::XML::Node *current = SP_OBJECT_REPR(i->data); + Inkscape::XML::Node *current = SP_OBJECT(i->data)->getRepr(); // Node to apply mask to Inkscape::XML::Node *apply_mask_to = current; @@ -3095,7 +3095,7 @@ void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) { } } - SP_OBJECT_REPR(i->data)->setAttribute(attributeName, "none"); + SP_OBJECT(i->data)->getRepr()->setAttribute(attributeName, "none"); if (ungroup_masked && SP_IS_GROUP(i->data)) { // if we had previously enclosed masked object in group, @@ -3117,7 +3117,7 @@ void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) { GSList *items_to_move = NULL; for ( SPObject *child = obj->firstChild() ; child; child = child->getNext() ) { // Collect all clipped paths and masks within a single group - Inkscape::XML::Node *copy = SP_OBJECT_REPR(child)->duplicate(xml_doc); + Inkscape::XML::Node *copy = SP_OBJECT(child)->getRepr()->duplicate(xml_doc); items_to_move = g_slist_prepend(items_to_move, copy); } @@ -3127,8 +3127,8 @@ void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) { } // remember parent and position of the item to which the clippath/mask was applied - Inkscape::XML::Node *parent = SP_OBJECT_REPR((*it).second)->parent(); - gint pos = SP_OBJECT_REPR((*it).second)->position(); + Inkscape::XML::Node *parent = ((*it).second)->getRepr()->parent(); + gint pos = ((*it).second)->getRepr()->position(); // Iterate through all clipped paths / masks for (GSList *i = items_to_move; NULL != i; i = i->next) { @@ -3144,7 +3144,7 @@ void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) { // transform mask, so it is moved the same spot where mask was applied Geom::Affine transform(mask_item->transform); transform *= (*it).second->transform; - mask_item->doWriteTransform(SP_OBJECT_REPR(mask_item), transform); + mask_item->doWriteTransform(mask_item->getRepr(), transform); } g_slist_free(items_to_move); diff --git a/src/seltrans.cpp b/src/seltrans.cpp index 848c0836a..f05ccaa6b 100644 --- a/src/seltrans.cpp +++ b/src/seltrans.cpp @@ -201,7 +201,7 @@ Inkscape::SelTrans::~SelTrans() } for (unsigned i = 0; i < _items.size(); i++) { - sp_object_unref(SP_OBJECT(_items[i]), NULL); + sp_object_unref(_items[i], NULL); } _items.clear(); @@ -235,7 +235,7 @@ void Inkscape::SelTrans::setCenter(Geom::Point const &p) // Write the new center position into all selected items for (GSList const *l = _desktop->selection->itemList(); l; l = l->next) { - SPItem *it = (SPItem*)SP_OBJECT(l->data); + SPItem *it = SP_ITEM(l->data); it->setCenter(p); // only set the value; updating repr and document_done will be done once, on ungrab } @@ -264,7 +264,7 @@ void Inkscape::SelTrans::grab(Geom::Point const &p, gdouble x, gdouble y, bool s } for (GSList const *l = selection->itemList(); l; l = l->next) { - SPItem *it = (SPItem *)sp_object_ref(SP_OBJECT(l->data), NULL); + SPItem *it = reinterpret_cast(sp_object_ref(SP_ITEM(l->data), NULL)); _items.push_back(it); _items_const.push_back(it); _items_affines.push_back(it->i2d_affine()); @@ -463,7 +463,7 @@ void Inkscape::SelTrans::ungrab() _updateVolatileState(); for (unsigned i = 0; i < _items.size(); i++) { - sp_object_unref(SP_OBJECT(_items[i]), NULL); + sp_object_unref(_items[i], NULL); } sp_canvas_item_hide(_norm); @@ -496,7 +496,7 @@ void Inkscape::SelTrans::ungrab() SPItem *currentItem = _items[i]; if (currentItem->isCenterSet()) { // only if it's already set currentItem->setCenter (_items_centers[i] * _current_relative_affine); - SP_OBJECT(currentItem)->updateRepr(); + currentItem->updateRepr(); } } } @@ -525,8 +525,8 @@ void Inkscape::SelTrans::ungrab() if (_center_is_set) { // we were dragging center; update reprs and commit undoable action for (GSList const *l = _desktop->selection->itemList(); l; l = l->next) { - SPItem *it = (SPItem*)SP_OBJECT(l->data); - SP_OBJECT(it)->updateRepr(); + SPItem *it = SP_ITEM(l->data); + it->updateRepr(); } DocumentUndo::done(sp_desktop_document(_desktop), SP_VERB_CONTEXT_SELECT, _("Set center")); @@ -568,7 +568,7 @@ void Inkscape::SelTrans::stamp() while (l) { SPItem *original_item = SP_ITEM(l->data); - Inkscape::XML::Node *original_repr = SP_OBJECT_REPR(original_item); + Inkscape::XML::Node *original_repr = original_item->getRepr(); // remember the position of the item gint pos = original_repr->position(); @@ -786,9 +786,9 @@ void Inkscape::SelTrans::handleClick(SPKnot */*knot*/, guint state, SPSelTransHa if (state & GDK_SHIFT_MASK) { // Unset the center position for all selected items for (GSList const *l = _desktop->selection->itemList(); l; l = l->next) { - SPItem *it = (SPItem*)(SP_OBJECT(l->data)); + SPItem *it = SP_ITEM(l->data); it->unsetCenter(); - SP_OBJECT(it)->updateRepr(); + it->updateRepr(); _center_is_set = false; // center has changed _updateHandles(); } @@ -835,7 +835,7 @@ void Inkscape::SelTrans::handleNewEvent(SPKnot *knot, Geom::Point *position, gui // in case items have been unhooked from the document, don't // try to continue processing events for them. for (unsigned int i = 0; i < _items.size(); i++) { - if (!SP_OBJECT_DOCUMENT(SP_OBJECT(_items[i])) ) { + if ( !_items[i]->document ) { return; } } diff --git a/src/sp-clippath.cpp b/src/sp-clippath.cpp index 4e6f41a70..be5b9a4d1 100644 --- a/src/sp-clippath.cpp +++ b/src/sp-clippath.cpp @@ -98,9 +98,9 @@ void SPClipPath::build(SPObject *object, SPDocument *document, Inkscape::XML::No void SPClipPath::release(SPObject * object) { - if (SP_OBJECT_DOCUMENT(object)) { - /* Unregister ourselves */ - SP_OBJECT_DOCUMENT(object)->removeResource("clipPath", object); + if (object->document) { + // Unregister ourselves + object->document->removeResource("clipPath", object); } SPClipPath *cp = SP_CLIPPATH(object); @@ -146,7 +146,7 @@ void SPClipPath::childAdded(SPObject *object, Inkscape::XML::Node *child, Inksca ((SPObjectClass *) (SPClipPathClass::static_parent_class))->child_added(object, child, ref); /* Show new object */ - SPObject *ochild = SP_OBJECT_DOCUMENT(object)->getObjectByRepr(child); + SPObject *ochild = object->document->getObjectByRepr(child); if (SP_IS_ITEM(ochild)) { SPClipPath *cp = SP_CLIPPATH(object); for (SPClipPathView *v = cp->display; v != NULL; v = v->next) { @@ -357,7 +357,7 @@ sp_clippath_view_list_remove(SPClipPathView *list, SPClipPathView *view) // Create a mask element (using passed elements), add it to const gchar *SPClipPath::create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform) { - Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document)); + Inkscape::XML::Node *defsrepr = SP_DOCUMENT_DEFS(document)->getRepr(); Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:clipPath"); @@ -374,7 +374,7 @@ const gchar *SPClipPath::create (GSList *reprs, SPDocument *document, Geom::Affi if (NULL != applyTransform) { Geom::Affine transform (item->transform); transform *= (*applyTransform); - item->doWriteTransform(SP_OBJECT_REPR(item), transform); + item->doWriteTransform(item->getRepr(), transform); } } diff --git a/src/sp-filter.cpp b/src/sp-filter.cpp index cfd6253a3..fd4319320 100644 --- a/src/sp-filter.cpp +++ b/src/sp-filter.cpp @@ -99,7 +99,7 @@ sp_filter_class_init(SPFilterClass *klass) static void sp_filter_init(SPFilter *filter) { - filter->href = new SPFilterReference(SP_OBJECT(filter)); + filter->href = new SPFilterReference(filter); filter->href->changedSignal().connect(sigc::bind(sigc::ptr_fun(filter_ref_changed), filter)); filter->x = 0; @@ -152,14 +152,13 @@ sp_filter_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *rep /** * Drops any allocated memory. */ -static void -sp_filter_release(SPObject *object) +static void sp_filter_release(SPObject *object) { SPFilter *filter = SP_FILTER(object); - if (SP_OBJECT_DOCUMENT(object)) { - /* Unregister ourselves */ - SP_OBJECT_DOCUMENT(object)->removeResource("filter", SP_OBJECT(object)); + if (object->document) { + // Unregister ourselves + object->document->removeResource("filter", object); } //TODO: release resources here @@ -404,10 +403,9 @@ filter_ref_changed(SPObject *old_ref, SPObject *ref, SPFilter *filter) filter_ref_modified(ref, 0, filter); } -static void -filter_ref_modified(SPObject */*href*/, guint /*flags*/, SPFilter *filter) +static void filter_ref_modified(SPObject */*href*/, guint /*flags*/, SPFilter *filter) { - SP_OBJECT(filter)->requestModified(SP_OBJECT_MODIFIED_FLAG); + filter->requestModified(SP_OBJECT_MODIFIED_FLAG); } /** @@ -552,7 +550,7 @@ Glib::ustring sp_filter_get_new_result_name(SPFilter *filter) { SPObject *primitive_obj = filter->children; while (primitive_obj) { if (SP_IS_FILTER_PRIMITIVE(primitive_obj)) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR(primitive_obj); + Inkscape::XML::Node *repr = primitive_obj->getRepr(); char const *result = repr->attribute("result"); int index; if (result && sscanf(result, "result%d", &index) == 1) { diff --git a/src/sp-flowtext.cpp b/src/sp-flowtext.cpp index 2db1d8787..d7bc0053f 100644 --- a/src/sp-flowtext.cpp +++ b/src/sp-flowtext.cpp @@ -180,7 +180,7 @@ static void sp_flowtext_update(SPObject *object, SPCtx *ctx, unsigned flags) group->invoke_bbox( &paintbox, Geom::identity(), TRUE); for (SPItemView *v = group->display; v != NULL; v = v->next) { group->_clearFlow(NR_ARENA_GROUP(v->arenaitem)); - nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), SP_OBJECT_STYLE(object)); + nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), object->style); // pass the bbox of the flowtext object as paintbox (used for paintserver fills) group->layout.show(NR_ARENA_GROUP(v->arenaitem), &paintbox); } @@ -201,7 +201,7 @@ static void sp_flowtext_modified(SPObject *object, guint flags) text->invoke_bbox( &paintbox, Geom::identity(), TRUE); for (SPItemView* v = text->display; v != NULL; v = v->next) { text->_clearFlow(NR_ARENA_GROUP(v->arenaitem)); - nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), SP_OBJECT_STYLE(object)); + nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), object->style); text->layout.show(NR_ARENA_GROUP(v->arenaitem), &paintbox); } } @@ -241,7 +241,7 @@ sp_flowtext_set(SPObject *object, unsigned key, gchar const *value) case SP_ATTR_LAYOUT_OPTIONS: { // deprecated attribute, read for backward compatibility only //XML Tree being directly used while it shouldn't be. - SPCSSAttr *opts = sp_repr_css_attr((SP_OBJECT(group))->getRepr(), "inkscape:layoutOptions"); + SPCSSAttr *opts = sp_repr_css_attr(group->getRepr(), "inkscape:layoutOptions"); { gchar const *val = sp_repr_css_property(opts, "justification", NULL); if (val != NULL && !object->style->text_align.set) { @@ -334,7 +334,7 @@ sp_flowtext_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform group->layout.getBoundingBox(bbox, transform); // Add stroke width - SPStyle* style=SP_OBJECT_STYLE (item); + SPStyle* style = item->style; if ( !style->stroke.isNone() ) { double const scale = transform.descrim(); if ( fabs(style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord @@ -366,8 +366,8 @@ sp_flowtext_print(SPItem *item, SPPrintContext *ctx) NRRect dbox; dbox.x0 = 0.0; dbox.y0 = 0.0; - dbox.x1 = SP_OBJECT_DOCUMENT(item)->getWidth(); - dbox.y1 = SP_OBJECT_DOCUMENT(item)->getHeight(); + dbox.x1 = item->document->getWidth(); + dbox.y1 = item->document->getHeight(); Geom::Affine const ctm (item->i2d_affine()); group->layout.print(ctx, &pbox, &dbox, &bbox, ctm); @@ -438,7 +438,7 @@ void SPFlowtext::_buildLayoutInput(SPObject *root, Shape const *exclusion_shape, if (SP_IS_FLOWPARA(root)) { // emulate par-indent with the first char's kern SPObject *t = root; - for ( ; t != NULL && !SP_IS_FLOWTEXT(t); t = SP_OBJECT_PARENT(t)){}; + for ( ; t != NULL && !SP_IS_FLOWTEXT(t); t = t->parent){}; if (SP_IS_FLOWTEXT(t)) { double indent = SP_FLOWTEXT(t)->par_indent; if (indent != 0) { @@ -556,10 +556,10 @@ SPFlowtext::getAsText() SPItem *item = SP_ITEM(this); - Inkscape::XML::Document *xml_doc = SP_OBJECT_DOCUMENT(this)->getReprDoc(); + Inkscape::XML::Document *xml_doc = this->document->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:text"); repr->setAttribute("xml:space", "preserve"); - repr->setAttribute("style", SP_OBJECT_REPR(this)->attribute("style")); + repr->setAttribute("style", this->getRepr()->attribute("style")); Geom::Point anchor_point = this->layout.characterAnchorPoint(this->layout.begin()); sp_repr_set_svg_double(repr, "x", anchor_point[Geom::X]); sp_repr_set_svg_double(repr, "y", anchor_point[Geom::Y]); @@ -695,7 +695,7 @@ bool SPFlowtext::has_internal_frame() { SPItem *frame = get_frame(NULL); - return (frame && SP_OBJECT(this)->isAncestorOf(SP_OBJECT(frame)) && SP_IS_RECT(frame)); + return (frame && this->isAncestorOf(frame) && SP_IS_RECT(frame)); } @@ -718,7 +718,7 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, Inkscape::XML::Node *rect_repr = xml_doc->createElement("svg:rect"); // FIXME: use path!!! after rects are converted to use path region_repr->appendChild(rect_repr); - SPObject *rect = doc->getObjectByRepr(rect_repr); + SPRect *rect = SP_RECT(doc->getObjectByRepr(rect_repr)); p0 *= desktop->dt2doc(); p1 *= desktop->dt2doc(); @@ -731,8 +731,8 @@ SPItem *create_flowtext_with_internal_frame (SPDesktop *desktop, Geom::Point p0, Geom::Coord const w = x1 - x0; Geom::Coord const h = y1 - y0; - sp_rect_position_set(SP_RECT(rect), x0, y0, w, h); - SP_OBJECT(rect)->updateRepr(); + sp_rect_position_set(rect, x0, y0, w, h); + rect->updateRepr(); Inkscape::XML::Node *para_repr = xml_doc->createElement("svg:flowPara"); root_repr->appendChild(para_repr); diff --git a/src/sp-font.cpp b/src/sp-font.cpp index 64f7bd481..852e6ba5d 100644 --- a/src/sp-font.cpp +++ b/src/sp-font.cpp @@ -151,7 +151,7 @@ sp_font_remove_child(SPObject *object, Inkscape::XML::Node *child) static void sp_font_release(SPObject *object) { //SPFont *font = SP_FONT(object); - SP_OBJECT_DOCUMENT(object)->removeResource("font", object); + object->document->removeResource("font", object); if (((SPObjectClass *) parent_class)->release) { ((SPObjectClass *) parent_class)->release(object); @@ -263,7 +263,7 @@ static Inkscape::XML::Node *sp_font_write(SPObject *object, Inkscape::XML::Docum sp_repr_set_svg_double(repr, "vert-origin-y", font->vert_origin_y); sp_repr_set_svg_double(repr, "vert-adv-y", font->vert_adv_y); - if (repr != SP_OBJECT_REPR(object)) { + if (repr != object->getRepr()) { // All the below COPY_ATTR funtions are directly using // the XML Tree while they shouldn't COPY_ATTR(repr, object->getRepr(), "horiz-origin-x"); diff --git a/src/sp-gradient.cpp b/src/sp-gradient.cpp index 06008c083..ad422a6ca 100644 --- a/src/sp-gradient.cpp +++ b/src/sp-gradient.cpp @@ -375,7 +375,7 @@ void SPGradientImpl::classInit(SPGradientClass *klass) */ void SPGradientImpl::init(SPGradient *gr) { - gr->ref = new SPGradientReference(SP_OBJECT(gr)); + gr->ref = new SPGradientReference(gr); gr->ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(SPGradientImpl::gradientRefChanged), gr)); /** \todo @@ -447,9 +447,9 @@ void SPGradientImpl::release(SPObject *object) g_print("Releasing gradient %s\n", object->getId()); #endif - if (SP_OBJECT_DOCUMENT(object)) { - /* Unregister ourselves */ - SP_OBJECT_DOCUMENT(object)->removeResource("gradient", SP_OBJECT(object)); + if (object->document) { + // Unregister ourselves + object->document->removeResource("gradient", object); } if (gradient->ref) { @@ -932,7 +932,7 @@ SPGradientUnits SPGradient::fetchUnits() void sp_gradient_repr_clear_vector(SPGradient *gr) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR(gr); + Inkscape::XML::Node *repr = gr->getRepr(); /* Collect stops from original repr */ GSList *sl = NULL; @@ -962,8 +962,8 @@ sp_gradient_repr_write_vector(SPGradient *gr) g_return_if_fail(gr != NULL); g_return_if_fail(SP_IS_GRADIENT(gr)); - Inkscape::XML::Document *xml_doc = SP_OBJECT_DOCUMENT(gr)->getReprDoc(); - Inkscape::XML::Node *repr = SP_OBJECT_REPR(gr); + Inkscape::XML::Document *xml_doc = gr->document->getReprDoc(); + Inkscape::XML::Node *repr = gr->getRepr(); /* We have to be careful, as vector may be our own, so construct repr list at first */ GSList *cl = NULL; @@ -995,7 +995,7 @@ sp_gradient_repr_write_vector(SPGradient *gr) void SPGradientImpl::gradientRefModified(SPObject */*href*/, guint /*flags*/, SPGradient *gradient) { if ( gradient->invalidateVector() ) { - SP_OBJECT(gradient)->requestModified(SP_OBJECT_MODIFIED_FLAG); + gradient->requestModified(SP_OBJECT_MODIFIED_FLAG); // Conditional to avoid causing infinite loop if there's a cycle in the href chain. } } @@ -1427,7 +1427,7 @@ sp_gradient_set_gs2d_matrix(SPGradient *gr, Geom::Affine const &ctm, } gr->gradientTransform_set = TRUE; - SP_OBJECT(gr)->requestModified(SP_OBJECT_MODIFIED_FLAG); + gr->requestModified(SP_OBJECT_MODIFIED_FLAG); } /* @@ -1689,7 +1689,7 @@ sp_lineargradient_set_position(SPLinearGradient *lg, lg->x2.set(SVGLength::NONE, x2, x2); lg->y2.set(SVGLength::NONE, y2, y2); - SP_OBJECT(lg)->requestModified(SP_OBJECT_MODIFIED_FLAG); + lg->requestModified(SP_OBJECT_MODIFIED_FLAG); } /** @@ -1968,7 +1968,7 @@ sp_radialgradient_set_position(SPRadialGradient *rg, rg->fy.set(SVGLength::NONE, fy, fy); rg->r.set(SVGLength::NONE, r, r); - SP_OBJECT(rg)->requestModified(SP_OBJECT_MODIFIED_FLAG); + rg->requestModified(SP_OBJECT_MODIFIED_FLAG); } /** diff --git a/src/sp-image.cpp b/src/sp-image.cpp index b23c2e161..ed9d84b70 100644 --- a/src/sp-image.cpp +++ b/src/sp-image.cpp @@ -655,9 +655,9 @@ sp_image_release (SPObject *object) { SPImage *image = SP_IMAGE(object); - if (SP_OBJECT_DOCUMENT (object)) { - /* Unregister ourselves */ - SP_OBJECT_DOCUMENT(object)->removeResource("image", SP_OBJECT(object)); + if (object->document) { + // Unregister ourselves + object->document->removeResource("image", object); } if (image->href) { @@ -818,7 +818,7 @@ static void sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags) { SPImage *image = SP_IMAGE(object); - SPDocument *doc = SP_OBJECT_DOCUMENT(object); + SPDocument *doc = object->document; if (((SPObjectClass *) (parent_class))->update) { ((SPObjectClass *) (parent_class))->update (object, ctx, flags); @@ -862,7 +862,7 @@ sp_image_update (SPObject *object, SPCtx *ctx, unsigned int flags) DEBUG_MESSAGE( lcmsFive, "in 's sp_image_update. About to call colorprofile_get_handle()" ); #endif // DEBUG_LCMS guint profIntent = Inkscape::RENDERING_INTENT_UNKNOWN; - cmsHPROFILE prof = Inkscape::colorprofile_get_handle( SP_OBJECT_DOCUMENT( object ), + cmsHPROFILE prof = Inkscape::colorprofile_get_handle( object->document, &profIntent, image->color_profile ); if ( prof ) { @@ -1124,9 +1124,9 @@ sp_image_print (SPItem *item, SPPrintContext *ctx) } if (image->aspect_align == SP_ASPECT_NONE) { - sp_print_image_R8G8B8A8_N(ctx, px, w, h, rs, &t, SP_OBJECT_STYLE (item)); + sp_print_image_R8G8B8A8_N(ctx, px, w, h, rs, &t, item->style); } else { // preserveAspectRatio - sp_print_image_R8G8B8A8_N(ctx, px + image->trimx*pixskip + image->trimy*rs, image->trimwidth, image->trimheight, rs, &t, SP_OBJECT_STYLE(item)); + sp_print_image_R8G8B8A8_N(ctx, px + image->trimx*pixskip + image->trimy*rs, image->trimwidth, image->trimheight, rs, &t, item->style); } } } @@ -1164,7 +1164,7 @@ sp_image_show (SPItem *item, NRArena *arena, unsigned int /*key*/, unsigned int if (image->pixbuf) { int pixskip = gdk_pixbuf_get_n_channels(image->pixbuf) * gdk_pixbuf_get_bits_per_sample(image->pixbuf) / 8; int rs = gdk_pixbuf_get_rowstride(image->pixbuf); - nr_arena_image_set_style(NR_ARENA_IMAGE(ai), SP_OBJECT_STYLE(SP_OBJECT(item))); + nr_arena_image_set_style(NR_ARENA_IMAGE(ai), item->style); if (image->aspect_align == SP_ASPECT_NONE) { nr_arena_image_set_pixels(NR_ARENA_IMAGE(ai), gdk_pixbuf_get_pixels(image->pixbuf), @@ -1315,7 +1315,7 @@ sp_image_update_canvas_image (SPImage *image) for (SPItemView *v = item->display; v != NULL; v = v->next) { int pixskip = gdk_pixbuf_get_n_channels(image->pixbuf) * gdk_pixbuf_get_bits_per_sample(image->pixbuf) / 8; int rs = gdk_pixbuf_get_rowstride(image->pixbuf); - nr_arena_image_set_style(NR_ARENA_IMAGE(v->arenaitem), SP_OBJECT_STYLE(SP_OBJECT(image))); + nr_arena_image_set_style(NR_ARENA_IMAGE(v->arenaitem), image->style); if (image->aspect_align == SP_ASPECT_NONE) { nr_arena_image_set_pixels(NR_ARENA_IMAGE(v->arenaitem), gdk_pixbuf_get_pixels(image->pixbuf), diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index bdc9400cf..a31961d2e 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -156,7 +156,7 @@ static void sp_group_build(SPObject *object, SPDocument *document, Inkscape::XML static void sp_group_release(SPObject *object) { if ( SP_GROUP(object)->_layer_mode == SPGroup::LAYER ) { - SP_OBJECT_DOCUMENT(object)->removeResource("layer", object); + object->document->removeResource("layer", object); } if (((SPObjectClass *)parent_class)->release) { ((SPObjectClass *)parent_class)->release(object); @@ -344,20 +344,20 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) g_return_if_fail (group != NULL); g_return_if_fail (SP_IS_GROUP (group)); - SPDocument *doc = SP_OBJECT_DOCUMENT (group); + SPDocument *doc = group->document; SPObject *root = doc->getRoot(); - SPObject *defs = SP_OBJECT (SP_ROOT (root)->defs); + SPObject *defs = SP_OBJECT(SP_ROOT(root)->defs); SPItem *gitem = SP_ITEM (group); - Inkscape::XML::Node *grepr = SP_OBJECT_REPR (gitem); + Inkscape::XML::Node *grepr = gitem->getRepr(); g_return_if_fail (!strcmp (grepr->name(), "svg:g") || !strcmp (grepr->name(), "svg:a") || !strcmp (grepr->name(), "svg:switch")); // this converts the gradient/pattern fill/stroke on the group, if any, to userSpaceOnUse gitem->adjust_paint_recursive (Geom::identity(), Geom::identity(), false); - SPItem *pitem = SP_ITEM (SP_OBJECT_PARENT (gitem)); - Inkscape::XML::Node *prepr = SP_OBJECT_REPR (pitem); + SPItem *pitem = SP_ITEM(gitem->parent); + Inkscape::XML::Node *prepr = pitem->getRepr(); if (SP_IS_BOX3D(gitem)) { group = box3d_convert_to_group(SP_BOX3D(gitem)); @@ -380,7 +380,7 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) // it here _before_ the new transform is set, so as to use the pre-transform bbox citem->adjust_paint_recursive (Geom::identity(), Geom::identity(), false); - sp_style_merge_from_dying_parent(SP_OBJECT_STYLE(child), SP_OBJECT_STYLE(gitem)); + sp_style_merge_from_dying_parent(child->style, gitem->style); /* * fixme: We currently make no allowance for the case where child is cloned * and the group has any style settings. @@ -405,33 +405,33 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) child->updateRepr(); - Inkscape::XML::Node *nrepr = SP_OBJECT_REPR (child)->duplicate(prepr->document()); + Inkscape::XML::Node *nrepr = child->getRepr()->duplicate(prepr->document()); // Merging transform Geom::Affine ctrans; Geom::Affine const g(gitem->transform); if (SP_IS_USE(citem) && sp_use_get_original (SP_USE(citem)) && - SP_OBJECT_PARENT (sp_use_get_original (SP_USE(citem))) == SP_OBJECT(group)) { + sp_use_get_original( SP_USE(citem) )->parent == SP_OBJECT(group)) { // make sure a clone's effective transform is the same as was under group ctrans = g.inverse() * citem->transform * g; } else { - // We should not apply the group's transformation to both a linked offset AND to its source - if (SP_IS_OFFSET(citem)) { // Do we have an offset at hand (whether it's dynamic or linked)? - SPItem *source = sp_offset_get_source(SP_OFFSET(citem)); - // When dealing with a chain of linked offsets, the transformation of an offset will be - // tied to the transformation of the top-most source, not to any of the intermediate - // offsets. So let's find the top-most source - while (source != NULL && SP_IS_OFFSET(source)) { - source = sp_offset_get_source(SP_OFFSET(source)); - } - if (source != NULL && // If true then we must be dealing with a linked offset ... - SP_OBJECT(group)->isAncestorOf(SP_OBJECT(source)) == false) { // ... of which the source is not in the same group - ctrans = citem->transform * g; // then we should apply the transformation of the group to the offset - } else { - ctrans = citem->transform; - } + // We should not apply the group's transformation to both a linked offset AND to its source + if (SP_IS_OFFSET(citem)) { // Do we have an offset at hand (whether it's dynamic or linked)? + SPItem *source = sp_offset_get_source(SP_OFFSET(citem)); + // When dealing with a chain of linked offsets, the transformation of an offset will be + // tied to the transformation of the top-most source, not to any of the intermediate + // offsets. So let's find the top-most source + while (source != NULL && SP_IS_OFFSET(source)) { + source = sp_offset_get_source(SP_OFFSET(source)); + } + if (source != NULL && // If true then we must be dealing with a linked offset ... + group->isAncestorOf(source) == false) { // ... of which the source is not in the same group + ctrans = citem->transform * g; // then we should apply the transformation of the group to the offset + } else { + ctrans = citem->transform; + } } else { - ctrans = citem->transform * g; + ctrans = citem->transform * g; } } @@ -452,27 +452,28 @@ sp_item_group_ungroup (SPGroup *group, GSList **children, bool do_done) items = g_slist_prepend (items, nrepr); } else { - Inkscape::XML::Node *nrepr = SP_OBJECT_REPR (child)->duplicate(prepr->document()); + Inkscape::XML::Node *nrepr = child->getRepr()->duplicate(prepr->document()); objects = g_slist_prepend (objects, nrepr); } } /* Step 2 - clear group */ // remember the position of the group - gint pos = SP_OBJECT_REPR(group)->position(); + gint pos = group->getRepr()->position(); // the group is leaving forever, no heir, clones should take note; its children however are going to reemerge - SP_OBJECT (group)->deleteObject(true, false); + group->deleteObject(true, false); /* Step 3 - add nonitems */ if (objects) { - Inkscape::XML::Node *last_def = SP_OBJECT_REPR(defs)->lastChild(); + Inkscape::XML::Node *last_def = defs->getRepr()->lastChild(); while (objects) { - Inkscape::XML::Node *repr = (Inkscape::XML::Node *) objects->data; - if (!sp_repr_is_meta_element(repr)) - SP_OBJECT_REPR(defs)->addChild(repr, last_def); - Inkscape::GC::release(repr); - objects = g_slist_remove (objects, objects->data); + Inkscape::XML::Node *repr = (Inkscape::XML::Node *) objects->data; + if (!sp_repr_is_meta_element(repr)) { + defs->getRepr()->addChild(repr, last_def); + } + Inkscape::GC::release(repr); + objects = g_slist_remove (objects, objects->data); } } @@ -534,9 +535,9 @@ SPObject *sp_item_group_get_child_by_name(SPGroup *group, SPObject *ref, const g void SPGroup::setLayerMode(LayerMode mode) { if ( _layer_mode != mode ) { if ( mode == LAYER ) { - SP_OBJECT_DOCUMENT(this)->addResource("layer", this); + this->document->addResource("layer", this); } else if ( _layer_mode == LAYER ) { - SP_OBJECT_DOCUMENT(this)->removeResource("layer", this); + this->document->removeResource("layer", this); } _layer_mode = mode; _updateLayerMode(); @@ -592,7 +593,7 @@ CGroup::~CGroup() { void CGroup::onChildAdded(Inkscape::XML::Node *child) { SPObject *last_child = _group->lastChild(); - if (last_child && SP_OBJECT_REPR(last_child) == child) { + if (last_child && last_child->getRepr() == child) { // optimization for the common special case where the child is being added at the end SPObject *ochild = last_child; if ( SP_IS_ITEM(ochild) ) { @@ -648,9 +649,9 @@ void CGroup::onUpdate(SPCtx *ctx, unsigned int flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { - SPObject *object = SP_OBJECT(_group); - for (SPItemView *v = SP_ITEM(_group)->display; v != NULL; v = v->next) { - nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), SP_OBJECT_STYLE(object)); + SPObject *object = _group; + for (SPItemView *v = _group->display; v != NULL; v = v->next) { + nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), object->style); } } @@ -679,9 +680,9 @@ void CGroup::onModified(guint flags) { flags &= SP_OBJECT_MODIFIED_CASCADE; if (flags & SP_OBJECT_STYLE_MODIFIED_FLAG) { - SPObject *object = SP_OBJECT(_group); - for (SPItemView *v = SP_ITEM(_group)->display; v != NULL; v = v->next) { - nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), SP_OBJECT_STYLE(object)); + SPObject *object = _group; + for (SPItemView *v = _group->display; v != NULL; v = v->next) { + nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), object->style); } } @@ -746,14 +747,14 @@ gchar *CGroup::getDescription() { NRArenaItem *CGroup::show (NRArena *arena, unsigned int key, unsigned int flags) { NRArenaItem *ai; - SPObject *object = SP_OBJECT(_group); + SPObject *object = _group; ai = NRArenaGroup::create(arena); nr_arena_group_set_transparent(NR_ARENA_GROUP (ai), _group->effectiveLayerMode(key) == SPGroup::LAYER); - nr_arena_group_set_style(NR_ARENA_GROUP(ai), SP_OBJECT_STYLE(object)); + nr_arena_group_set_style(NR_ARENA_GROUP(ai), object->style); _showChildren(arena, ai, key, flags); return ai; @@ -863,7 +864,7 @@ sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup, bool write) SP_SHAPE(subitem)->setCurve(c, TRUE); if (write) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR(subitem); + Inkscape::XML::Node *repr = subitem->getRepr(); gchar *str = sp_svg_write_path(c->get_pathvector()); repr->setAttribute("d", str); #ifdef GROUP_VERBOSE diff --git a/src/sp-mask.cpp b/src/sp-mask.cpp index 372dd51da..700efa572 100644 --- a/src/sp-mask.cpp +++ b/src/sp-mask.cpp @@ -111,23 +111,22 @@ sp_mask_build (SPObject *object, SPDocument *document, Inkscape::XML::Node *repr document->addResource("mask", object); } -static void -sp_mask_release (SPObject * object) +static void sp_mask_release (SPObject * object) { - if (SP_OBJECT_DOCUMENT (object)) { - /* Unregister ourselves */ - SP_OBJECT_DOCUMENT(object)->removeResource("mask", object); - } + if (object->document) { + // Unregister ourselves + object->document->removeResource("mask", object); + } - SPMask *cp = SP_MASK (object); - while (cp->display) { - /* We simply unref and let item manage this in handler */ - cp->display = sp_mask_view_list_remove (cp->display, cp->display); - } + SPMask *cp = SP_MASK (object); + while (cp->display) { + // We simply unref and let item manage this in handler + cp->display = sp_mask_view_list_remove (cp->display, cp->display); + } - if (((SPObjectClass *) (parent_class))->release) { - ((SPObjectClass *) parent_class)->release (object); - } + if (((SPObjectClass *) (parent_class))->release) { + ((SPObjectClass *) parent_class)->release (object); + } } static void @@ -176,7 +175,7 @@ sp_mask_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML ((SPObjectClass *) (parent_class))->child_added (object, child, ref); /* Show new object */ - SPObject *ochild = SP_OBJECT_DOCUMENT (object)->getObjectByRepr(child); + SPObject *ochild = object->document->getObjectByRepr(child); if (SP_IS_ITEM (ochild)) { SPMask *cp = SP_MASK (object); for (SPMaskView *v = cp->display; v != NULL; v = v->next) { @@ -269,7 +268,7 @@ sp_mask_write (SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML const gchar * sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTransform) { - Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document)); + Inkscape::XML::Node *defsrepr = SP_DOCUMENT_DEFS(document)->getRepr(); Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:mask"); @@ -286,7 +285,7 @@ sp_mask_create (GSList *reprs, SPDocument *document, Geom::Affine const* applyTr if (NULL != applyTransform) { Geom::Affine transform (item->transform); transform *= (*applyTransform); - item->doWriteTransform(SP_OBJECT_REPR(item), transform); + item->doWriteTransform(item->getRepr(), transform); } } diff --git a/src/sp-namedview.cpp b/src/sp-namedview.cpp index 59ef4762d..001f7731f 100644 --- a/src/sp-namedview.cpp +++ b/src/sp-namedview.cpp @@ -269,7 +269,7 @@ static void sp_namedview_build(SPObject *object, SPDocument *document, Inkscape: object->readAttr( "inkscape:connector-spacing" ); /* Construct guideline list */ - for (SPObject *o = SP_OBJECT(og)->firstChild() ; o; o = o->getNext() ) { + for (SPObject *o = og->firstChild() ; o; o = o->getNext() ) { if (SP_IS_GUIDE(o)) { SPGuide * g = SP_GUIDE(o); nv->guides = g_slist_prepend(nv->guides, g); @@ -696,7 +696,7 @@ static void sp_namedview_remove_child(SPObject *object, Inkscape::XML::Node *chi } else { GSList **ref = &nv->guides; for ( GSList *iter = nv->guides ; iter ; iter = iter->next ) { - if ( SP_OBJECT_REPR((SPObject *)iter->data) == child ) { + if ( reinterpret_cast(iter->data)->getRepr() == child ) { *ref = iter->next; iter->next = NULL; g_slist_free_1(iter); @@ -714,12 +714,12 @@ static void sp_namedview_remove_child(SPObject *object, Inkscape::XML::Node *chi static Inkscape::XML::Node *sp_namedview_write(SPObject *object, Inkscape::XML::Document *doc, Inkscape::XML::Node *repr, guint flags) { if ( ( flags & SP_OBJECT_WRITE_EXT ) && - repr != SP_OBJECT_REPR(object) ) + repr != object->getRepr() ) { if (repr) { - repr->mergeFrom(SP_OBJECT_REPR(object), "id"); + repr->mergeFrom(object->getRepr(), "id"); } else { - repr = SP_OBJECT_REPR(object)->duplicate(doc); + repr = object->getRepr()->duplicate(doc); } } @@ -739,7 +739,7 @@ void SPNamedView::show(SPDesktop *desktop) views = g_slist_prepend(views, desktop); // generate grids specified in SVG: - Inkscape::XML::Node *repr = SP_OBJECT_REPR(this); + Inkscape::XML::Node *repr = this->getRepr(); if (repr) { for (Inkscape::XML::Node * child = repr->firstChild() ; child != NULL; child = child->next() ) { if (!strcmp(child->name(), "inkscape:grid")) { @@ -850,7 +850,7 @@ void sp_namedview_document_from_window(SPDesktop *desktop) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); bool save_geometry_in_file = prefs->getBool("/options/savewindowgeometry/value", 0); - Inkscape::XML::Node *view = SP_OBJECT_REPR(desktop->namedview); + Inkscape::XML::Node *view = desktop->namedview->getRepr(); Geom::Rect const r = desktop->get_display_area(); // saving window geometry is not undoable @@ -943,8 +943,8 @@ void sp_namedview_show_grids(SPNamedView * namedview, bool show, bool dirty_docu { namedview->grids_visible = show; - SPDocument *doc = SP_OBJECT_DOCUMENT (namedview); - Inkscape::XML::Node *repr = SP_OBJECT_REPR(namedview); + SPDocument *doc = namedview->document; + Inkscape::XML::Node *repr = namedview->getRepr(); bool saved = DocumentUndo::getUndoSensitive(doc); DocumentUndo::setUndoSensitive(doc, false); @@ -962,7 +962,7 @@ gchar const *SPNamedView::getName() const { SPException ex; SP_EXCEPTION_INIT(&ex); - return SP_OBJECT(this)->getAttribute("id", &ex); + return this->getAttribute("id", &ex); } guint SPNamedView::getViewCount() diff --git a/src/sp-object.h b/src/sp-object.h index 8581fd35a..094ad5bb0 100644 --- a/src/sp-object.h +++ b/src/sp-object.h @@ -56,7 +56,6 @@ class SPObjectClass; /* Convenience stuff */ #define SP_OBJECT_REPR(o) (((SPObject *) (o))->getRepr()) -#define SP_OBJECT_DOCUMENT(o) (((SPObject *) (o))->document) #define SP_OBJECT_PARENT(o) (((SPObject *) (o))->parent) #define SP_OBJECT_STYLE(o) (((SPObject *) (o))->style) diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp index b0264ad13..cd2e706f0 100644 --- a/src/sp-pattern.cpp +++ b/src/sp-pattern.cpp @@ -128,7 +128,7 @@ sp_pattern_class_init (SPPatternClass *klass) static void sp_pattern_init (SPPattern *pat) { - pat->ref = new SPPatternReference(SP_OBJECT(pat)); + pat->ref = new SPPatternReference(pat); pat->ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(pattern_ref_changed), pat)); pat->patternUnits = SP_PATTERN_UNITS_OBJECTBOUNDINGBOX; @@ -170,29 +170,27 @@ sp_pattern_build (SPObject *object, SPDocument *document, Inkscape::XML::Node *r document->addResource("pattern", object); } -static void -sp_pattern_release (SPObject *object) +static void sp_pattern_release(SPObject *object) { - SPPattern *pat; + SPPattern *pat = reinterpret_cast(object); - pat = (SPPattern *) object; - - if (SP_OBJECT_DOCUMENT (object)) { - /* Unregister ourselves */ - SP_OBJECT_DOCUMENT (object)->removeResource("pattern", SP_OBJECT (object)); - } + if (object->document) { + // Unregister ourselves + object->document->removeResource("pattern", object); + } - if (pat->ref) { - pat->modified_connection.disconnect(); - pat->ref->detach(); - delete pat->ref; - pat->ref = NULL; - } + if (pat->ref) { + pat->modified_connection.disconnect(); + pat->ref->detach(); + delete pat->ref; + pat->ref = NULL; + } - pat->modified_connection.~connection(); + pat->modified_connection.~connection(); - if (((SPObjectClass *) pattern_parent_class)->release) - ((SPObjectClass *) pattern_parent_class)->release (object); + if (((SPObjectClass *) pattern_parent_class)->release) { + ((SPObjectClass *) pattern_parent_class)->release (object); + } } static void @@ -426,12 +424,12 @@ pattern_ref_changed(SPObject *old_ref, SPObject *ref, SPPattern *pat) /** Gets called when the referenced is changed */ -static void -pattern_ref_modified (SPObject */*ref*/, guint /*flags*/, SPPattern *pattern) +static void pattern_ref_modified (SPObject */*ref*/, guint /*flags*/, SPPattern *pattern) { - if (SP_IS_OBJECT (pattern)) - SP_OBJECT (pattern)->requestModified(SP_OBJECT_MODIFIED_FLAG); - /* Conditional to avoid causing infinite loop if there's a cycle in the href chain. */ + if ( SP_IS_OBJECT(pattern) ) { + pattern->requestModified(SP_OBJECT_MODIFIED_FLAG); + } + // Conditional to avoid causing infinite loop if there's a cycle in the href chain. } @@ -446,7 +444,7 @@ count_pattern_hrefs(SPObject *o, SPPattern *pat) guint i = 0; - SPStyle *style = SP_OBJECT_STYLE(o); + SPStyle *style = o->style; if (style && style->fill.isPaintserver() && SP_IS_PATTERN(SP_STYLE_FILL_SERVER(style)) @@ -471,13 +469,13 @@ count_pattern_hrefs(SPObject *o, SPPattern *pat) SPPattern *pattern_chain(SPPattern *pattern) { - SPDocument *document = SP_OBJECT_DOCUMENT (pattern); + SPDocument *document = pattern->document; Inkscape::XML::Document *xml_doc = document->getReprDoc(); - Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document)); + Inkscape::XML::Node *defsrepr = SP_DOCUMENT_DEFS(document)->getRepr(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:pattern"); repr->setAttribute("inkscape:collect", "always"); - gchar *parent_ref = g_strconcat ("#", SP_OBJECT_REPR(pattern)->attribute("id"), NULL); + gchar *parent_ref = g_strconcat("#", pattern->getRepr()->attribute("id"), NULL); repr->setAttribute("xlink:href", parent_ref); g_free (parent_ref); @@ -494,11 +492,11 @@ sp_pattern_clone_if_necessary (SPItem *item, SPPattern *pattern, const gchar *pr { if (!pattern->href || pattern->hrefcount > count_pattern_hrefs(item, pattern)) { pattern = pattern_chain (pattern); - gchar *href = g_strconcat ("url(#", SP_OBJECT_REPR (pattern)->attribute("id"), ")", NULL); + gchar *href = g_strconcat("url(#", pattern->getRepr()->attribute("id"), ")", NULL); SPCSSAttr *css = sp_repr_css_attr_new (); sp_repr_css_set_property (css, property, href); - sp_repr_css_change_recursive (SP_OBJECT_REPR (item), css, "style"); + sp_repr_css_change_recursive(item->getRepr(), css, "style"); } return pattern; } @@ -507,7 +505,7 @@ void sp_pattern_transform_multiply (SPPattern *pattern, Geom::Affine postmul, bool set) { // this formula is for a different interpretation of pattern transforms as described in (*) in sp-pattern.cpp - // for it to work, we also need sp_object_read_attr (SP_OBJECT (item), "transform"); + // for it to work, we also need sp_object_read_attr( item, "transform"); //pattern->patternTransform = premul * item->transform * pattern->patternTransform * item->transform.inverse() * postmul; // otherwise the formula is much simpler @@ -519,14 +517,14 @@ sp_pattern_transform_multiply (SPPattern *pattern, Geom::Affine postmul, bool se pattern->patternTransform_set = TRUE; gchar *c=sp_svg_transform_write(pattern->patternTransform); - SP_OBJECT_REPR(pattern)->setAttribute("patternTransform", c); + pattern->getRepr()->setAttribute("patternTransform", c); g_free(c); } const gchar *pattern_tile(GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Affine transform, Geom::Affine move) { Inkscape::XML::Document *xml_doc = document->getReprDoc(); - Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (SP_DOCUMENT_DEFS (document)); + Inkscape::XML::Node *defsrepr = SP_DOCUMENT_DEFS(document)->getRepr(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:pattern"); repr->setAttribute("patternUnits", "userSpaceOnUse"); @@ -550,8 +548,8 @@ const gchar *pattern_tile(GSList *reprs, Geom::Rect bounds, SPDocument *document dup_transform = Geom::identity(); dup_transform *= move; - copy->doWriteTransform(SP_OBJECT_REPR(copy), dup_transform, NULL, false); - } + copy->doWriteTransform(copy->getRepr(), dup_transform, NULL, false); + } Inkscape::GC::release(repr); return pat_id; diff --git a/src/sp-script.cpp b/src/sp-script.cpp index 3b6a8796d..f18d231b0 100644 --- a/src/sp-script.cpp +++ b/src/sp-script.cpp @@ -90,13 +90,14 @@ sp_script_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *rep static void sp_script_release(SPObject *object) { - if (SP_OBJECT_DOCUMENT(object)) { - /* Unregister ourselves */ - SP_OBJECT_DOCUMENT(object)->removeResource("script", SP_OBJECT(object)); + if (object->document) { + // Unregister ourselves + object->document->removeResource("script", object); } - if (((SPObjectClass *) parent_class)->release) + if (((SPObjectClass *) parent_class)->release) { ((SPObjectClass *) parent_class)->release(object); + } } static void sp_script_update(SPObject */*object*/, SPCtx */*ctx*/, guint /*flags*/) diff --git a/src/sp-shape.cpp b/src/sp-shape.cpp index 59105a1c7..d9a47f76a 100644 --- a/src/sp-shape.cpp +++ b/src/sp-shape.cpp @@ -242,8 +242,7 @@ void SPShape::sp_shape_update(SPObject *object, SPCtx *ctx, unsigned int flags) } if (flags & (SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_VIEWPORT_MODIFIED_FLAG)) { - SPStyle *style; - style = SP_OBJECT_STYLE (object); + SPStyle *style = object->style; if (style->stroke_width.unit == SP_CSS_UNIT_PERCENT) { SPItemCtx *ictx = (SPItemCtx *) ctx; double const aw = 1.0 / NR::expansion(ictx->i2vp); @@ -525,7 +524,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const } case SPItem::RENDERING_BBOX: { // convert the stroke to a path and calculate that path's geometric bbox - SPStyle* style=SP_OBJECT_STYLE (item); + SPStyle* style = item->style; if (!style->stroke.isNone()) { Geom::PathVector *pathv = item_outline(item); if (pathv) { @@ -545,7 +544,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const } default: case SPItem::APPROXIMATE_BBOX: { - SPStyle* style=SP_OBJECT_STYLE (item); + SPStyle* style = item->style; if (!style->stroke.isNone()) { double const scale = transform.descrim(); if ( fabs(style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord @@ -567,7 +566,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const for (unsigned i = 0; i < 2; i++) { // SP_MARKER_LOC and SP_MARKER_LOC_START if ( shape->marker[i] ) { SPMarker* marker = SP_MARKER (shape->marker[i]); - SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); + SPItem* marker_item = sp_item_first_item_child( marker ); if (marker_item) { Geom::Affine tr(sp_shape_marker_get_transform_at_start(pathv.begin()->front())); @@ -594,7 +593,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const for (unsigned i = 0; i < 3; i += 2) { // SP_MARKER_LOC and SP_MARKER_LOC_MID SPMarker* marker = SP_MARKER (shape->marker[i]); if ( !shape->marker[i] ) continue; - SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); + SPItem* marker_item = sp_item_first_item_child( marker ); if ( !marker_item ) continue; for(Geom::PathVector::const_iterator path_it = pathv.begin(); path_it != pathv.end(); ++path_it) { @@ -626,7 +625,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const * there should be a midpoint marker between last segment and closing straight line segment */ SPMarker* marker = SP_MARKER (shape->marker[i]); - SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); + SPItem* marker_item = sp_item_first_item_child( marker ); if (marker_item) { Geom::Affine tr(sp_shape_marker_get_transform(*curve_it1, *curve_it2)); @@ -669,7 +668,7 @@ void SPShape::sp_shape_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const for (unsigned i = 0; i < 4; i += 3) { // SP_MARKER_LOC and SP_MARKER_LOC_END if ( shape->marker[i] ) { SPMarker* marker = SP_MARKER (shape->marker[i]); - SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); + SPItem* marker_item = sp_item_first_item_child( marker ); if (marker_item) { /* Get reference to last curve in the path. @@ -719,7 +718,7 @@ sp_shape_print_invoke_marker_printing(SPObject* obj, Geom::Affine tr, SPStyle* s tr = Geom::Scale(style->stroke_width.computed) * tr; } - SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (marker)); + SPItem* marker_item = sp_item_first_item_child( marker ); tr = marker_item->transform * marker->c2p * tr; Geom::Affine old_tr = marker_item->transform; @@ -749,7 +748,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) gint add_comments = prefs->getBool("/printing/debug/add-label-comments"); if (add_comments) { gchar * comment = g_strdup_printf("begin '%s'", - SP_OBJECT(item)->defaultLabel()); + item->defaultLabel()); sp_print_comment(ctx, comment); g_free(comment); } @@ -758,12 +757,12 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) item->invoke_bbox( &pbox, Geom::identity(), TRUE); dbox.x0 = 0.0; dbox.y0 = 0.0; - dbox.x1 = SP_OBJECT_DOCUMENT (item)->getWidth (); - dbox.y1 = SP_OBJECT_DOCUMENT (item)->getHeight (); + dbox.x1 = item->document->getWidth(); + dbox.y1 = item->document->getHeight(); item->getBboxDesktop (&bbox); Geom::Affine const i2d(item->i2d_affine()); - SPStyle* style = SP_OBJECT_STYLE (item); + SPStyle* style = item->style; if (!style->fill.isNone()) { sp_print_fill (ctx, pathv, &i2d, style, &pbox, &dbox, &bbox); @@ -839,7 +838,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) if (add_comments) { gchar * comment = g_strdup_printf("end '%s'", - SP_OBJECT(item)->defaultLabel()); + item->defaultLabel()); sp_print_comment(ctx, comment); g_free(comment); } @@ -850,7 +849,7 @@ sp_shape_print (SPItem *item, SPPrintContext *ctx) */ NRArenaItem * SPShape::sp_shape_show(SPItem *item, NRArena *arena, unsigned int /*key*/, unsigned int /*flags*/) { - SPObject *object = SP_OBJECT(item); + SPObject *object = item; SPShape *shape = SP_SHAPE(item); NRArenaItem *arenaitem = NRArenaShape::create(arena); @@ -1050,7 +1049,7 @@ sp_shape_set_marker (SPObject *object, unsigned int key, const gchar *value) return; } - SPObject *mrk = sp_css_uri_reference_resolve (SP_OBJECT_DOCUMENT (object), value); + SPObject *mrk = sp_css_uri_reference_resolve(object->document, value); if (mrk != shape->marker[key]) { if (shape->marker[key]) { SPItemView *v; @@ -1110,7 +1109,7 @@ void SPShape::setCurve(SPCurve *curve, unsigned int owner) this->curve = curve->copy(); } } - SP_OBJECT(this)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } /** diff --git a/src/sp-text.cpp b/src/sp-text.cpp index 3abeadaee..57f9dd14e 100644 --- a/src/sp-text.cpp +++ b/src/sp-text.cpp @@ -227,18 +227,18 @@ static void sp_text_update(SPObject *object, SPCtx *ctx, guint flags) // Create temporary list of children GSList *l = NULL; for (SPObject *child = object->firstChild() ; child ; child = child->getNext() ) { - sp_object_ref (SP_OBJECT (child), object); + sp_object_ref(child, object); l = g_slist_prepend (l, child); } l = g_slist_reverse (l); while (l) { - SPObject *child = SP_OBJECT (l->data); + SPObject *child = reinterpret_cast(l->data); // We just built this list, so cast is safe. l = g_slist_remove (l, child); if (cflags || (child->uflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { /* fixme: Do we need transform? */ child->updateDisplay(ctx, cflags); } - sp_object_unref (SP_OBJECT (child), object); + sp_object_unref(child, object); } if (flags & ( SP_OBJECT_STYLE_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG | @@ -253,7 +253,7 @@ static void sp_text_update(SPObject *object, SPCtx *ctx, guint flags) text->invoke_bbox( &paintbox, Geom::identity(), TRUE); for (SPItemView* v = text->display; v != NULL; v = v->next) { text->_clearFlow(NR_ARENA_GROUP(v->arenaitem)); - nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), SP_OBJECT_STYLE(object)); + nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), object->style); // pass the bbox of the text object as paintbox (used for paintserver fills) text->layout.show(NR_ARENA_GROUP(v->arenaitem), &paintbox); } @@ -281,7 +281,7 @@ static void sp_text_modified(SPObject *object, guint flags) text->invoke_bbox( &paintbox, Geom::identity(), TRUE); for (SPItemView* v = text->display; v != NULL; v = v->next) { text->_clearFlow(NR_ARENA_GROUP(v->arenaitem)); - nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), SP_OBJECT_STYLE(object)); + nr_arena_group_set_style(NR_ARENA_GROUP(v->arenaitem), object->style); text->layout.show(NR_ARENA_GROUP(v->arenaitem), &paintbox); } } @@ -289,17 +289,17 @@ static void sp_text_modified(SPObject *object, guint flags) // Create temporary list of children GSList *l = NULL; for (SPObject *child = object->firstChild() ; child ; child = child->getNext() ) { - sp_object_ref (SP_OBJECT (child), object); + sp_object_ref(child, object); l = g_slist_prepend (l, child); } l = g_slist_reverse (l); while (l) { - SPObject *child = SP_OBJECT (l->data); + SPObject *child = reinterpret_cast(l->data); // We just built this list, so cast is safe. l = g_slist_remove (l, child); if (cflags || (child->mflags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG))) { child->emitModified(cflags); } - sp_object_unref (SP_OBJECT (child), object); + sp_object_unref(child, object); } } @@ -337,7 +337,7 @@ static Inkscape::XML::Node *sp_text_write(SPObject *object, Inkscape::XML::Docum continue; } if (SP_IS_STRING(child)) { - SP_OBJECT_REPR(child)->setContent(SP_STRING(child)->string.c_str()); + child->getRepr()->setContent(SP_STRING(child)->string.c_str()); } else { child->updateRepr(flags); } @@ -350,9 +350,9 @@ static Inkscape::XML::Node *sp_text_write(SPObject *object, Inkscape::XML::Docum if (text->style->line_height.set && !text->style->line_height.inherit && !text->style->line_height.normal && text->style->line_height.unit == SP_CSS_UNIT_PERCENT) { Inkscape::SVGOStringStream os; os << (text->style->line_height.value * 100.0) << "%"; - SP_OBJECT_REPR(text)->setAttribute("sodipodi:linespacing", os.str().c_str()); + text->getRepr()->setAttribute("sodipodi:linespacing", os.str().c_str()); } else { - SP_OBJECT_REPR(text)->setAttribute("sodipodi:linespacing", NULL); + text->getRepr()->setAttribute("sodipodi:linespacing", NULL); } if (((SPObjectClass *) (text_parent_class))->write) { @@ -368,7 +368,7 @@ sp_text_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, un SP_TEXT(item)->layout.getBoundingBox(bbox, transform); // Add stroke width - SPStyle* style=SP_OBJECT_STYLE (item); + SPStyle* style = item->style; if (!style->stroke.isNone()) { double const scale = transform.descrim(); if ( fabs(style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord @@ -409,11 +409,10 @@ sp_text_hide(SPItem *item, unsigned key) ((SPItemClass *) text_parent_class)->hide (item, key); } -static char * -sp_text_description(SPItem *item) +static char * sp_text_description(SPItem *item) { - SPText *text = (SPText *) item; - SPStyle *style = SP_OBJECT_STYLE(text); + SPText *text = reinterpret_cast(item); + SPStyle *style = text->style; font_instance *tf = font_factory::Default()->FaceFromStyle(style); @@ -515,8 +514,8 @@ sp_text_print (SPItem *item, SPPrintContext *ctx) item->getBboxDesktop (&bbox); dbox.x0 = 0.0; dbox.y0 = 0.0; - dbox.x1 = SP_OBJECT_DOCUMENT (item)->getWidth (); - dbox.y1 = SP_OBJECT_DOCUMENT (item)->getHeight (); + dbox.x1 = item->document->getWidth(); + dbox.y1 = item->document->getHeight(); Geom::Affine const ctm (item->i2d_affine()); group->layout.print(ctx,&pbox,&dbox,&bbox,ctm); @@ -623,7 +622,7 @@ void SPText::rebuildLayout() void SPText::_adjustFontsizeRecursive(SPItem *item, double ex, bool is_root) { - SPStyle *style = SP_OBJECT_STYLE (item); + SPStyle *style = item->style; if (style && !NR_DF_TEST_CLOSE (ex, 1.0, NR_EPSILON)) { if (!style->font_size.set && is_root) { diff --git a/src/sp-tref.cpp b/src/sp-tref.cpp index a882ee0b0..7c4976a11 100644 --- a/src/sp-tref.cpp +++ b/src/sp-tref.cpp @@ -123,7 +123,7 @@ sp_tref_init(SPTRef *tref) new (&tref->attributes) TextTagAttributes; tref->href = NULL; - tref->uriOriginalRef = new SPTRefReference(SP_OBJECT(tref)); + tref->uriOriginalRef = new SPTRefReference(tref); new (&tref->_delete_connection) sigc::connection(); new (&tref->_changed_connection) sigc::connection(); @@ -223,7 +223,7 @@ sp_tref_set(SPObject *object, unsigned int key, gchar const *value) } // No matter what happened, an update should be in order - SP_OBJECT(tref)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + tref->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } } else { // default @@ -323,16 +323,20 @@ static void sp_tref_bbox(SPItem const *item, NRRect *bbox, Geom::Affine const &transform, unsigned const /*flags*/) { // find out the ancestor text which holds our layout - SPObject *parent_text = SP_OBJECT(item); - for (; parent_text != NULL && !SP_IS_TEXT(parent_text); parent_text = SP_OBJECT_PARENT (parent_text)){}; - if (parent_text == NULL) return; + SPObject const *parent_text = item; + while ( parent_text && !SP_IS_TEXT(parent_text) ) { + parent_text = parent_text->parent; + } + if (parent_text == NULL) { + return; + } // get the bbox of our portion of the layout SP_TEXT(parent_text)->layout.getBoundingBox( bbox, transform, sp_text_get_length_upto(parent_text, item), sp_text_get_length_upto(item, NULL) - 1); // Add stroke width - SPStyle* style=SP_OBJECT_STYLE (item); + SPStyle* style = item->style; if (!style->stroke.isNone()) { double const scale = transform.descrim(); if ( fabs(style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord @@ -388,7 +392,7 @@ sp_tref_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPTRef *tref) tref->_delete_connection.disconnect(); if (tref->stringChild) { - SP_OBJECT(tref)->detach(tref->stringChild); + tref->detach(tref->stringChild); tref->stringChild = NULL; } @@ -399,7 +403,7 @@ sp_tref_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPTRef *tref) sp_tref_update_text(tref); // Restore the delete connection now that we're done messing with stuff - tref->_delete_connection = SP_OBJECT(refRoot)->connectDelete(sigc::bind(sigc::ptr_fun(&sp_tref_delete_self), tref)); + tref->_delete_connection = refRoot->connectDelete(sigc::bind(sigc::ptr_fun(&sp_tref_delete_self), tref)); } } @@ -412,7 +416,7 @@ sp_tref_href_changed(SPObject */*old_ref*/, SPObject */*ref*/, SPTRef *tref) static void sp_tref_delete_self(SPObject */*deleted*/, SPTRef *self) { - SP_OBJECT(self)->deleteObject(); + self->deleteObject(); } /** @@ -423,7 +427,7 @@ SPObject * SPTRef::getObjectReferredTo(void) SPObject *referredObject = NULL; if (uriOriginalRef) { - referredObject = SP_OBJECT(uriOriginalRef->getObject()); + referredObject = uriOriginalRef->getObject(); } return referredObject; @@ -441,7 +445,7 @@ sp_tref_reference_allowed(SPTRef *tref, SPObject *possible_ref) if (tref && possible_ref) { if (tref != possible_ref) { bool ancestor = false; - for (SPObject *obj = tref; obj; obj = SP_OBJECT_PARENT(obj)) { + for (SPObject *obj = tref; obj; obj = obj->parent) { if (possible_ref == obj) { ancestor = true; break; @@ -470,15 +474,15 @@ sp_tref_fully_contained(SPObject *start_item, Glib::ustring::iterator &start, // If neither the beginning or the end is a tref then we return true (whether there // is a tref in the innards or not, because if there is one then it must be totally // contained) - if (!(SP_IS_STRING(start_item) && SP_IS_TREF(SP_OBJECT_PARENT(start_item))) - && !(SP_IS_STRING(end_item) && SP_IS_TREF(SP_OBJECT_PARENT(end_item)))) { + if (!(SP_IS_STRING(start_item) && SP_IS_TREF(start_item->parent)) + && !(SP_IS_STRING(end_item) && SP_IS_TREF(end_item->parent))) { fully_contained = true; } // Both the beginning and end are trefs; but in this case, the string iterators // must be at the right places - else if ((SP_IS_STRING(start_item) && SP_IS_TREF(SP_OBJECT_PARENT(start_item))) - && (SP_IS_STRING(end_item) && SP_IS_TREF(SP_OBJECT_PARENT(end_item)))) { + else if ((SP_IS_STRING(start_item) && SP_IS_TREF(start_item->parent)) + && (SP_IS_STRING(end_item) && SP_IS_TREF(end_item->parent))) { if (start == SP_STRING(start_item)->string.begin() && end == SP_STRING(start_item)->string.end()) { fully_contained = true; @@ -487,16 +491,16 @@ sp_tref_fully_contained(SPObject *start_item, Glib::ustring::iterator &start, // If the beginning is a string that is a child of a tref, the iterator has to be // at the beginning of the item - else if ((SP_IS_STRING(start_item) && SP_IS_TREF(SP_OBJECT_PARENT(start_item))) - && !(SP_IS_STRING(end_item) && SP_IS_TREF(SP_OBJECT_PARENT(end_item)))) { + else if ((SP_IS_STRING(start_item) && SP_IS_TREF(start_item->parent)) + && !(SP_IS_STRING(end_item) && SP_IS_TREF(end_item->parent))) { if (start == SP_STRING(start_item)->string.begin()) { fully_contained = true; } } // Same, but the for the end - else if (!(SP_IS_STRING(start_item) && SP_IS_TREF(SP_OBJECT_PARENT(start_item))) - && (SP_IS_STRING(end_item) && SP_IS_TREF(SP_OBJECT_PARENT(end_item)))) { + else if (!(SP_IS_STRING(start_item) && SP_IS_TREF(start_item->parent)) + && (SP_IS_STRING(end_item) && SP_IS_TREF(end_item->parent))) { if (end == SP_STRING(start_item)->string.end()) { fully_contained = true; } @@ -512,23 +516,23 @@ void sp_tref_update_text(SPTRef *tref) if (tref) { // Get the character data that will be used with this tref Glib::ustring charData = ""; - build_string_from_root(SP_OBJECT_REPR(tref->getObjectReferredTo()), &charData); + build_string_from_root(tref->getObjectReferredTo()->getRepr(), &charData); if (tref->stringChild) { - SP_OBJECT(tref)->detach(tref->stringChild); + tref->detach(tref->stringChild); tref->stringChild = NULL; } // Create the node and SPString to be the tref's child - Inkscape::XML::Document *xml_doc = SP_OBJECT_DOCUMENT(tref)->getReprDoc(); + Inkscape::XML::Document *xml_doc = tref->document->getReprDoc(); Inkscape::XML::Node *newStringRepr = xml_doc->createTextNode(charData.c_str()); tref->stringChild = SP_OBJECT(g_object_new(sp_repr_type_lookup(newStringRepr), NULL)); // Add this SPString as a child of the tref - SP_OBJECT(tref)->attach(tref->stringChild, tref->lastChild()); + tref->attach(tref->stringChild, tref->lastChild()); sp_object_unref(tref->stringChild, NULL); - (tref->stringChild)->invoke_build(SP_OBJECT(tref)->document, newStringRepr, TRUE); + (tref->stringChild)->invoke_build(tref->document, newStringRepr, TRUE); Inkscape::GC::release(newStringRepr); } @@ -581,10 +585,10 @@ sp_tref_convert_to_tspan(SPObject *obj) SPTRef *tref = SP_TREF(obj); if (tref && tref->stringChild) { - Inkscape::XML::Node *tref_repr = SP_OBJECT_REPR(tref); + Inkscape::XML::Node *tref_repr = tref->getRepr(); Inkscape::XML::Node *tref_parent = sp_repr_parent(tref_repr); - SPDocument *document = SP_OBJECT(tref)->document; + SPDocument *document = tref->document; Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *new_tspan_repr = xml_doc->createElement("svg:tspan"); @@ -596,35 +600,35 @@ sp_tref_convert_to_tspan(SPObject *obj) new_tspan = document->getObjectByRepr(new_tspan_repr); // Create a new string child for the tspan - Inkscape::XML::Node *new_string_repr = SP_OBJECT_REPR(tref->stringChild)->duplicate(xml_doc); + Inkscape::XML::Node *new_string_repr = tref->stringChild->getRepr()->duplicate(xml_doc); new_tspan_repr->addChild(new_string_repr, NULL); //SPObject * new_string_child = document->getObjectByRepr(new_string_repr); // Merge style from the tref - SPStyle *new_tspan_sty = SP_OBJECT_STYLE(new_tspan); - SPStyle const *tref_sty = SP_OBJECT_STYLE(tref); + SPStyle *new_tspan_sty = new_tspan->style; + SPStyle const *tref_sty = tref->style; sp_style_merge_from_dying_parent(new_tspan_sty, tref_sty); sp_style_merge_from_parent(new_tspan_sty, new_tspan->parent->style); - SP_OBJECT(new_tspan)->updateRepr(); + new_tspan->updateRepr(); // Hold onto our SPObject and repr for now. - sp_object_ref(SP_OBJECT(tref), NULL); + sp_object_ref(tref, NULL); Inkscape::GC::anchor(tref_repr); // Remove ourselves, not propagating delete events to avoid a // chain-reaction with other elements that might reference us. - SP_OBJECT(tref)->deleteObject(false); + tref->deleteObject(false); // Give the copy our old id and let go of our old repr. new_tspan_repr->setAttribute("id", tref_repr->attribute("id")); Inkscape::GC::release(tref_repr); // Establish the succession and let go of our object. - SP_OBJECT(tref)->setSuccessor(new_tspan); - sp_object_unref(SP_OBJECT(tref), NULL); + tref->setSuccessor(new_tspan); + sp_object_unref(tref, NULL); } } //////////////////// @@ -633,19 +637,19 @@ sp_tref_convert_to_tspan(SPObject *obj) else { GSList *l = NULL; for (SPObject *child = obj->firstChild() ; child != NULL ; child = child->getNext() ) { - sp_object_ref (SP_OBJECT (child), obj); + sp_object_ref(child, obj); l = g_slist_prepend (l, child); } l = g_slist_reverse (l); while (l) { - SPObject *child = SP_OBJECT (l->data); + SPObject *child = reinterpret_cast(l->data); // We just built this list, so cast is safe. l = g_slist_remove (l, child); // Note that there may be more than one conversion happening here, so if it's not a // tref being passed into this function, the returned value can't be specifically known new_tspan = sp_tref_convert_to_tspan(child); - sp_object_unref (SP_OBJECT (child), obj); + sp_object_unref(child, obj); } } diff --git a/src/spray-context.cpp b/src/spray-context.cpp index 244c52fad..e7ef9d317 100644 --- a/src/spray-context.cpp +++ b/src/spray-context.cpp @@ -155,7 +155,7 @@ void sp_spray_rotate_rel(Geom::Point c,SPDesktop */*desktop*/,SPItem *item, Geom // Rotate item. item->set_i2d_affine(item->i2d_affine() * (Geom::Affine)affine); // Use each item's own transform writer, consistent with sp_selection_apply_affine() - item->doWriteTransform(SP_OBJECT_REPR(item), item->transform); + item->doWriteTransform(item->getRepr(), item->transform); // Restore the center position (it's changed because the bbox center changed) if (item->isCenterSet()) { item->setCenter(c); @@ -168,7 +168,7 @@ void sp_spray_scale_rel(Geom::Point c, SPDesktop */*desktop*/, SPItem *item, Geo { Geom::Translate const s(c); item->set_i2d_affine(item->i2d_affine() * s.inverse() * scale * s ); - item->doWriteTransform(SP_OBJECT_REPR(item), item->transform); + item->doWriteTransform(item->getRepr(), item->transform); } static void sp_spray_context_init(SPSprayContext *tc) @@ -487,9 +487,9 @@ bool sp_spray_recursive(SPDesktop *desktop, if(_fid<=population) { // duplicate - SPDocument *doc = SP_OBJECT_DOCUMENT(item); + SPDocument *doc = item->document; Inkscape::XML::Document* xml_doc = doc->getReprDoc(); - Inkscape::XML::Node *old_repr = SP_OBJECT_REPR(item); + Inkscape::XML::Node *old_repr = item->getRepr(); Inkscape::XML::Node *parent = old_repr->parent(); Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc); parent->appendChild(copy); @@ -528,9 +528,9 @@ bool sp_spray_recursive(SPDesktop *desktop, } i++; } - SPDocument *doc = SP_OBJECT_DOCUMENT(father); + SPDocument *doc = father->document; Inkscape::XML::Document* xml_doc = doc->getReprDoc(); - Inkscape::XML::Node *old_repr = SP_OBJECT_REPR(father); + Inkscape::XML::Node *old_repr = father->getRepr(); Inkscape::XML::Node *parent = old_repr->parent(); Geom::OptRect a = father->getBounds(father->i2doc_affine()); @@ -575,9 +575,9 @@ bool sp_spray_recursive(SPDesktop *desktop, if (a) { if(_fid<=population) { SPItem *item_copied; - SPDocument *doc = SP_OBJECT_DOCUMENT(item); + SPDocument *doc = item->document; Inkscape::XML::Document* xml_doc = doc->getReprDoc(); - Inkscape::XML::Node *old_repr = SP_OBJECT_REPR(item); + Inkscape::XML::Node *old_repr = item->getRepr(); Inkscape::XML::Node *parent = old_repr->parent(); // Creation of the clone diff --git a/src/style.cpp b/src/style.cpp index d254ab6f4..bb25a5f46 100644 --- a/src/style.cpp +++ b/src/style.cpp @@ -568,7 +568,7 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr) { g_assert(style != NULL); g_assert(repr != NULL); - g_assert(!object || (SP_OBJECT_REPR(object) == repr)); + g_assert(!object || (object->getRepr() == repr)); sp_style_clear(style); @@ -652,7 +652,7 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr) val = repr->attribute("color"); if (val) { sp_style_read_icolor(&style->color, val, style, ( object - ? SP_OBJECT_DOCUMENT(object) + ? object->document : NULL )); } } @@ -660,7 +660,7 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr) if (!style->fill.set) { val = repr->attribute("fill"); if (val) { - style->fill.read( val, *style, (object) ? SP_OBJECT_DOCUMENT(object) : NULL ); + style->fill.read( val, *style, (object) ? object->document : NULL ); } } /* fill-opacity */ @@ -676,7 +676,7 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr) if (!style->stroke.set) { val = repr->attribute("stroke"); if (val) { - style->stroke.read( val, *style, (object) ? SP_OBJECT_DOCUMENT(object) : NULL ); + style->stroke.read( val, *style, (object) ? object->document : NULL ); } } SPS_READ_PLENGTH_IF_UNSET(&style->stroke_width, repr, "stroke-width"); @@ -762,7 +762,7 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr) if (!style->filter.set) { val = repr->attribute("filter"); if (val) { - sp_style_read_ifilter(val, style, (object) ? SP_OBJECT_DOCUMENT(object) : NULL); + sp_style_read_ifilter(val, style, (object) ? object->document : NULL); } } SPS_READ_PENUM_IF_UNSET(&style->enable_background, repr, @@ -771,7 +771,7 @@ sp_style_read(SPStyle *style, SPObject *object, Inkscape::XML::Node *repr) /* 3. Merge from parent */ if (object) { if (object->parent) { - sp_style_merge_from_parent(style, SP_OBJECT_STYLE(object->parent)); + sp_style_merge_from_parent(style, object->parent->style); } } else { if (sp_repr_parent(repr)) { @@ -799,7 +799,7 @@ sp_style_read_from_object(SPStyle *style, SPObject *object) g_return_if_fail(object != NULL); g_return_if_fail(SP_IS_OBJECT(object)); - Inkscape::XML::Node *repr = SP_OBJECT_REPR(object); + Inkscape::XML::Node *repr = object->getRepr(); g_return_if_fail(repr != NULL); sp_style_read(style, object, repr); @@ -987,7 +987,7 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val) break; case SP_PROP_COLOR: if (!style->color.set) { - sp_style_read_icolor(&style->color, val, style, (style->object) ? SP_OBJECT_DOCUMENT(style->object) : NULL); + sp_style_read_icolor(&style->color, val, style, (style->object) ? style->object->document : NULL); } break; case SP_PROP_CURSOR: @@ -1044,7 +1044,7 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val) /* Filter */ case SP_PROP_FILTER: if (!style->filter.set && !style->filter.inherit) { - sp_style_read_ifilter(val, style, (style->object) ? SP_OBJECT_DOCUMENT(style->object) : NULL); + sp_style_read_ifilter(val, style, (style->object) ? style->object->document : NULL); } break; case SP_PROP_FLOOD_COLOR: @@ -1085,7 +1085,7 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val) } case SP_PROP_FILL: if (!style->fill.set) { - style->fill.read( val, *style, (style->object) ? SP_OBJECT_DOCUMENT(style->object) : NULL ); + style->fill.read( val, *style, (style->object) ? style->object->document : NULL ); } break; case SP_PROP_FILL_OPACITY: @@ -1152,7 +1152,7 @@ sp_style_merge_property(SPStyle *style, gint id, gchar const *val) case SP_PROP_STROKE: if (!style->stroke.set) { - style->stroke.read( val, *style, (style->object) ? SP_OBJECT_DOCUMENT(style->object) : NULL ); + style->stroke.read( val, *style, (style->object) ? style->object->document : NULL ); } break; case SP_PROP_STROKE_WIDTH: @@ -2274,8 +2274,8 @@ sp_style_merge_ifilter(SPStyle *style, SPIFilter const *parent) style->filter.href->detach(); // it may be that this style has not yet created its SPFilterReference - if (!style->filter.href && style->object && SP_OBJECT_DOCUMENT(style->object)) { - style->filter.href = new SPFilterReference(SP_OBJECT_DOCUMENT(style->object)); + if (!style->filter.href && style->object && style->object->document) { + style->filter.href = new SPFilterReference(style->object->document); style->filter.href->changedSignal().connect(sigc::bind(sigc::ptr_fun(sp_style_filter_ref_changed), style)); } @@ -4071,7 +4071,7 @@ sp_style_filter_clear(SPStyle *style) void sp_style_set_property_url (SPObject *item, gchar const *property, SPObject *linked, bool recursive) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR(item); + Inkscape::XML::Node *repr = item->getRepr(); if (repr == NULL) return; @@ -4099,13 +4099,19 @@ sp_style_set_property_url (SPObject *item, gchar const *property, SPObject *link void sp_style_unset_property_attrs(SPObject *o) { - if (!o) return; + if (!o) { + return; + } - SPStyle *style = SP_OBJECT_STYLE(o); - if (!style) return; + SPStyle *style = o->style; + if (!style) { + return; + } - Inkscape::XML::Node *repr = SP_OBJECT_REPR(o); - if (!repr) return; + Inkscape::XML::Node *repr = o->getRepr(); + if (!repr) { + return; + } if (style->opacity.set) { repr->setAttribute("opacity", NULL); @@ -4198,16 +4204,16 @@ sp_css_attr_from_style(SPStyle const *const style, guint const flags) * \pre object != NULL * \pre flags in {IFSET, ALWAYS}. */ -SPCSSAttr * -sp_css_attr_from_object(SPObject *object, guint const flags) +SPCSSAttr *sp_css_attr_from_object(SPObject *object, guint const flags) { g_return_val_if_fail(((flags == SP_STYLE_FLAG_IFSET) || (flags == SP_STYLE_FLAG_ALWAYS) ), NULL); - SPStyle const *const style = SP_OBJECT_STYLE(object); - if (style == NULL) - return NULL; - return sp_css_attr_from_style(style, flags); + SPCSSAttr * result = 0; + if (object->style) { + result = sp_css_attr_from_style(object->style, flags); + } + return result; } /** diff --git a/src/text-context.cpp b/src/text-context.cpp index 66e5f9450..5af2c5ebc 100644 --- a/src/text-context.cpp +++ b/src/text-context.cpp @@ -721,7 +721,7 @@ sp_text_context_root_handler(SPEventContext *const event_context, GdkEvent *cons // otherwise even one line won't fit; most probably a slip of hand (even if bigger than tolerance) SPItem *ft = create_flowtext_with_internal_frame (desktop, tc->p0, p1); /* Set style */ - sp_desktop_apply_style_tool(desktop, SP_OBJECT_REPR(ft), "/tools/text", true); + sp_desktop_apply_style_tool(desktop, ft->getRepr(), "/tools/text", true); sp_desktop_selection(desktop)->set(ft); desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Flowed text is created.")); DocumentUndo::done(sp_desktop_document(desktop), SP_VERB_CONTEXT_TEXT, @@ -1526,11 +1526,13 @@ sp_text_context_style_set(SPCSSAttr const *css, SPTextContext *tc) static int sp_text_context_style_query(SPStyle *style, int property, SPTextContext *tc) { - if (tc->text == NULL) + if (tc->text == NULL) { return QUERY_STYLE_NOTHING; + } const Inkscape::Text::Layout *layout = te_get_layout(tc->text); - if (layout == NULL) + if (layout == NULL) { return QUERY_STYLE_NOTHING; + } sp_text_context_validate_cursor_iterators(tc); GSList *styles_list = NULL; @@ -1543,18 +1545,21 @@ sp_text_context_style_query(SPStyle *style, int property, SPTextContext *tc) begin_it = tc->text_sel_end; end_it = tc->text_sel_start; } - if (begin_it == end_it) - if (!begin_it.prevCharacter()) + if (begin_it == end_it) { + if (!begin_it.prevCharacter()) { end_it.nextCharacter(); + } + } for (Inkscape::Text::Layout::iterator it = begin_it ; it < end_it ; it.nextStartOfSpan()) { SPObject const *pos_obj = 0; void *rawptr = 0; layout->getSourceOfCharacter(it, &rawptr); - if (!rawptr || !SP_IS_OBJECT(rawptr)) + if (!rawptr || !SP_IS_OBJECT(rawptr)) { continue; + } pos_obj = SP_OBJECT(rawptr); - while (SP_IS_STRING(pos_obj) && SP_OBJECT_PARENT(pos_obj)) { - pos_obj = SP_OBJECT_PARENT(pos_obj); // SPStrings don't have style + while (SP_IS_STRING(pos_obj) && pos_obj->parent) { + pos_obj = pos_obj->parent; // SPStrings don't have style } styles_list = g_slist_prepend(styles_list, (gpointer)pos_obj); } @@ -1716,7 +1721,7 @@ sp_text_context_forget_text(SPTextContext *tc) */ /* if ((SP_IS_TEXT(ti) || SP_IS_FLOWTEXT(ti)) && sp_te_input_is_empty(ti)) { - Inkscape::XML::Node *text_repr=SP_OBJECT_REPR(ti); + Inkscape::XML::Node *text_repr = ti->getRepr(); // the repr may already have been unparented // if we were called e.g. as the result of // an undo or the element being removed from @@ -1756,7 +1761,7 @@ sptc_commit(GtkIMContext */*imc*/, gchar *string, SPTextContext *tc) sp_text_context_update_cursor(tc); sp_text_context_update_text_selection(tc); - DocumentUndo::done(SP_OBJECT_DOCUMENT(tc->text), SP_VERB_CONTEXT_TEXT, + DocumentUndo::done(tc->text->document, SP_VERB_CONTEXT_TEXT, _("Type text")); } diff --git a/src/text-editing.cpp b/src/text-editing.cpp index fb9e2e6a3..1e918ae00 100644 --- a/src/text-editing.cpp +++ b/src/text-editing.cpp @@ -118,23 +118,26 @@ sp_te_get_cursor_coords (SPItem const *item, Inkscape::Text::Layout::iterator co SPStyle const * sp_te_style_at_position(SPItem const *text, Inkscape::Text::Layout::iterator const &position) { SPObject const *pos_obj = sp_te_object_at_position(text, position); - if (pos_obj) - return SP_OBJECT_STYLE(pos_obj); - return NULL; + SPStyle *result = (pos_obj) ? pos_obj->style : 0; + return result; } SPObject const * sp_te_object_at_position(SPItem const *text, Inkscape::Text::Layout::iterator const &position) { Inkscape::Text::Layout const *layout = te_get_layout(text); - if (layout == NULL) + if (layout == NULL) { return NULL; + } SPObject const *pos_obj = 0; void *rawptr = 0; layout->getSourceOfCharacter(position, &rawptr); pos_obj = SP_OBJECT(rawptr); - if (pos_obj == 0) pos_obj = text; - while (SP_OBJECT_STYLE(pos_obj) == NULL) - pos_obj = SP_OBJECT_PARENT(pos_obj); // not interested in SPStrings + if (pos_obj == 0) { + pos_obj = text; + } + while (pos_obj->style == NULL) { + pos_obj = pos_obj->parent; // not interested in SPStrings + } return pos_obj; } @@ -240,7 +243,7 @@ unsigned sp_text_get_length_upto(SPObject const *item, SPObject const *upto) // Take care of new lines... if (is_line_break_object(item) && !SP_IS_TEXT(item)) { - if (item != SP_OBJECT_PARENT(item)->firstChild()) { + if (item != item->parent->firstChild()) { // add 1 for each newline length++; } @@ -303,7 +306,7 @@ to \a item at the same level. */ static unsigned sum_sibling_text_lengths_before(SPObject const *item) { unsigned char_index = 0; - for (SPObject *sibling = SP_OBJECT_PARENT(item)->firstChild() ; sibling && sibling != item ; sibling = sibling->getNext()) { + for (SPObject *sibling = item->parent->firstChild() ; sibling && sibling != item ; sibling = sibling->getNext()) { char_index += sp_text_get_length(sibling); } return char_index; @@ -327,20 +330,20 @@ parent of the first line break node encountered. */ static SPObject* split_text_object_tree_at(SPObject *split_obj, unsigned char_index) { - Inkscape::XML::Document *xml_doc = SP_OBJECT_DOCUMENT(split_obj)->getReprDoc(); + Inkscape::XML::Document *xml_doc = split_obj->document->getReprDoc(); if (is_line_break_object(split_obj)) { - Inkscape::XML::Node *new_node = duplicate_node_without_children(xml_doc, SP_OBJECT_REPR(split_obj)); - SP_OBJECT_REPR(SP_OBJECT_PARENT(split_obj))->addChild(new_node, SP_OBJECT_REPR(split_obj)); + Inkscape::XML::Node *new_node = duplicate_node_without_children(xml_doc, split_obj->getRepr()); + split_obj->parent->getRepr()->addChild(new_node, split_obj->getRepr()); Inkscape::GC::release(new_node); split_attributes(split_obj, split_obj->getNext(), char_index); return split_obj->getNext(); } unsigned char_count_before = sum_sibling_text_lengths_before(split_obj); - SPObject *duplicate_obj = split_text_object_tree_at(SP_OBJECT_PARENT(split_obj), char_index + char_count_before); + SPObject *duplicate_obj = split_text_object_tree_at(split_obj->parent, char_index + char_count_before); // copy the split node - Inkscape::XML::Node *new_node = duplicate_node_without_children(xml_doc, SP_OBJECT_REPR(split_obj)); - SP_OBJECT_REPR(duplicate_obj)->appendChild(new_node); + Inkscape::XML::Node *new_node = duplicate_node_without_children(xml_doc, split_obj->getRepr()); + duplicate_obj->getRepr()->appendChild(new_node); Inkscape::GC::release(new_node); // sort out the copied attributes (x/y/dx/dy/rotate) @@ -349,11 +352,11 @@ static SPObject* split_text_object_tree_at(SPObject *split_obj, unsigned char_in // then move all the subsequent nodes split_obj = split_obj->getNext(); while (split_obj) { - Inkscape::XML::Node *move_repr = SP_OBJECT_REPR(split_obj); + Inkscape::XML::Node *move_repr = split_obj->getRepr(); SPObject *next_obj = split_obj->getNext(); // this is about to become invalidated by removeChild() Inkscape::GC::anchor(move_repr); - SP_OBJECT_REPR(SP_OBJECT_PARENT(split_obj))->removeChild(move_repr); - SP_OBJECT_REPR(duplicate_obj)->appendChild(move_repr); + split_obj->parent->getRepr()->removeChild(move_repr); + duplicate_obj->getRepr()->appendChild(move_repr); Inkscape::GC::release(move_repr); split_obj = next_obj; @@ -392,14 +395,14 @@ Inkscape::Text::Layout::iterator sp_te_insert_line (SPItem *item, Inkscape::Text } if (split_obj) { - Inkscape::XML::Document *xml_doc = SP_OBJECT_DOCUMENT(split_obj)->getReprDoc(); - Inkscape::XML::Node *new_node = duplicate_node_without_children(xml_doc, SP_OBJECT_REPR(split_obj)); - SP_OBJECT_REPR(SP_OBJECT_PARENT(split_obj))->addChild(new_node, SP_OBJECT_REPR(split_obj)); + Inkscape::XML::Document *xml_doc = split_obj->document->getReprDoc(); + Inkscape::XML::Node *new_node = duplicate_node_without_children(xml_doc, split_obj->getRepr()); + split_obj->parent->getRepr()->addChild(new_node, split_obj->getRepr()); Inkscape::GC::release(new_node); } } else if (SP_IS_STRING(split_obj)) { // If the parent is a tref, editing on this particular string is disallowed. - if (SP_IS_TREF(SP_OBJECT_PARENT(split_obj))) { + if (SP_IS_TREF(split_obj->parent)) { desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, tref_edit_message); return position; } @@ -410,9 +413,9 @@ Inkscape::Text::Layout::iterator sp_te_insert_line (SPItem *item, Inkscape::Text char_index++; // we need to split the entire text tree into two SPString *new_string = SP_STRING(split_text_object_tree_at(split_obj, char_index)); - SP_OBJECT_REPR(new_string)->setContent(&*split_text_iter.base()); // a little ugly + new_string->getRepr()->setContent(&*split_text_iter.base()); // a little ugly string->erase(split_text_iter, string->end()); - SP_OBJECT_REPR(split_obj)->setContent(string->c_str()); + split_obj->getRepr()->setContent(string->c_str()); // TODO: if the split point was at the beginning of a span we have a whole load of empty elements to clean up } else { // TODO @@ -461,7 +464,7 @@ static void insert_into_spstring(SPString *string_item, Glib::ustring::iterator SPObject *parent_item = string_item; for ( ; ; ) { char_index += sum_sibling_text_lengths_before(parent_item); - parent_item = SP_OBJECT_PARENT(parent_item); + parent_item = parent_item->parent; TextTagAttributes *attributes = attributes_for_object(parent_item); if (!attributes) break; attributes->insert(char_index, char_count); @@ -494,7 +497,7 @@ sp_te_insert(SPItem *item, Inkscape::Text::Layout::iterator const &position, gch source_obj = SP_OBJECT(rawptr); if (SP_IS_STRING(source_obj)) { // If the parent is a tref, editing on this particular string is disallowed. - if (SP_IS_TREF(SP_OBJECT_PARENT(source_obj))) { + if (SP_IS_TREF(source_obj->parent)) { desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, tref_edit_message); return position; } @@ -505,7 +508,7 @@ sp_te_insert(SPItem *item, Inkscape::Text::Layout::iterator const &position, gch insert_into_spstring(string_item, cursor_at_end ? string_item->string.end() : iter_text, utf8); } else { // the not-so-simple case where we're at a line break or other control char; add to the next child/sibling SPString - Inkscape::XML::Document *xml_doc = SP_OBJECT_REPR(item)->document(); + Inkscape::XML::Document *xml_doc = item->getRepr()->document(); if (cursor_at_start) { source_obj = item; if (source_obj->hasChildren()) { @@ -521,7 +524,7 @@ sp_te_insert(SPItem *item, Inkscape::Text::Layout::iterator const &position, gch } if (source_obj == item && SP_IS_FLOWTEXT(item)) { Inkscape::XML::Node *para = xml_doc->createElement("svg:flowPara"); - SP_OBJECT_REPR(item)->appendChild(para); + item->getRepr()->appendChild(para); source_obj = item->lastChild(); } } else @@ -532,13 +535,13 @@ sp_te_insert(SPItem *item, Inkscape::Text::Layout::iterator const &position, gch if (string_item == NULL) { // need to add an SPString in this (pathological) case Inkscape::XML::Node *rstring = xml_doc->createTextNode(""); - SP_OBJECT_REPR(source_obj)->addChild(rstring, NULL); + source_obj->getRepr()->addChild(rstring, NULL); Inkscape::GC::release(rstring); g_assert(SP_IS_STRING(source_obj->firstChild())); string_item = SP_STRING(source_obj->firstChild()); } // If the parent is a tref, editing on this particular string is disallowed. - if (SP_IS_TREF(SP_OBJECT_PARENT(string_item))) { + if (SP_IS_TREF(string_item->parent)) { desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, tref_edit_message); return position; } @@ -581,10 +584,10 @@ static SPObject* get_common_ancestor(SPObject *text, SPObject *one, SPObject *tw return text; SPObject *common_ancestor = one; if (SP_IS_STRING(common_ancestor)) - common_ancestor = SP_OBJECT_PARENT(common_ancestor); + common_ancestor = common_ancestor->parent; while (!(common_ancestor == two || common_ancestor->isAncestorOf(two))) { g_assert(common_ancestor != text); - common_ancestor = SP_OBJECT_PARENT(common_ancestor); + common_ancestor = common_ancestor->parent; } return common_ancestor; } @@ -605,7 +608,7 @@ the next suitable object and deleting \a item. Returns the object after the ones that have just been moved and sets \a next_is_sibling accordingly. */ static SPObject* delete_line_break(SPObject *root, SPObject *item, bool *next_is_sibling) { - Inkscape::XML::Node *this_repr = SP_OBJECT_REPR(item); + Inkscape::XML::Node *this_repr = item->getRepr(); SPObject *next_item = NULL; unsigned moved_char_count = sp_text_get_length(item) - 1; // the -1 is because it's going to count the line break @@ -614,7 +617,7 @@ static SPObject* delete_line_break(SPObject *root, SPObject *item, bool *next_is

*text

*text

*/ - Inkscape::XML::Document *xml_doc = SP_OBJECT_REPR(item)->document(); + Inkscape::XML::Document *xml_doc = item->getRepr()->document(); Inkscape::XML::Node *new_span_repr = xml_doc->createElement(span_name_for_text_object(root)); if (gchar const *a = this_repr->attribute("dx")) @@ -626,15 +629,15 @@ static SPObject* delete_line_break(SPObject *root, SPObject *item, bool *next_is SPObject *following_item = item; while (following_item->getNext() == NULL) { - following_item = SP_OBJECT_PARENT(following_item); + following_item = following_item->parent; g_assert(following_item != root); } following_item = following_item->getNext(); SPObject *new_parent_item; if (SP_IS_STRING(following_item)) { - new_parent_item = SP_OBJECT_PARENT(following_item); - SP_OBJECT_REPR(new_parent_item)->addChild(new_span_repr, following_item->getPrev() ? SP_OBJECT_REPR(following_item->getPrev()) : NULL); + new_parent_item = following_item->parent; + new_parent_item->getRepr()->addChild(new_span_repr, following_item->getPrev() ? following_item->getPrev()->getRepr() : NULL); next_item = following_item; *next_is_sibling = true; } else { @@ -645,13 +648,13 @@ static SPObject* delete_line_break(SPObject *root, SPObject *item, bool *next_is next_item = new_parent_item; *next_is_sibling = false; } - SP_OBJECT_REPR(new_parent_item)->addChild(new_span_repr, NULL); + new_parent_item->getRepr()->addChild(new_span_repr, NULL); } // work around a bug in sp_style_write_difference() which causes the difference // not to be written if the second param has a style set which the first does not // by causing the first param to have everything set - SPCSSAttr *dest_node_attrs = sp_repr_css_attr(SP_OBJECT_REPR(new_parent_item), "style"); + SPCSSAttr *dest_node_attrs = sp_repr_css_attr(new_parent_item->getRepr(), "style"); SPCSSAttr *this_node_attrs = sp_repr_css_attr(this_repr, "style"); SPCSSAttr *this_node_attrs_inherited = sp_repr_css_attr_inherited(this_repr, "style"); Inkscape::Util::List attrs = dest_node_attrs->attributeList(); @@ -687,17 +690,19 @@ static void erase_from_spstring(SPString *string_item, Glib::ustring::iterator i for (Glib::ustring::iterator it = iter_from ; it != iter_to ; it++) char_count++; string->erase(iter_from, iter_to); - SP_OBJECT_REPR(string_item)->setContent(string->c_str()); + string_item->getRepr()->setContent(string->c_str()); SPObject *parent_item = string_item; for ( ; ; ) { char_index += sum_sibling_text_lengths_before(parent_item); - parent_item = SP_OBJECT_PARENT(parent_item); + parent_item = parent_item->parent; TextTagAttributes *attributes = attributes_for_object(parent_item); - if (attributes == NULL) break; + if (attributes == NULL) { + break; + } attributes->erase(char_index, char_count); - attributes->writeTo(SP_OBJECT_REPR(parent_item)); + attributes->writeTo(parent_item->getRepr()); } } @@ -732,16 +737,18 @@ sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start, start_item = SP_OBJECT(rawptr); layout->getSourceOfCharacter(iter_pair.second, &rawptr, &end_text_iter); end_item = SP_OBJECT(rawptr); - if (start_item == 0) + if (start_item == 0) { return success; // start is at end of text - if (is_line_break_object(start_item)) + } + if (is_line_break_object(start_item)) { move_to_end_of_paragraph(&start_item, &start_text_iter); + } if (end_item == 0) { end_item = item->lastChild(); move_to_end_of_paragraph(&end_item, &end_text_iter); - } - else if (is_line_break_object(end_item)) + } else if (is_line_break_object(end_item)) { move_to_end_of_paragraph(&end_item, &end_text_iter); + } SPObject *common_ancestor = get_common_ancestor(item, start_item, end_item); @@ -749,7 +756,7 @@ sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start, // the quick case where we're deleting stuff all from the same string if (SP_IS_STRING(start_item)) { // always true (if it_start != it_end anyway) // If the parent is a tref, editing on this particular string is disallowed. - if (SP_IS_TREF(SP_OBJECT_PARENT(start_item))) { + if (SP_IS_TREF(start_item->parent)) { desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, tref_edit_message); } else { erase_from_spstring(SP_STRING(start_item), start_text_iter, end_text_iter); @@ -763,7 +770,7 @@ sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start, if (sub_item == end_item) { if (SP_IS_STRING(sub_item)) { // If the parent is a tref, editing on this particular string is disallowed. - if (SP_IS_TREF(SP_OBJECT_PARENT(sub_item))) { + if (SP_IS_TREF(sub_item->parent)) { desktop->messageStack()->flash(Inkscape::ERROR_MESSAGE, tref_edit_message); break; } @@ -791,7 +798,7 @@ sp_te_delete (SPItem *item, Inkscape::Text::Layout::iterator const &start, bool is_sibling = true; next_item = sub_item->getNext(); if (next_item == NULL) { - next_item = SP_OBJECT_PARENT(sub_item); + next_item = sub_item->parent; is_sibling = false; } @@ -875,10 +882,11 @@ sp_te_get_string_multiline (SPItem const *text, Inkscape::Text::Layout::iterator Glib::ustring::iterator text_iter; layout->getSourceOfCharacter(first, &rawptr, &text_iter); char_item = SP_OBJECT(rawptr); - if (SP_IS_STRING(char_item)) + if (SP_IS_STRING(char_item)) { result += *text_iter; - else + } else { result += '\n'; + } } return result; } @@ -889,20 +897,22 @@ sp_te_set_repr_text_multiline(SPItem *text, gchar const *str) g_return_if_fail (text != NULL); g_return_if_fail (SP_IS_TEXT(text) || SP_IS_FLOWTEXT(text)); - Inkscape::XML::Document *xml_doc = SP_OBJECT_REPR(text)->document(); + Inkscape::XML::Document *xml_doc = text->getRepr()->document(); Inkscape::XML::Node *repr; SPObject *object; bool is_textpath = false; if (SP_IS_TEXT_TEXTPATH (text)) { - repr = SP_OBJECT_REPR(text->firstChild()); + repr = text->firstChild()->getRepr(); object = text->firstChild(); is_textpath = true; } else { - repr = SP_OBJECT_REPR (text); - object = SP_OBJECT (text); + repr = text->getRepr(); + object = text; } - if (!str) str = ""; + if (!str) { + str = ""; + } gchar *content = g_strdup (str); repr->setContent(""); @@ -910,7 +920,7 @@ sp_te_set_repr_text_multiline(SPItem *text, gchar const *str) while (child) { SPObject *next = child->getNext(); if (!SP_IS_FLOWREGION(child) && !SP_IS_FLOWREGIONEXCLUDE(child)) { - repr->removeChild(SP_OBJECT_REPR(child)); + repr->removeChild(child->getRepr()); } child = next; } @@ -954,8 +964,9 @@ which represents the iterator \a position. */ TextTagAttributes* text_tag_attributes_at_position(SPItem *item, Inkscape::Text::Layout::iterator const &position, unsigned *char_index) { - if (item == NULL || char_index == NULL || !SP_IS_TEXT(item)) + if (item == NULL || char_index == NULL || !SP_IS_TEXT(item)) { return NULL; // flowtext doesn't support kerning yet + } SPText *text = SP_TEXT(item); SPObject *source_item = 0; @@ -964,13 +975,16 @@ text_tag_attributes_at_position(SPItem *item, Inkscape::Text::Layout::iterator c text->layout.getSourceOfCharacter(position, &rawptr, &source_text_iter); source_item = SP_OBJECT(rawptr); - if (!SP_IS_STRING(source_item)) return NULL; + if (!SP_IS_STRING(source_item)) { + return NULL; + } Glib::ustring *string = &SP_STRING(source_item)->string; *char_index = sum_sibling_text_lengths_before(source_item); - for (Glib::ustring::iterator it = string->begin() ; it != source_text_iter ; it++) + for (Glib::ustring::iterator it = string->begin() ; it != source_text_iter ; it++) { ++*char_index; + } - return attributes_for_object(SP_OBJECT_PARENT(source_item)); + return attributes_for_object(source_item->parent); } void @@ -1045,8 +1059,10 @@ sp_te_adjust_rotation_screen(SPItem *text, Inkscape::Text::Layout::iterator cons void *rawptr = 0; layout->getSourceOfCharacter(std::min(start, end), &rawptr); source_item = SP_OBJECT(rawptr); - if (source_item == 0) return; - gdouble degrees = (180/M_PI) * atan2(pixels, SP_OBJECT_PARENT(source_item)->style->font_size.computed / factor); + if (source_item == 0) { + return; + } + gdouble degrees = (180/M_PI) * atan2(pixels, source_item->parent->style->font_size.computed / factor); sp_te_adjust_rotation(text, start, end, desktop, degrees); } @@ -1113,7 +1129,7 @@ sp_te_adjust_tspan_letterspacing_screen(SPItem *text, Inkscape::Text::Layout::it source_obj = source_obj->parent; } - SPStyle *style = SP_OBJECT_STYLE (source_obj); + SPStyle *style = source_obj->style; // calculate real value /* TODO: Consider calculating val unconditionally, i.e. drop the first `if' line, and @@ -1131,8 +1147,9 @@ sp_te_adjust_tspan_letterspacing_screen(SPItem *text, Inkscape::Text::Layout::it } if (start == end) { - while (!is_line_break_object(source_obj)) // move up the tree so we apply to the closest paragraph - source_obj = SP_OBJECT_PARENT(source_obj); + while (!is_line_break_object(source_obj)) { // move up the tree so we apply to the closest paragraph + source_obj = source_obj->parent; + } nb_let = sp_text_get_length(source_obj); } else { nb_let = abs(layout->iteratorToCharIndex(end) - layout->iteratorToCharIndex(start)); @@ -1195,7 +1212,7 @@ sp_te_adjust_linespacing_screen (SPItem *text, Inkscape::Text::Layout::iterator g_return_if_fail (SP_IS_TEXT(text) || SP_IS_FLOWTEXT(text)); Inkscape::Text::Layout const *layout = te_get_layout(text); - SPStyle *style = SP_OBJECT_STYLE (text); + SPStyle *style = text->style; if (!style->line_height.set || style->line_height.inherit || style->line_height.normal) { style->line_height.set = TRUE; @@ -1283,14 +1300,15 @@ as opposed to sp_style_merge_from_style_string which merges its parameter underneath the existing styles (ie ignoring already set properties). */ static void overwrite_style_with_string(SPObject *item, gchar const *style_string) { - SPStyle *new_style = sp_style_new(SP_OBJECT_DOCUMENT(item)); + SPStyle *new_style = sp_style_new(item->document); sp_style_merge_from_style_string(new_style, style_string); - gchar const *item_style_string = SP_OBJECT_REPR(item)->attribute("style"); - if (item_style_string && *item_style_string) + gchar const *item_style_string = item->getRepr()->attribute("style"); + if (item_style_string && *item_style_string) { sp_style_merge_from_style_string(new_style, item_style_string); + } gchar *new_style_string = sp_style_write_string(new_style); sp_style_unref(new_style); - SP_OBJECT_REPR(item)->setAttribute("style", new_style_string && *new_style_string ? new_style_string : NULL); + item->getRepr()->setAttribute("style", new_style_string && *new_style_string ? new_style_string : NULL); g_free(new_style_string); } @@ -1308,7 +1326,7 @@ static bool objects_have_equal_style(SPObject const *parent, SPObject const *chi gchar *parent_style = sp_style_write_string(parent->style, SP_STYLE_FLAG_ALWAYS); // we have to write parent_style then read it again, because some properties format their values // differently depending on whether they're set or not (*cough*dash-offset*cough*) - SPStyle *parent_spstyle = sp_style_new(SP_OBJECT_DOCUMENT(parent)); + SPStyle *parent_spstyle = sp_style_new(parent->document); sp_style_merge_from_style_string(parent_spstyle, parent_style); g_free(parent_style); parent_style = sp_style_write_string(parent_spstyle, SP_STYLE_FLAG_ALWAYS); @@ -1317,15 +1335,15 @@ static bool objects_have_equal_style(SPObject const *parent, SPObject const *chi Glib::ustring child_style_construction; while (child != parent) { // FIXME: this assumes that child's style is only in style= whereas it can also be in css attributes! - char const *style_text = SP_OBJECT_REPR(child)->attribute("style"); + char const *style_text = child->getRepr()->attribute("style"); if (style_text && *style_text) { child_style_construction.insert(0, style_text); child_style_construction.insert(0, 1, ';'); } - child = SP_OBJECT_PARENT(child); + child = child->parent; } child_style_construction.insert(0, parent_style); - SPStyle *child_spstyle = sp_style_new(SP_OBJECT_DOCUMENT(parent)); + SPStyle *child_spstyle = sp_style_new(parent->document); sp_style_merge_from_style_string(child_spstyle, child_style_construction.c_str()); gchar *child_style = sp_style_write_string(child_spstyle, SP_STYLE_FLAG_ALWAYS); sp_style_unref(child_spstyle); @@ -1361,7 +1379,7 @@ Annoyingly similar to sp_desktop_apply_css_recursive(), except without the transform stuff. */ static void apply_css_recursive(SPObject *o, SPCSSAttr const *css) { - sp_repr_css_change(SP_OBJECT_REPR(o), const_cast(css), "style"); + sp_repr_css_change(o->getRepr(), const_cast(css), "style"); for (SPObject *child = o->firstChild() ; child ; child = child->getNext() ) { if (sp_repr_css_property(const_cast(css), "opacity", NULL) != NULL) { @@ -1386,7 +1404,7 @@ name of the xml for a text span (ie tspan or flowspan). */ static void recursively_apply_style(SPObject *common_ancestor, SPCSSAttr const *css, SPObject *start_item, Glib::ustring::iterator start_text_iter, SPObject *end_item, Glib::ustring::iterator end_text_iter, char const *span_object_name) { bool passed_start = start_item == NULL ? true : false; - Inkscape::XML::Document *xml_doc = SP_OBJECT_DOCUMENT(common_ancestor)->getReprDoc(); + Inkscape::XML::Document *xml_doc = common_ancestor->document->getReprDoc(); for (SPObject *child = common_ancestor->firstChild() ; child ; child = child->getNext()) { if (start_item == child) { @@ -1409,7 +1427,7 @@ static void recursively_apply_style(SPObject *common_ancestor, SPCSSAttr const * Inkscape::XML::Node *child_span = xml_doc->createElement(span_object_name); sp_repr_css_set(child_span, const_cast(css), "style"); // better hope that prototype wasn't nonconst for a good reason SPObject *prev_item = child->getPrev(); - Inkscape::XML::Node *prev_repr = prev_item ? SP_OBJECT_REPR(prev_item) : NULL; + Inkscape::XML::Node *prev_repr = prev_item ? prev_item->getRepr() : NULL; if (child == start_item || child == end_item) { surround_entire_string = false; @@ -1419,33 +1437,31 @@ static void recursively_apply_style(SPObject *common_ancestor, SPCSSAttr const * unsigned end_char_index = char_index_of_iterator(string_item->string, end_text_iter); Inkscape::XML::Node *text_before = xml_doc->createTextNode(string_item->string.substr(0, start_char_index).c_str()); - SP_OBJECT_REPR(common_ancestor)->addChild(text_before, prev_repr); - SP_OBJECT_REPR(common_ancestor)->addChild(child_span, text_before); + common_ancestor->getRepr()->addChild(text_before, prev_repr); + common_ancestor->getRepr()->addChild(child_span, text_before); Inkscape::GC::release(text_before); Inkscape::XML::Node *text_in_span = xml_doc->createTextNode(string_item->string.substr(start_char_index, end_char_index - start_char_index).c_str()); child_span->appendChild(text_in_span); Inkscape::GC::release(text_in_span); - SP_OBJECT_REPR(child)->setContent(string_item->string.substr(end_char_index).c_str()); - + child->getRepr()->setContent(string_item->string.substr(end_char_index).c_str()); } else if (child == end_item) { // eg "ABCdef" -> "ABC""def" // (includes case where start_text_iter == begin()) // NB: we might create an empty string here. Doesn't matter, it'll get cleaned up later unsigned end_char_index = char_index_of_iterator(string_item->string, end_text_iter); - SP_OBJECT_REPR(common_ancestor)->addChild(child_span, prev_repr); + common_ancestor->getRepr()->addChild(child_span, prev_repr); Inkscape::XML::Node *text_in_span = xml_doc->createTextNode(string_item->string.substr(0, end_char_index).c_str()); child_span->appendChild(text_in_span); Inkscape::GC::release(text_in_span); - SP_OBJECT_REPR(child)->setContent(string_item->string.substr(end_char_index).c_str()); - + child->getRepr()->setContent(string_item->string.substr(end_char_index).c_str()); } else if (start_text_iter != string_item->string.begin()) { // eg "abcDEF" -> "abc""DEF" unsigned start_char_index = char_index_of_iterator(string_item->string, start_text_iter); Inkscape::XML::Node *text_before = xml_doc->createTextNode(string_item->string.substr(0, start_char_index).c_str()); - SP_OBJECT_REPR(common_ancestor)->addChild(text_before, prev_repr); - SP_OBJECT_REPR(common_ancestor)->addChild(child_span, text_before); + common_ancestor->getRepr()->addChild(text_before, prev_repr); + common_ancestor->getRepr()->addChild(child_span, text_before); Inkscape::GC::release(text_before); Inkscape::XML::Node *text_in_span = xml_doc->createTextNode(string_item->string.substr(start_char_index).c_str()); child_span->appendChild(text_in_span); @@ -1457,10 +1473,10 @@ static void recursively_apply_style(SPObject *common_ancestor, SPCSSAttr const * surround_entire_string = true; } if (surround_entire_string) { - Inkscape::XML::Node *child_repr = SP_OBJECT_REPR(child); - SP_OBJECT_REPR(common_ancestor)->addChild(child_span, child_repr); + Inkscape::XML::Node *child_repr = child->getRepr(); + common_ancestor->getRepr()->addChild(child_span, child_repr); Inkscape::GC::anchor(child_repr); - SP_OBJECT_REPR(common_ancestor)->removeChild(child_repr); + common_ancestor->getRepr()->removeChild(child_repr); child_span->appendChild(child_repr); Inkscape::GC::release(child_repr); child = common_ancestor->get_child_by_repr(child_span); @@ -1501,11 +1517,13 @@ static SPObject* ascend_while_first(SPObject *item, Glib::ustring::iterator text if (text_iter != SP_STRING(item)->string.begin()) return item; for ( ; ; ) { - SPObject *parent = SP_OBJECT_PARENT(item); - if (parent == common_ancestor) + SPObject *parent = item->parent; + if (parent == common_ancestor) { break; - if (item != parent->firstChild()) + } + if (item != parent->firstChild()) { break; + } item = parent; } return item; @@ -1535,18 +1553,28 @@ the repeated strings will be merged by another operator. */ static bool tidy_operator_inexplicable_spans(SPObject **item) { //XML Tree being directly used here while it shouldn't be. - if (*item && sp_repr_is_meta_element((*item)->getRepr())) return false; - if (SP_IS_STRING(*item)) return false; - if (is_line_break_object(*item)) return false; + if (*item && sp_repr_is_meta_element((*item)->getRepr())) { + return false; + } + if (SP_IS_STRING(*item)) { + return false; + } + if (is_line_break_object(*item)) { + return false; + } TextTagAttributes *attrs = attributes_for_object(*item); - if (attrs && attrs->anyAttributesSet()) return false; - if (!objects_have_equal_style(SP_OBJECT_PARENT(*item), *item)) return false; + if (attrs && attrs->anyAttributesSet()) { + return false; + } + if (!objects_have_equal_style((*item)->parent, *item)) { + return false; + } SPObject *next = *item; while ((*item)->hasChildren()) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR((*item)->firstChild()); + Inkscape::XML::Node *repr = (*item)->firstChild()->getRepr(); Inkscape::GC::anchor(repr); - SP_OBJECT_REPR(*item)->removeChild(repr); - SP_OBJECT_REPR(SP_OBJECT_PARENT(*item))->addChild(repr, SP_OBJECT_REPR(next)); + (*item)->getRepr()->removeChild(repr); + (*item)->parent->getRepr()->addChild(repr, next->getRepr()); Inkscape::GC::release(repr); next = next->getNext(); } @@ -1563,15 +1591,15 @@ static bool tidy_operator_repeated_spans(SPObject **item) SPObject *second = first->getNext(); if (second == NULL) return false; - Inkscape::XML::Node *first_repr = SP_OBJECT_REPR(first); - Inkscape::XML::Node *second_repr = SP_OBJECT_REPR(second); + Inkscape::XML::Node *first_repr = first->getRepr(); + Inkscape::XML::Node *second_repr = second->getRepr(); if (first_repr->type() != second_repr->type()) return false; if (SP_IS_STRING(first) && SP_IS_STRING(second)) { // also amalgamate consecutive SPStrings into one Glib::ustring merged_string = SP_STRING(first)->string + SP_STRING(second)->string; - SP_OBJECT_REPR(first)->setContent(merged_string.c_str()); + first->getRepr()->setContent(merged_string.c_str()); second_repr->parent()->removeChild(second_repr); return true; } @@ -1605,18 +1633,30 @@ static bool tidy_operator_repeated_spans(SPObject **item) -> abc */ static bool tidy_operator_excessive_nesting(SPObject **item) { - if (!(*item)->hasChildren()) return false; - if ((*item)->firstChild() != (*item)->lastChild()) return false; - if (SP_IS_FLOWREGION((*item)->firstChild()) || SP_IS_FLOWREGIONEXCLUDE((*item)->firstChild())) + if (!(*item)->hasChildren()) { return false; - if (SP_IS_STRING((*item)->firstChild())) return false; - if (is_line_break_object((*item)->firstChild())) return false; + } + if ((*item)->firstChild() != (*item)->lastChild()) { + return false; + } + if (SP_IS_FLOWREGION((*item)->firstChild()) || SP_IS_FLOWREGIONEXCLUDE((*item)->firstChild())) { + return false; + } + if (SP_IS_STRING((*item)->firstChild())) { + return false; + } + if (is_line_break_object((*item)->firstChild())) { + return false; + } TextTagAttributes *attrs = attributes_for_object((*item)->firstChild()); - if (attrs && attrs->anyAttributesSet()) return false; - gchar const *child_style = SP_OBJECT_REPR((*item)->firstChild())->attribute("style"); - if (child_style && *child_style) + if (attrs && attrs->anyAttributesSet()) { + return false; + } + gchar const *child_style = (*item)->firstChild()->getRepr()->attribute("style"); + if (child_style && *child_style) { overwrite_style_with_string(*item, child_style); - move_child_nodes(SP_OBJECT_REPR((*item)->firstChild()), SP_OBJECT_REPR(*item)); + } + move_child_nodes((*item)->firstChild()->getRepr(), (*item)->getRepr()); (*item)->firstChild()->deleteObject(); return true; } @@ -1624,26 +1664,37 @@ static bool tidy_operator_excessive_nesting(SPObject **item) /** helper for tidy_operator_redundant_double_nesting() */ static bool redundant_double_nesting_processor(SPObject **item, SPObject *child, bool prepend) { - if (SP_IS_FLOWREGION(child) || SP_IS_FLOWREGIONEXCLUDE(child)) + if (SP_IS_FLOWREGION(child) || SP_IS_FLOWREGIONEXCLUDE(child)) { return false; - if (SP_IS_STRING(child)) return false; - if (is_line_break_object(child)) return false; - if (is_line_break_object(*item)) return false; + } + if (SP_IS_STRING(child)) { + return false; + } + if (is_line_break_object(child)) { + return false; + } + if (is_line_break_object(*item)) { + return false; + } TextTagAttributes *attrs = attributes_for_object(child); - if (attrs && attrs->anyAttributesSet()) return false; - if (!objects_have_equal_style(SP_OBJECT_PARENT(*item), child)) return false; + if (attrs && attrs->anyAttributesSet()) { + return false; + } + if (!objects_have_equal_style((*item)->parent, child)) { + return false; + } Inkscape::XML::Node *insert_after_repr = 0; if (!prepend) { - insert_after_repr = SP_OBJECT_REPR(*item); + insert_after_repr = (*item)->getRepr(); } else if ((*item)->getPrev()) { - insert_after_repr = SP_OBJECT_REPR((*item)->getPrev()); + insert_after_repr = (*item)->getPrev()->getRepr(); } - while (SP_OBJECT_REPR(child)->childCount()) { - Inkscape::XML::Node *move_repr = SP_OBJECT_REPR(child)->firstChild(); + while (child->getRepr()->childCount()) { + Inkscape::XML::Node *move_repr = child->getRepr()->firstChild(); Inkscape::GC::anchor(move_repr); - SP_OBJECT_REPR(child)->removeChild(move_repr); - SP_OBJECT_REPR(SP_OBJECT_PARENT(*item))->addChild(move_repr, insert_after_repr); + child->getRepr()->removeChild(move_repr); + (*item)->parent->getRepr()->addChild(move_repr, insert_after_repr); Inkscape::GC::release(move_repr); insert_after_repr = move_repr; // I think this will stay valid long enough. It's garbage collected these days. } @@ -1686,11 +1737,11 @@ static bool redundant_semi_nesting_processor(SPObject **item, SPObject *child, b SPCSSAttr *css_child_and_item = sp_repr_css_attr_new(); SPCSSAttr *css_child_only = sp_repr_css_attr_new(); - gchar const *item_style = SP_OBJECT_REPR(*item)->attribute("style"); + gchar const *item_style = (*item)->getRepr()->attribute("style"); if (item_style && *item_style) { sp_repr_css_attr_add_from_string(css_child_and_item, item_style); } - gchar const *child_style = SP_OBJECT_REPR(child)->attribute("style"); + gchar const *child_style = child->getRepr()->attribute("style"); if (child_style && *child_style) { sp_repr_css_attr_add_from_string(css_child_and_item, child_style); sp_repr_css_attr_add_from_string(css_child_only, child_style); @@ -1700,15 +1751,16 @@ static bool redundant_semi_nesting_processor(SPObject **item, SPObject *child, b sp_repr_css_attr_unref(css_child_only); if (!equal) return false; - Inkscape::XML::Document *xml_doc = SP_OBJECT_REPR(*item)->document(); - Inkscape::XML::Node *new_span = xml_doc->createElement(SP_OBJECT_REPR(*item)->name()); + Inkscape::XML::Document *xml_doc = (*item)->getRepr()->document(); + Inkscape::XML::Node *new_span = xml_doc->createElement((*item)->getRepr()->name()); if (prepend) { SPObject *prev = (*item)->getPrev(); - SP_OBJECT_REPR(SP_OBJECT_PARENT(*item))->addChild(new_span, prev ? SP_OBJECT_REPR(prev) : NULL); - } else + (*item)->parent->getRepr()->addChild(new_span, prev ? prev->getRepr() : NULL); + } else { SP_OBJECT_REPR(SP_OBJECT_PARENT(*item))->addChild(new_span, SP_OBJECT_REPR(*item)); - new_span->setAttribute("style", SP_OBJECT_REPR(child)->attribute("style")); - move_child_nodes(SP_OBJECT_REPR(child), new_span); + } + new_span->setAttribute("style", child->getRepr()->attribute("style")); + move_child_nodes(child->getRepr(), new_span); Inkscape::GC::release(new_span); child->deleteObject(); return true; @@ -1751,10 +1803,15 @@ static SPString* find_last_string_child_not_equal_to(SPObject *root, SPObject *n -> abcdef ghi */ static bool tidy_operator_styled_whitespace(SPObject **item) { - if (!SP_IS_STRING(*item)) return false; + if (!SP_IS_STRING(*item)) { + return false; + } Glib::ustring const &str = SP_STRING(*item)->string; - for (Glib::ustring::const_iterator it = str.begin() ; it != str.end() ; ++it) - if (!g_unichar_isspace(*it)) return false; + for (Glib::ustring::const_iterator it = str.begin() ; it != str.end() ; ++it) { + if (!g_unichar_isspace(*it)) { + return false; + } + } SPObject *test_item = *item; SPString *next_string; @@ -1765,9 +1822,13 @@ static bool tidy_operator_styled_whitespace(SPObject **item) break; } for ( ; ; ) { // go up one item in the xml - test_item = SP_OBJECT_PARENT(test_item); - if (is_line_break_object(test_item)) break; - if (SP_IS_FLOWTEXT(test_item)) return false; + test_item = test_item->parent; + if (is_line_break_object(test_item)) { + break; + } + if (SP_IS_FLOWTEXT(test_item)) { + return false; + } SPObject *next = test_item->getNext(); if (next) { test_item = next; @@ -1776,12 +1837,14 @@ static bool tidy_operator_styled_whitespace(SPObject **item) } if (is_line_break_object(test_item)) { // no next string, see if there's a prev string next_string = find_last_string_child_not_equal_to(test_item, *item); - if (next_string == NULL) return false; // an empty paragraph + if (next_string == NULL) { + return false; // an empty paragraph + } next_string->string += str; break; } } - SP_OBJECT_REPR(next_string)->setContent(next_string->string.c_str()); + next_string->getRepr()->setContent(next_string->string.c_str()); SPObject *delete_obj = *item; *item = (*item)->getNext(); delete_obj->deleteObject(); diff --git a/src/tweak-context.cpp b/src/tweak-context.cpp index 999ee877f..c1ab82af8 100644 --- a/src/tweak-context.cpp +++ b/src/tweak-context.cpp @@ -416,7 +416,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P GSList *items = g_slist_prepend (NULL, item); GSList *selected = NULL; GSList *to_select = NULL; - SPDocument *doc = SP_OBJECT_DOCUMENT(item); + SPDocument *doc = item->document; sp_item_list_to_curves (items, &selected, &to_select); g_slist_free (items); SPObject* newObj = doc->getObjectByRepr((Inkscape::XML::Node *) to_select->data); @@ -521,13 +521,13 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P double chance = g_random_double_range(0, 1); if (chance <= prob) { if (reverse) { // delete - sp_object_ref(SP_OBJECT(item), NULL); - SP_OBJECT(item)->deleteObject(true, true); - sp_object_unref(SP_OBJECT(item), NULL); + sp_object_ref(item, NULL); + item->deleteObject(true, true); + sp_object_unref(item, NULL); } else { // duplicate - SPDocument *doc = SP_OBJECT_DOCUMENT(item); + SPDocument *doc = item->document; Inkscape::XML::Document* xml_doc = doc->getReprDoc(); - Inkscape::XML::Node *old_repr = SP_OBJECT_REPR(item); + Inkscape::XML::Node *old_repr = item->getRepr(); SPObject *old_obj = doc->getObjectByRepr(old_repr); Inkscape::XML::Node *parent = old_repr->parent(); Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc); @@ -555,11 +555,11 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P return false; // remember the position of the item - pos = SP_OBJECT_REPR(item)->position(); + pos = item->getRepr()->position(); // remember parent - parent = SP_OBJECT_REPR(item)->parent(); + parent = item->getRepr()->parent(); // remember id - id = SP_OBJECT_REPR(item)->attribute("id"); + id = item->getRepr()->attribute("id"); } @@ -587,7 +587,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P orig->ConvertWithBackData((0.08 - (0.07 * fidelity)) / i2doc.descrim()); // default 0.059 orig->Fill(theShape, 0); - SPCSSAttr *css = sp_repr_css_attr(SP_OBJECT_REPR(item), "style"); + SPCSSAttr *css = sp_repr_css_attr(item->getRepr(), "style"); gchar const *val = sp_repr_css_property(css, "fill-rule", NULL); if (val && strcmp(val, "nonzero") == 0) { @@ -650,7 +650,7 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P selection->remove(item); // It's going to resurrect, so we delete without notifying listeners. - SP_OBJECT(item)->deleteObject(false); + item->deleteObject(false); // restore id newrepr->setAttribute("id", id); @@ -669,9 +669,9 @@ sp_tweak_dilate_recursive (Inkscape::Selection *selection, SPItem *item, Geom::P newrepr->setAttribute("d", str); } else { if (SP_IS_LPE_ITEM(item) && sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(item))) { - SP_OBJECT_REPR(item)->setAttribute("inkscape:original-d", str); + item->getRepr()->setAttribute("inkscape:original-d", str); } else { - SP_OBJECT_REPR(item)->setAttribute("d", str); + item->getRepr()->setAttribute("d", str); } } g_free(str); @@ -886,7 +886,7 @@ tweak_colors_in_gradient (SPItem *item, bool fill_or_stroke, tweak_color (mode, SP_STOP(child_prev)->specified_color.v.c, rgb_goal, force * (offset_h - pos_e) / (offset_h - offset_l), do_h, do_s, do_l); - SP_OBJECT(stop)->updateRepr(); + stop->updateRepr(); child_prev->updateRepr(); break; } else { @@ -903,7 +903,7 @@ tweak_colors_in_gradient (SPItem *item, bool fill_or_stroke, tweak_color (mode, stop->specified_color.v.c, rgb_goal, force * tweak_profile (fabs (pos_e - offset_h), r), do_h, do_s, do_l); - SP_OBJECT(stop)->updateRepr(); + stop->updateRepr(); } } } @@ -938,7 +938,7 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point, } } else { - SPStyle *style = SP_OBJECT_STYLE(item); + SPStyle *style = item->style; if (!style) { return false; } @@ -1012,7 +1012,7 @@ sp_tweak_color_recursive (guint mode, SPItem *item, SPItem *item_at_point, remove_filter(item, false); } else { double radius = blur_new * perimeter; - SPFilter *filter = modify_filter_gaussian_blur_from_item(SP_OBJECT_DOCUMENT(item), item, radius); + SPFilter *filter = modify_filter_gaussian_blur_from_item(item->document, item, radius); sp_style_set_property_url(item, "filter", filter, false); } diff --git a/src/ui/context-menu.cpp b/src/ui/context-menu.cpp index c544d1999..8e50897e8 100644 --- a/src/ui/context-menu.cpp +++ b/src/ui/context-menu.cpp @@ -278,20 +278,20 @@ sp_item_create_link(GtkMenuItem *menuitem, SPItem *item) Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); Inkscape::XML::Node *repr = xml_doc->createElement("svg:a"); - SP_OBJECT_REPR(SP_OBJECT_PARENT(item))->addChild(repr, SP_OBJECT_REPR(item)); - SPObject *object = SP_OBJECT_DOCUMENT(item)->getObjectByRepr(repr); + item->parent->getRepr()->addChild(repr, item->getRepr()); + SPObject *object = item->document->getObjectByRepr(repr); g_return_if_fail(SP_IS_ANCHOR(object)); - const char *id = SP_OBJECT_REPR(item)->attribute("id"); - Inkscape::XML::Node *child = SP_OBJECT_REPR(item)->duplicate(xml_doc); - SP_OBJECT(item)->deleteObject(false); + const char *id = item->getRepr()->attribute("id"); + Inkscape::XML::Node *child = item->getRepr()->duplicate(xml_doc); + item->deleteObject(false); repr->addChild(child, NULL); child->setAttribute("id", id); Inkscape::GC::release(repr); Inkscape::GC::release(child); - DocumentUndo::done(SP_OBJECT_DOCUMENT(object), SP_VERB_NONE, + DocumentUndo::done(object->document, SP_VERB_NONE, _("Create link")); sp_object_attributes_dialog(object, "SPAnchor"); @@ -371,7 +371,7 @@ sp_anchor_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m) static void sp_anchor_link_properties(GtkMenuItem */*menuitem*/, SPAnchor *anchor) { - sp_object_attributes_dialog(SP_OBJECT(anchor), "Link"); + sp_object_attributes_dialog(anchor, "Link"); } static void @@ -420,7 +420,7 @@ sp_image_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m) gtk_signal_connect(GTK_OBJECT(w), "activate", GTK_SIGNAL_FUNC(sp_image_image_edit), item); gtk_widget_show(w); gtk_menu_append(GTK_MENU(m), w); - Inkscape::XML::Node *ir = SP_OBJECT_REPR(object); + Inkscape::XML::Node *ir = object->getRepr(); const gchar *href = ir->attribute("xlink:href"); if ( (!href) || ((strncmp(href, "data:", 5) == 0)) ) { gtk_widget_set_sensitive( w, FALSE ); @@ -430,7 +430,7 @@ sp_image_menu(SPObject *object, SPDesktop *desktop, GtkMenu *m) static void sp_image_image_properties(GtkMenuItem */*menuitem*/, SPAnchor *anchor) { - sp_object_attributes_dialog(SP_OBJECT(anchor), "Image"); + sp_object_attributes_dialog(anchor, "Image"); } static gchar* getImageEditorName() { @@ -455,8 +455,8 @@ static gchar* getImageEditorName() { static void sp_image_image_edit(GtkMenuItem *menuitem, SPAnchor *anchor) { - SPObject* obj = SP_OBJECT(anchor); - Inkscape::XML::Node *ir = SP_OBJECT_REPR(obj); + SPObject* obj = anchor; + Inkscape::XML::Node *ir = obj->getRepr(); const gchar *href = ir->attribute("xlink:href"); GError* errThing = 0; diff --git a/src/ui/dialog/guides.cpp b/src/ui/dialog/guides.cpp index 1ab0d51bc..bd9777048 100644 --- a/src/ui/dialog/guides.cpp +++ b/src/ui/dialog/guides.cpp @@ -109,7 +109,7 @@ void GuidelinePropertiesDialog::_onApply() sp_guide_moveto(*_guide, newpos, true); - DocumentUndo::done(SP_OBJECT_DOCUMENT(_guide), SP_VERB_NONE, + DocumentUndo::done(_guide->document, SP_VERB_NONE, _("Set guide properties")); } @@ -120,7 +120,7 @@ void GuidelinePropertiesDialog::_onOK() void GuidelinePropertiesDialog::_onDelete() { - SPDocument *doc = SP_OBJECT_DOCUMENT(_guide); + SPDocument *doc = _guide->document; sp_guide_remove(_guide); DocumentUndo::done(doc, SP_VERB_NONE, _("Delete guide")); @@ -235,7 +235,7 @@ void GuidelinePropertiesDialog::_setup() { } { - Inkscape::XML::Node *repr = SP_OBJECT_REPR (_guide); + Inkscape::XML::Node *repr = _guide->getRepr(); const gchar *guide_id = repr->attribute("id"); gchar *label = g_strdup_printf(_("Guideline ID: %s"), guide_id); _label_name.set_label(label); diff --git a/src/ui/dialog/icon-preview.cpp b/src/ui/dialog/icon-preview.cpp index b507d9f9a..bb566fb7f 100644 --- a/src/ui/dialog/icon-preview.cpp +++ b/src/ui/dialog/icon-preview.cpp @@ -355,7 +355,7 @@ void IconPreviewPanel::refreshPreview() GSList const *items = sel->itemList(); while ( items && !target ) { SPItem* item = SP_ITEM( items->data ); - SPObject * obj = SP_OBJECT(item); + SPObject * obj = item; gchar const *id = obj->getId(); if ( id ) { targetId = id; @@ -427,7 +427,7 @@ void IconPreviewPanel::modeToggled() void IconPreviewPanel::renderPreview( SPObject* obj ) { - SPDocument * doc = SP_OBJECT_DOCUMENT(obj); + SPDocument * doc = obj->document; gchar const * id = obj->getId(); if ( !renderTimer ) { renderTimer = new Glib::Timer(); diff --git a/src/uri-references.cpp b/src/uri-references.cpp index d979fe292..2c09695d4 100644 --- a/src/uri-references.cpp +++ b/src/uri-references.cpp @@ -47,7 +47,7 @@ void URIReference::attach(const URI &uri) throw(BadURIException) { SPDocument *document; if (_owner) { - document = SP_OBJECT_DOCUMENT(_owner); + document = _owner->document; } else if (_owner_document) { document = _owner_document; } else { diff --git a/src/widgets/gradient-selector.cpp b/src/widgets/gradient-selector.cpp index 49549de1c..f7a981c9f 100644 --- a/src/widgets/gradient-selector.cpp +++ b/src/widgets/gradient-selector.cpp @@ -259,7 +259,7 @@ SPGradientSpread SPGradientSelector::getSpread() void SPGradientSelector::setVector(SPDocument *doc, SPGradient *vector) { g_return_if_fail(!vector || SP_IS_GRADIENT(vector)); - g_return_if_fail(!vector || (SP_OBJECT_DOCUMENT(vector) == doc)); + g_return_if_fail(!vector || (vector->document == doc)); if (vector && !vector->hasStops()) { return; @@ -312,7 +312,7 @@ sp_gradient_selector_vector_set (SPGradientVectorSelector */*gvs*/, SPGradient * if (!blocked) { blocked = TRUE; gr = sp_gradient_ensure_vector_normalized (gr); - sel->setVector((gr) ? SP_OBJECT_DOCUMENT (gr) : 0, gr); + sel->setVector((gr) ? gr->document : 0, gr); g_signal_emit (G_OBJECT (sel), signals[CHANGED], 0, gr); blocked = FALSE; } @@ -344,9 +344,9 @@ sp_gradient_selector_add_vector_clicked (GtkWidget */*w*/, SPGradientSelector *s Inkscape::XML::Node *repr = NULL; - if (gr) - repr = SP_OBJECT_REPR (gr)->duplicate(xml_doc); - else { + if (gr) { + repr = gr->getRepr()->duplicate(xml_doc); + } else { repr = xml_doc->createElement("svg:linearGradient"); Inkscape::XML::Node *stop = xml_doc->createElement("svg:stop"); stop->setAttribute("offset", "0"); @@ -360,7 +360,7 @@ sp_gradient_selector_add_vector_clicked (GtkWidget */*w*/, SPGradientSelector *s Inkscape::GC::release(stop); } - SP_OBJECT_REPR (SP_DOCUMENT_DEFS (doc))->addChild(repr, NULL); + SP_DOCUMENT_DEFS(doc)->getRepr()->addChild(repr, NULL); gr = (SPGradient *) doc->getObjectByRepr(repr); sp_gradient_vector_selector_set_gradient( diff --git a/src/widgets/gradient-vector.cpp b/src/widgets/gradient-vector.cpp index 1be0aae8e..839ddf67c 100644 --- a/src/widgets/gradient-vector.cpp +++ b/src/widgets/gradient-vector.cpp @@ -162,7 +162,7 @@ GtkWidget *sp_gradient_vector_selector_new(SPDocument *doc, SPGradient *gr) GtkWidget *gvs; g_return_val_if_fail(!gr || SP_IS_GRADIENT(gr), NULL); - g_return_val_if_fail(!gr || (SP_OBJECT_DOCUMENT(gr) == doc), NULL); + g_return_val_if_fail(!gr || (gr->document == doc), NULL); gvs = static_cast(gtk_type_new(SP_TYPE_GRADIENT_VECTOR_SELECTOR)); @@ -187,7 +187,7 @@ void sp_gradient_vector_selector_set_gradient(SPGradientVectorSelector *gvs, SPD g_return_if_fail(SP_IS_GRADIENT_VECTOR_SELECTOR(gvs)); g_return_if_fail(!gr || (doc != NULL)); g_return_if_fail(!gr || SP_IS_GRADIENT(gr)); - g_return_if_fail(!gr || (SP_OBJECT_DOCUMENT(gr) == doc)); + g_return_if_fail(!gr || (gr->document == doc)); g_return_if_fail(!gr || gr->hasStops()); if (doc != gvs->doc) { @@ -256,7 +256,7 @@ static void sp_gvs_rebuild_gui_full(SPGradientVectorSelector *gvs) /* Pick up all gradients with vectors */ GSList *gl = NULL; if (gvs->gr) { - const GSList *gradients = SP_OBJECT_DOCUMENT(gvs->gr)->getResourceList("gradient"); + const GSList *gradients = gvs->gr->document->getResourceList("gradient"); for (const GSList *curr = gradients; curr; curr = curr->next) { SPGradient* grad = SP_GRADIENT(curr->data); if ( grad->hasStops() && (grad->isSwatch() == gvs->swatched) ) { @@ -371,7 +371,7 @@ static void sp_gvs_gradient_activate(GtkMenuItem *mi, SPGradientVectorSelector * /* We do extra undo push here */ /* If handler has already done it, it is just NOP */ // FIXME: looks like this is never a valid undo step, consider removing this - DocumentUndo::done(SP_OBJECT_DOCUMENT(norm), SP_VERB_CONTEXT_GRADIENT, + DocumentUndo::done(norm->document, SP_VERB_CONTEXT_GRADIENT, /* TODO: annotate */ "gradient-vector.cpp:350"); } } @@ -479,7 +479,7 @@ static void verify_grad(SPGradient *gradient) } Inkscape::XML::Document *xml_doc; - xml_doc = SP_OBJECT_REPR(gradient)->document(); + xml_doc = gradient->getRepr()->document(); if (i < 1) { Inkscape::CSSOStringStream os; @@ -490,20 +490,20 @@ static void verify_grad(SPGradient *gradient) child = xml_doc->createElement("svg:stop"); sp_repr_set_css_double(child, "offset", 0.0); child->setAttribute("style", os.str().c_str()); - SP_OBJECT_REPR(gradient)->addChild(child, NULL); + gradient->getRepr()->addChild(child, NULL); Inkscape::GC::release(child); child = xml_doc->createElement("svg:stop"); sp_repr_set_css_double(child, "offset", 1.0); child->setAttribute("style", os.str().c_str()); - SP_OBJECT_REPR(gradient)->addChild(child, NULL); + gradient->getRepr()->addChild(child, NULL); Inkscape::GC::release(child); } if (i < 2) { - sp_repr_set_css_double(SP_OBJECT_REPR(stop), "offset", 0.0); - Inkscape::XML::Node *child = SP_OBJECT_REPR(stop)->duplicate(SP_OBJECT_REPR(gradient)->document()); + sp_repr_set_css_double(stop->getRepr(), "offset", 0.0); + Inkscape::XML::Node *child = stop->getRepr()->duplicate(gradient->getRepr()->document()); sp_repr_set_css_double(child, "offset", 1.0); - SP_OBJECT_REPR(gradient)->addChild(child, SP_OBJECT_REPR(stop)); + gradient->getRepr()->addChild(child, stop->getRepr()); Inkscape::GC::release(child); } } @@ -513,7 +513,7 @@ static void select_stop_in_list( GtkWidget *mnu, SPGradient *gradient, SPStop *n int i = 0; for ( SPObject *ochild = gradient->firstChild() ; ochild ; ochild = ochild->getNext() ) { if (SP_IS_STOP(ochild)) { - if (SP_OBJECT(ochild) == SP_OBJECT(new_stop)) { + if (ochild == new_stop) { gtk_option_menu_set_history(GTK_OPTION_MENU(mnu), i); break; } @@ -565,7 +565,7 @@ static void update_stop_list( GtkWidget *mnu, SPGradient *gradient, SPStop *new_ gtk_widget_show(cpv); gtk_container_add( GTK_CONTAINER(hb), cpv ); g_object_set_data( G_OBJECT(i), "preview", cpv ); - Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) sl->data); + Inkscape::XML::Node *repr = reinterpret_cast(sl->data)->getRepr(); GtkWidget *l = gtk_label_new(repr->attribute("id")); gtk_widget_show(l); gtk_misc_set_alignment(GTK_MISC(l), 1.0, 0.5); @@ -659,9 +659,9 @@ static void offadjustmentChanged( GtkAdjustment *adjustment, GtkWidget *vb) SPStop *stop = SP_STOP(g_object_get_data(G_OBJECT(gtk_menu_get_active(GTK_MENU(gtk_option_menu_get_menu(mnu)))), "stop")); stop->offset = adjustment->value; - sp_repr_set_css_double(SP_OBJECT_REPR(stop), "offset", stop->offset); + sp_repr_set_css_double(stop->getRepr(), "offset", stop->offset); - DocumentUndo::maybeDone(SP_OBJECT_DOCUMENT(stop), "gradient:stop:offset", SP_VERB_CONTEXT_GRADIENT, + DocumentUndo::maybeDone(stop->document, "gradient:stop:offset", SP_VERB_CONTEXT_GRADIENT, _("Change gradient stop offset")); blocked = FALSE; @@ -705,15 +705,15 @@ static void sp_grd_ed_add_stop(GtkWidget */*widget*/, GtkWidget *vb) } if (next != NULL) { - new_stop_repr = SP_OBJECT_REPR(stop)->duplicate(SP_OBJECT_REPR(gradient)->document()); - SP_OBJECT_REPR(gradient)->addChild(new_stop_repr, SP_OBJECT_REPR(stop)); + new_stop_repr = stop->getRepr()->duplicate(gradient->getRepr()->document()); + gradient->getRepr()->addChild(new_stop_repr, stop->getRepr()); } else { next = stop; - new_stop_repr = SP_OBJECT_REPR(stop->getPrevStop())->duplicate(SP_OBJECT_REPR(gradient)->document()); - SP_OBJECT_REPR(gradient)->addChild(new_stop_repr, SP_OBJECT_REPR(stop->getPrevStop())); + new_stop_repr = stop->getPrevStop()->getRepr()->duplicate(gradient->getRepr()->document()); + gradient->getRepr()->addChild(new_stop_repr, stop->getPrevStop()->getRepr()); } - SPStop *newstop = (SPStop *) SP_OBJECT_DOCUMENT(gradient)->getObjectByRepr(new_stop_repr); + SPStop *newstop = reinterpret_cast(gradient->document->getObjectByRepr(new_stop_repr)); newstop->offset = (stop->offset + next->offset) * 0.5 ; @@ -726,8 +726,8 @@ static void sp_grd_ed_add_stop(GtkWidget */*widget*/, GtkWidget *vb) sp_svg_write_color(c, sizeof(c), cnew); gdouble opacity = static_cast(SP_RGBA32_A_F(cnew)); os << "stop-color:" << c << ";stop-opacity:" << opacity <<";"; - SP_OBJECT_REPR (newstop)->setAttribute("style", os.str().c_str()); - sp_repr_set_css_double( SP_OBJECT_REPR(newstop), "offset", (double)newstop->offset); + newstop->getRepr()->setAttribute("style", os.str().c_str()); + sp_repr_set_css_double( newstop->getRepr(), "offset", (double)newstop->offset); sp_gradient_vector_widget_load_gradient(vb, gradient); Inkscape::GC::release(new_stop_repr); @@ -736,7 +736,7 @@ static void sp_grd_ed_add_stop(GtkWidget */*widget*/, GtkWidget *vb) GtkWidget *offslide =GTK_WIDGET(g_object_get_data(G_OBJECT(vb), "offslide")); gtk_widget_set_sensitive(offslide, TRUE); gtk_widget_set_sensitive(GTK_WIDGET(offspin), TRUE); - DocumentUndo::done(SP_OBJECT_DOCUMENT(gradient), SP_VERB_CONTEXT_GRADIENT, + DocumentUndo::done(gradient->document, SP_VERB_CONTEXT_GRADIENT, _("Add gradient stop")); } @@ -754,20 +754,20 @@ static void sp_grd_ed_del_stop(GtkWidget */*widget*/, GtkWidget *vb) SPStop *next = stop->getNextStop(); if (next) { next->offset = 0; - sp_repr_set_css_double(SP_OBJECT_REPR(next), "offset", 0); + sp_repr_set_css_double(next->getRepr(), "offset", 0); } } else if (stop->offset == 1) { SPStop *prev = stop->getPrevStop(); if (prev) { prev->offset = 1; - sp_repr_set_css_double(SP_OBJECT_REPR(prev), "offset", 1); + sp_repr_set_css_double(prev->getRepr(), "offset", 1); } } - SP_OBJECT_REPR(gradient)->removeChild(SP_OBJECT_REPR(stop)); + gradient->getRepr()->removeChild(stop->getRepr()); sp_gradient_vector_widget_load_gradient(vb, gradient); update_stop_list(GTK_WIDGET(mnu), gradient, NULL); - DocumentUndo::done(SP_OBJECT_DOCUMENT(gradient), SP_VERB_CONTEXT_GRADIENT, + DocumentUndo::done(gradient->document, SP_VERB_CONTEXT_GRADIENT, _("Delete gradient stop")); } @@ -787,7 +787,7 @@ static GtkWidget * sp_gradient_vector_widget_new(SPGradient *gradient, SPStop *s gtk_widget_show(w); gtk_box_pack_start(GTK_BOX(vb), w, TRUE, TRUE, PAD); - sp_repr_add_listener(SP_OBJECT_REPR(gradient), &grad_edit_dia_repr_events, vb); + sp_repr_add_listener(gradient->getRepr(), &grad_edit_dia_repr_events, vb); GtkTooltips *tt = gtk_tooltips_new(); /* Stop list */ @@ -1031,11 +1031,11 @@ static void sp_gradient_vector_widget_load_gradient(GtkWidget *widget, SPGradien update_stop_list(GTK_WIDGET(mnu), gradient, NULL); // Once the user edits a gradient, it stops being auto-collectable - if (SP_OBJECT_REPR(gradient)->attribute("inkscape:collect")) { - SPDocument *document = SP_OBJECT_DOCUMENT(gradient); + if (gradient->getRepr()->attribute("inkscape:collect")) { + SPDocument *document = gradient->document; bool saved = DocumentUndo::getUndoSensitive(document); DocumentUndo::setUndoSensitive(document, false); - SP_OBJECT_REPR(gradient)->setAttribute("inkscape:collect", NULL); + gradient->getRepr()->setAttribute("inkscape:collect", NULL); DocumentUndo::setUndoSensitive(document, saved); } } else { // no gradient, disable everything @@ -1077,9 +1077,7 @@ static gboolean sp_gradient_vector_dialog_delete(GtkWidget */*widget*/, GdkEvent static void sp_gradient_vector_widget_destroy(GtkObject *object, gpointer /*data*/) { - GObject *gradient; - - gradient = (GObject*)g_object_get_data(G_OBJECT(object), "gradient"); + SPObject *gradient = reinterpret_cast(g_object_get_data(G_OBJECT(object), "gradient")); sigc::connection *release_connection = (sigc::connection *)g_object_get_data(G_OBJECT(object), "gradient_release_connection"); sigc::connection *modified_connection = (sigc::connection *)g_object_get_data(G_OBJECT(object), "gradient_modified_connection"); @@ -1092,8 +1090,8 @@ static void sp_gradient_vector_widget_destroy(GtkObject *object, gpointer /*data sp_signal_disconnect_by_data(gradient, object); } - if (gradient && SP_OBJECT_REPR(gradient)) { - sp_repr_remove_listener_by_data(SP_OBJECT_REPR(gradient), object); + if (gradient && gradient->getRepr()) { + sp_repr_remove_listener_by_data(gradient->getRepr(), object); } } @@ -1178,14 +1176,14 @@ static void sp_gradient_vector_color_changed(SPColorSelector *csel, GtkObject *o float alpha = 0; csel->base->getColorAlpha( color, alpha ); - sp_repr_set_css_double(SP_OBJECT_REPR(stop), "offset", stop->offset); + sp_repr_set_css_double(stop->getRepr(), "offset", stop->offset); Inkscape::CSSOStringStream os; os << "stop-color:" << color.toString() << ";stop-opacity:" << static_cast(alpha) <<";"; - SP_OBJECT_REPR(stop)->setAttribute("style", os.str().c_str()); + stop->getRepr()->setAttribute("style", os.str().c_str()); // g_snprintf(c, 256, "stop-color:#%06x;stop-opacity:%g;", rgb >> 8, static_cast(alpha)); - //SP_OBJECT_REPR(stop)->setAttribute("style", c); + //stop->getRepr()->setAttribute("style", c); - DocumentUndo::done(SP_OBJECT_DOCUMENT(ngr), SP_VERB_CONTEXT_GRADIENT, + DocumentUndo::done(ngr->document, SP_VERB_CONTEXT_GRADIENT, _("Change gradient stop color")); blocked = FALSE; diff --git a/src/widgets/paint-selector.cpp b/src/widgets/paint-selector.cpp index 1d8acb40a..7b513a4d7 100644 --- a/src/widgets/paint-selector.cpp +++ b/src/widgets/paint-selector.cpp @@ -457,7 +457,7 @@ void SPPaintSelector::setSwatch(SPGradient *vector ) SwatchSelector *swatchsel = static_cast(g_object_get_data(G_OBJECT(selector), "swatch-selector")); if (swatchsel) { - swatchsel->setVector( (vector) ? SP_OBJECT_DOCUMENT(vector) : 0, vector ); + swatchsel->setVector( (vector) ? vector->document : 0, vector ); } } @@ -471,7 +471,7 @@ void SPPaintSelector::setGradientLinear(SPGradient *vector) SPGradientSelector *gsel = getGradientFromData(this); gsel->setMode(SPGradientSelector::MODE_LINEAR); - gsel->setVector((vector) ? SP_OBJECT_DOCUMENT(vector) : 0, vector); + gsel->setVector((vector) ? vector->document : 0, vector); } void SPPaintSelector::setGradientRadial(SPGradient *vector) @@ -485,7 +485,7 @@ void SPPaintSelector::setGradientRadial(SPGradient *vector) gsel->setMode(SPGradientSelector::MODE_RADIAL); - gsel->setVector((vector) ? SP_OBJECT_DOCUMENT(vector) : 0, vector); + gsel->setVector((vector) ? vector->document : 0, vector); } void SPPaintSelector::setGradientProperties( SPGradientUnits units, SPGradientSpread spread ) @@ -541,7 +541,7 @@ void SPPaintSelector::pushAttrsToGradient( SPGradient *gr ) const getGradientProperties( units, spread ); gr->setUnits(units); gr->setSpread(spread); - SP_OBJECT(gr)->updateRepr(); + gr->updateRepr(); } static void @@ -804,7 +804,7 @@ sp_pattern_menu_build (GtkWidget *m, GSList *pattern_list, SPDocument */*source* { for (; pattern_list != NULL; pattern_list = pattern_list->next) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) pattern_list->data); + Inkscape::XML::Node *repr = reinterpret_cast(pattern_list->data)->getRepr(); GtkWidget *i = gtk_menu_item_new(); gtk_widget_show(i); diff --git a/src/widgets/sp-attribute-widget.cpp b/src/widgets/sp-attribute-widget.cpp index 0c31c2f74..a64a03f4e 100644 --- a/src/widgets/sp-attribute-widget.cpp +++ b/src/widgets/sp-attribute-widget.cpp @@ -154,14 +154,12 @@ sp_attribute_widget_changed (GtkEditable *editable) if (!*text) text = NULL; - if (spaw->hasobj && spaw->src.object) { - - SP_OBJECT_REPR (spaw->src.object)->setAttribute(spaw->attribute, text, false); - DocumentUndo::done(SP_OBJECT_DOCUMENT (spaw->src.object), SP_VERB_NONE, + if (spaw->hasobj && spaw->src.object) { + spaw->src.object->getRepr()->setAttribute(spaw->attribute, text, false); + DocumentUndo::done(spaw->src.object->document, SP_VERB_NONE, _("Set attribute")); } else if (spaw->src.repr) { - spaw->src.repr->setAttribute(spaw->attribute, text, false); /* TODO: Warning! Undo will not be flushed in given case */ } @@ -248,7 +246,7 @@ sp_attribute_widget_set_object ( SPAttributeWidget *spaw, spaw->attribute = g_strdup (attribute); - val = SP_OBJECT_REPR (object)->attribute(attribute); + val = object->getRepr()->attribute(attribute); gtk_entry_set_text (GTK_ENTRY (spaw), val ? val : (const gchar *) ""); spaw->blocked = FALSE; } @@ -317,7 +315,7 @@ sp_attribute_widget_object_modified ( SPObject */*object*/, if (flags && SP_OBJECT_MODIFIED_FLAG) { const gchar *val, *text; - val = SP_OBJECT_REPR (spaw->src.object)->attribute(spaw->attribute); + val = spaw->src.object->getRepr()->attribute(spaw->attribute); text = gtk_entry_get_text (GTK_ENTRY (spaw)); if (val || text) { @@ -588,7 +586,7 @@ sp_attribute_table_set_object ( SPAttributeTable *spat, XPAD, YPAD ); w = gtk_entry_new (); gtk_widget_show (w); - val = SP_OBJECT_REPR (object)->attribute(attributes[i]); + val = object->getRepr()->attribute(attributes[i]); gtk_entry_set_text (GTK_ENTRY (w), val ? val : (const gchar *) ""); gtk_table_attach ( GTK_TABLE (spat->table), w, 1, 2, i, i + 1, (GtkAttachOptions)(GTK_EXPAND | GTK_FILL), @@ -719,7 +717,7 @@ sp_attribute_table_object_modified ( SPObject */*object*/, gint i; for (i = 0; i < spat->num_attr; i++) { const gchar *val, *text; - val = SP_OBJECT_REPR (spat->src.object)->attribute(spat->attributes[i]); + val = spat->src.object->getRepr()->attribute(spat->attributes[i]); text = gtk_entry_get_text (GTK_ENTRY (spat->entries[i])); if (val || text) { if (!val || !text || strcmp (val, text)) { @@ -763,8 +761,8 @@ sp_attribute_table_entry_changed ( GtkEditable *editable, text = NULL; if (spat->hasobj && spat->src.object) { - SP_OBJECT_REPR (spat->src.object)->setAttribute(spat->attributes[i], text, false); - DocumentUndo::done(SP_OBJECT_DOCUMENT (spat->src.object), SP_VERB_NONE, + spat->src.object->getRepr()->setAttribute(spat->attributes[i], text, false); + DocumentUndo::done(spat->src.object->document, SP_VERB_NONE, _("Set attribute")); } else if (spat->src.repr) { diff --git a/src/widgets/stroke-style.cpp b/src/widgets/stroke-style.cpp index 9b79ed09e..555418269 100644 --- a/src/widgets/stroke-style.cpp +++ b/src/widgets/stroke-style.cpp @@ -161,11 +161,11 @@ sp_marker_prev_new(unsigned psize, gchar const *mname, // Create a copy repr of the marker with id="sample" Inkscape::XML::Document *xml_doc = sandbox->getReprDoc(); - Inkscape::XML::Node *mrepr = SP_OBJECT_REPR (marker)->duplicate(xml_doc); + Inkscape::XML::Node *mrepr = marker->getRepr()->duplicate(xml_doc); mrepr->setAttribute("id", "sample"); // Replace the old sample in the sandbox by the new one - Inkscape::XML::Node *defsrepr = SP_OBJECT_REPR (sandbox->getObjectById("defs")); + Inkscape::XML::Node *defsrepr = sandbox->getObjectById("defs")->getRepr(); SPObject *oldmarker = sandbox->getObjectById("sample"); if (oldmarker) oldmarker->deleteObject(false); @@ -225,7 +225,7 @@ ink_marker_list_get (SPDocument *source) GSList *ml = NULL; SPDefs *defs = (SPDefs *) SP_DOCUMENT_DEFS (source); - for ( SPObject *child = SP_OBJECT(defs)->firstChild(); child; child = child->getNext() ) + for ( SPObject *child = defs->firstChild(); child; child = child->getNext() ) { if (SP_IS_MARKER(child)) { ml = g_slist_prepend (ml, child); @@ -248,14 +248,15 @@ sp_marker_menu_build (Gtk::Menu *m, GSList *marker_list, SPDocument *source, SPD NRArenaItem *root = SP_ITEM(sandbox->getRoot())->invoke_show((NRArena *) arena, visionkey, SP_ITEM_SHOW_DISPLAY); for (; marker_list != NULL; marker_list = marker_list->next) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) marker_list->data); + Inkscape::XML::Node *repr = reinterpret_cast(marker_list->data)->getRepr(); Gtk::MenuItem *i = new Gtk::MenuItem(); i->show(); - if (repr->attribute("inkscape:stockid")) + if (repr->attribute("inkscape:stockid")) { i->set_data("stockid", (void *) "true"); - else + } else { i->set_data("stockid", (void *) "false"); + } gchar const *markid = repr->attribute("id"); i->set_data("marker", (void *) markid); @@ -468,7 +469,7 @@ sp_marker_select(Gtk::OptionMenu *mnu, Gtk::Container *spw, SPMarkerLoc const wh if (!strcmp(stockid,"true")) markurn = g_strconcat("urn:inkscape:marker:",markid,NULL); SPObject *mark = get_stock_item(markurn); if (mark) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR(mark); + Inkscape::XML::Node *repr = mark->getRepr(); marker = g_strconcat("url(#", repr->attribute("id"), ")", NULL); } } else { @@ -486,16 +487,17 @@ sp_marker_select(Gtk::OptionMenu *mnu, Gtk::Container *spw, SPMarkerLoc const wh Inkscape::Selection *selection = sp_desktop_selection(desktop); GSList const *items = selection->itemList(); for (; items != NULL; items = items->next) { - SPItem *item = (SPItem *) items->data; - if (!SP_IS_SHAPE(item) || SP_IS_RECT(item)) // can't set marker to rect, until it's converted to using - continue; - Inkscape::XML::Node *selrepr = SP_OBJECT_REPR((SPItem *) items->data); - if (selrepr) { - sp_repr_css_change_recursive(selrepr, css, "style"); - } - SP_OBJECT(items->data)->requestModified(SP_OBJECT_MODIFIED_FLAG); - SP_OBJECT(items->data)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); - } + SPItem *item = reinterpret_cast(items->data); + if (!SP_IS_SHAPE(item) || SP_IS_RECT(item)) { // can't set marker to rect, until it's converted to using + continue; + } + Inkscape::XML::Node *selrepr = item->getRepr(); + if (selrepr) { + sp_repr_css_change_recursive(selrepr, css, "style"); + } + item->requestModified(SP_OBJECT_MODIFIED_FLAG); + item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); + } sp_repr_css_attr_unref(css); css = 0; @@ -690,7 +692,7 @@ sp_stroke_style_line_widget_new(void) tt->set_tip(*sb, _("Stroke width")); sb->show(); spw_label(t, C_("Stroke width", "_Width:"), 0, i, sb); - + sp_dialog_defocus_on_enter_cpp(sb); hb->pack_start(*sb, false, false, 0); @@ -813,10 +815,10 @@ sp_stroke_style_line_widget_new(void) /* Dash */ spw_label(t, _("Dashes:"), 0, i, NULL); //no mnemonic for now - //decide what to do: - // implement a set_mnemonic_source function in the - // SPDashSelector class, so that we do not have to - // expose any of the underlying widgets? + //decide what to do: + // implement a set_mnemonic_source function in the + // SPDashSelector class, so that we do not have to + // expose any of the underlying widgets? ds = manage(new SPDashSelector); ds->show(); @@ -1091,7 +1093,7 @@ sp_stroke_style_line_update(Gtk::Container *spw, Inkscape::Selection *sel) GSList const *objects = sel->itemList(); SPObject * const object = SP_OBJECT(objects->data); - SPStyle * const style = SP_OBJECT_STYLE(object); + SPStyle * const style = object->style; /* Markers */ sp_stroke_style_update_marker_menus(spw, objects); // FIXME: make this desktop query too @@ -1174,7 +1176,7 @@ sp_stroke_style_scale_line(Gtk::Container *spw) if (unit->base == SP_UNIT_ABSOLUTE || unit->base == SP_UNIT_DEVICE) { width = sp_units_get_pixels (width_typed, *unit); } else { // percentage - gdouble old_w = SP_OBJECT_STYLE (i->data)->stroke_width.computed; + gdouble old_w = SP_OBJECT(i->data)->style->stroke_width.computed; width = old_w * width_typed / 100; } @@ -1362,14 +1364,16 @@ ink_marker_menu_set_current(SPObject *marker, Gtk::OptionMenu *mnu) Gtk::Menu *m = mnu->get_menu(); if (marker != NULL) { bool mark_is_stock = false; - if (SP_OBJECT_REPR(marker)->attribute("inkscape:stockid")) + if (marker->getRepr()->attribute("inkscape:stockid")) { mark_is_stock = true; + } - gchar *markname; - if (mark_is_stock) - markname = g_strdup(SP_OBJECT_REPR(marker)->attribute("inkscape:stockid")); - else - markname = g_strdup(SP_OBJECT_REPR(marker)->attribute("id")); + gchar *markname = 0; + if (mark_is_stock) { + markname = g_strdup(marker->getRepr()->attribute("inkscape:stockid")); + } else { + markname = g_strdup(marker->getRepr()->attribute("id")); + } int markpos = ink_marker_menu_get_pos(m, markname); mnu->set_history(markpos); @@ -1427,7 +1431,7 @@ sp_stroke_style_update_marker_menus(Gtk::Container *spw, GSList const *objects) // If the object has this type of markers, // Extract the name of the marker that the object uses - SPObject *marker = ink_extract_marker_name(object->style->marker[keyloc[i].loc].value, SP_OBJECT_DOCUMENT(object)); + SPObject *marker = ink_extract_marker_name(object->style->marker[keyloc[i].loc].value, object->document); // Scroll the menu to that marker ink_marker_menu_set_current(marker, mnu); diff --git a/src/widgets/swatch-selector.cpp b/src/widgets/swatch-selector.cpp index 935282a3a..cd624630b 100644 --- a/src/widgets/swatch-selector.cpp +++ b/src/widgets/swatch-selector.cpp @@ -133,9 +133,9 @@ void SwatchSelector::_changedCb(SPColorSelector */*csel*/, void *data) gchar c[64]; sp_svg_write_color(c, sizeof(c), rgb); os << "stop-color:" << c << ";stop-opacity:" << static_cast(alpha) <<";"; - SP_OBJECT_REPR(stop)->setAttribute("style", os.str().c_str()); + stop->getRepr()->setAttribute("style", os.str().c_str()); - DocumentUndo::done(SP_OBJECT_DOCUMENT(ngr), SP_VERB_CONTEXT_GRADIENT, + DocumentUndo::done(ngr->document, SP_VERB_CONTEXT_GRADIENT, _("Change swatch color")); } } @@ -169,7 +169,7 @@ void SwatchSelector::connectchangedHandler( GCallback handler, void *data ) void SwatchSelector::setVector(SPDocument */*doc*/, SPGradient *vector) { //GtkVBox * box = gobj(); - _gsel->setVector((vector) ? SP_OBJECT_DOCUMENT(vector) : 0, vector); + _gsel->setVector((vector) ? vector->document : 0, vector); if ( vector && vector->isSolid() ) { SPStop* stop = vector->getFirstStop(); diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index b488a0280..7ef864383 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -2041,14 +2041,14 @@ static void toggle_snap_callback(GtkToggleAction *act, gpointer data) //data poi SPDesktop *dt = reinterpret_cast(ptr); SPNamedView *nv = sp_desktop_namedview(dt); - SPDocument *doc = SP_OBJECT_DOCUMENT(nv); + SPDocument *doc = nv->document; if (dt == NULL || nv == NULL) { g_warning("No desktop or namedview specified (in toggle_snap_callback)!"); return; } - Inkscape::XML::Node *repr = SP_OBJECT_REPR(nv); + Inkscape::XML::Node *repr = nv->getRepr(); if (repr == NULL) { g_warning("This namedview doesn't have a xml representation attached!"); @@ -2520,13 +2520,14 @@ static void sp_stb_magnitude_value_changed( GtkAdjustment *adj, GObject *dataKlu Inkscape::Selection *selection = sp_desktop_selection(desktop); GSList const *items = selection->itemList(); for (; items != NULL; items = items->next) { - if (SP_IS_STAR((SPItem *) items->data)) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data); + SPItem *item = reinterpret_cast(items->data); + if (SP_IS_STAR(item)) { + Inkscape::XML::Node *repr = item->getRepr(); sp_repr_set_int(repr,"sodipodi:sides",(gint)adj->value); sp_repr_set_svg_double(repr, "sodipodi:arg2", (sp_repr_get_double_attribute(repr, "sodipodi:arg1", 0.5) + M_PI / (gint)adj->value)); - SP_OBJECT((SPItem *) items->data)->updateRepr(); + item->updateRepr(); modmade = true; } } @@ -2561,8 +2562,9 @@ static void sp_stb_proportion_value_changed( GtkAdjustment *adj, GObject *dataKl Inkscape::Selection *selection = sp_desktop_selection(desktop); GSList const *items = selection->itemList(); for (; items != NULL; items = items->next) { - if (SP_IS_STAR((SPItem *) items->data)) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data); + SPItem *item = reinterpret_cast(items->data); + if (SP_IS_STAR(item)) { + Inkscape::XML::Node *repr = item->getRepr(); gdouble r1 = sp_repr_get_double_attribute(repr, "sodipodi:r1", 1.0); gdouble r2 = sp_repr_get_double_attribute(repr, "sodipodi:r2", 1.0); @@ -2572,7 +2574,7 @@ static void sp_stb_proportion_value_changed( GtkAdjustment *adj, GObject *dataKl sp_repr_set_svg_double(repr, "sodipodi:r1", r2*adj->value); } - SP_OBJECT((SPItem *) items->data)->updateRepr(); + item->updateRepr(); modmade = true; } } @@ -2613,10 +2615,11 @@ static void sp_stb_sides_flat_state_changed( EgeSelectOneAction *act, GObject *d } for (; items != NULL; items = items->next) { - if (SP_IS_STAR((SPItem *) items->data)) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data); + SPItem *item = reinterpret_cast(items->data); + if (SP_IS_STAR(item)) { + Inkscape::XML::Node *repr = item->getRepr(); repr->setAttribute("inkscape:flatsided", flat ? "true" : "false" ); - SP_OBJECT((SPItem *) items->data)->updateRepr(); + item->updateRepr(); modmade = true; } } @@ -2651,10 +2654,11 @@ static void sp_stb_rounded_value_changed( GtkAdjustment *adj, GObject *dataKludg Inkscape::Selection *selection = sp_desktop_selection(desktop); GSList const *items = selection->itemList(); for (; items != NULL; items = items->next) { - if (SP_IS_STAR((SPItem *) items->data)) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data); + SPItem *item = reinterpret_cast(items->data); + if (SP_IS_STAR(item)) { + Inkscape::XML::Node *repr = item->getRepr(); sp_repr_set_svg_double(repr, "inkscape:rounded", (gdouble) adj->value); - SP_OBJECT(items->data)->updateRepr(); + item->updateRepr(); modmade = true; } } @@ -2688,10 +2692,11 @@ static void sp_stb_randomized_value_changed( GtkAdjustment *adj, GObject *dataKl Inkscape::Selection *selection = sp_desktop_selection(desktop); GSList const *items = selection->itemList(); for (; items != NULL; items = items->next) { - if (SP_IS_STAR((SPItem *) items->data)) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data); + SPItem *item = reinterpret_cast(items->data); + if (SP_IS_STAR(item)) { + Inkscape::XML::Node *repr = item->getRepr(); sp_repr_set_svg_double(repr, "inkscape:randomized", (gdouble) adj->value); - SP_OBJECT(items->data)->updateRepr(); + item->updateRepr(); modmade = true; } } @@ -2783,9 +2788,10 @@ sp_star_toolbox_selection_changed(Inkscape::Selection *selection, GObject *tbl) items != NULL; items = items->next) { - if (SP_IS_STAR((SPItem *) items->data)) { + SPItem* item = reinterpret_cast(items->data); + if (SP_IS_STAR(item)) { n_selected++; - repr = SP_OBJECT_REPR((SPItem *) items->data); + repr = item->getRepr(); } } @@ -3055,7 +3061,7 @@ static void sp_rtb_value_changed(GtkAdjustment *adj, GObject *tbl, gchar const * if (adj->value != 0) { setter(SP_RECT(items->data), sp_units_get_pixels(adj->value, *unit)); } else { - SP_OBJECT_REPR(items->data)->setAttribute(value_name, NULL); + SP_OBJECT(items->data)->getRepr()->setAttribute(value_name, NULL); } modmade = true; } @@ -3184,10 +3190,10 @@ static void sp_rect_toolbox_selection_changed(Inkscape::Selection *selection, GO for (GSList const *items = selection->itemList(); items != NULL; items = items->next) { - if (SP_IS_RECT((SPItem *) items->data)) { + if (SP_IS_RECT(reinterpret_cast(items->data))) { n_selected++; - item = (SPItem *) items->data; - repr = SP_OBJECT_REPR(item); + item = reinterpret_cast(items->data); + repr = item->getRepr(); } } @@ -3474,7 +3480,7 @@ static void box3d_toolbox_selection_changed(Inkscape::Selection *selection, GObj // FIXME: Also deal with multiple selected boxes SPBox3D *box = SP_BOX3D(item); Persp3D *persp = box3d_get_perspective(box); - persp_repr = SP_OBJECT_REPR(persp); + persp_repr = persp->getRepr(); if (persp_repr) { g_object_set_data(tbl, "repr", persp_repr); Inkscape::GC::anchor(persp_repr); @@ -3513,7 +3519,7 @@ static void box3d_angle_value_changed(GtkAdjustment *adj, GObject *dataKludge, P Persp3D *persp = sel_persps.front(); persp->perspective_impl->tmat.set_infinite_direction (axis, adj->value); - SP_OBJECT(persp)->updateRepr(); + persp->updateRepr(); // TODO: use the correct axis here, too DocumentUndo::maybeDone(document, "perspangle", SP_VERB_CONTEXT_3DBOX, _("3D Box: Change perspective (angle of infinite axis)")); @@ -3731,10 +3737,11 @@ static void sp_spl_tb_value_changed(GtkAdjustment *adj, GObject *tbl, Glib::ustr items != NULL; items = items->next) { - if (SP_IS_SPIRAL((SPItem *) items->data)) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data); + SPItem *item = reinterpret_cast(items->data); + if (SP_IS_SPIRAL(item)) { + Inkscape::XML::Node *repr = item->getRepr(); sp_repr_set_svg_double( repr, namespaced_name, adj->value ); - SP_OBJECT((SPItem *) items->data)->updateRepr(); + item->updateRepr(); modmade = true; } } @@ -3841,9 +3848,10 @@ static void sp_spiral_toolbox_selection_changed(Inkscape::Selection *selection, items != NULL; items = items->next) { - if (SP_IS_SPIRAL((SPItem *) items->data)) { + SPItem *item = reinterpret_cast(items->data); + if (SP_IS_SPIRAL(item)) { n_selected++; - repr = SP_OBJECT_REPR((SPItem *) items->data); + repr = item->getRepr(); } } @@ -5395,10 +5403,11 @@ static void sp_arctb_open_state_changed( EgeSelectOneAction *act, GObject *tbl ) items != NULL; items = items->next) { - if (SP_IS_ARC((SPItem *) items->data)) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data); + SPItem *item = reinterpret_cast(items->data); + if (SP_IS_ARC(item)) { + Inkscape::XML::Node *repr = item->getRepr(); repr->setAttribute("sodipodi:open", "true"); - SP_OBJECT((SPItem *) items->data)->updateRepr(); + item->updateRepr(); modmade = true; } } @@ -5407,10 +5416,11 @@ static void sp_arctb_open_state_changed( EgeSelectOneAction *act, GObject *tbl ) items != NULL; items = items->next) { - if (SP_IS_ARC((SPItem *) items->data)) { - Inkscape::XML::Node *repr = SP_OBJECT_REPR((SPItem *) items->data); + SPItem *item = reinterpret_cast(items->data); + if (SP_IS_ARC(item)) { + Inkscape::XML::Node *repr = item->getRepr(); repr->setAttribute("sodipodi:open", NULL); - SP_OBJECT((SPItem *) items->data)->updateRepr(); + item->updateRepr(); modmade = true; } } @@ -5496,9 +5506,10 @@ static void sp_arc_toolbox_selection_changed(Inkscape::Selection *selection, GOb items != NULL; items = items->next) { - if (SP_IS_ARC((SPItem *) items->data)) { + SPItem *item = reinterpret_cast(items->data); + if (SP_IS_ARC(item)) { n_selected++; - repr = SP_OBJECT_REPR((SPItem *) items->data); + repr = item->getRepr(); } } @@ -6688,7 +6699,7 @@ static void sp_text_align_mode_changed( EgeSelectOneAction *act, GObject *tbl ) if (SP_IS_TEXT((SPItem *) items->data)) { SPItem *item = SP_ITEM(items->data); - unsigned writing_mode = SP_OBJECT_STYLE(item)->writing_mode.value; + 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; @@ -6708,7 +6719,7 @@ static void sp_text_align_mode_changed( EgeSelectOneAction *act, GObject *tbl ) // frame (currently unused) double left_slack = 0; double right_slack = 0; - unsigned old_align = SP_OBJECT_STYLE(item)->text_align.value; + unsigned old_align = item->style->text_align.value; double move = 0; if (old_align == SP_CSS_TEXT_ALIGN_START || old_align == SP_CSS_TEXT_ALIGN_LEFT) { switch (mode) { @@ -6754,8 +6765,8 @@ static void sp_text_align_mode_changed( EgeSelectOneAction *act, GObject *tbl ) XY = XY + Geom::Point (0, move); } SP_TEXT(item)->attributes.setFirstXY(XY); - SP_OBJECT(item)->updateRepr(); - SP_OBJECT(item)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); + item->updateRepr(); + item->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); } } @@ -6843,7 +6854,7 @@ static void sp_text_lineheight_value_changed( GtkAdjustment *adj, GObject *tbl ) bool modmade = false; for (; items != NULL; items = items->next) { if (SP_IS_TEXT (items->data)) { - SP_OBJECT_REPR(items->data)->setAttribute("sodipodi:linespacing", sp_repr_css_property (css, "line-height", NULL)); + SP_OBJECT(items->data)->getRepr()->setAttribute("sodipodi:linespacing", sp_repr_css_property (css, "line-height", NULL)); modmade = true; } } @@ -8013,7 +8024,7 @@ static void connector_spacing_changed(GtkAdjustment *adj, GObject* tbl) return; } - Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview); + Inkscape::XML::Node *repr = desktop->namedview->getRepr(); if ( !repr->attribute("inkscape:connector-spacing") && ( adj->value == defaultConnSpacing )) { @@ -8032,7 +8043,7 @@ static void connector_spacing_changed(GtkAdjustment *adj, GObject* tbl) g_object_set_data( tbl, "freeze", GINT_TO_POINTER(TRUE)); sp_repr_set_css_double(repr, "inkscape:connector-spacing", adj->value); - SP_OBJECT(desktop->namedview)->updateRepr(); + desktop->namedview->updateRepr(); bool modmade = false; GSList *items = get_avoided_items(NULL, desktop->currentRoot(), desktop); @@ -8314,7 +8325,7 @@ static void sp_connector_toolbox_prep( SPDesktop *desktop, GtkActionGroup* mainA // Code to watch for changes to the connector-spacing attribute in // the XML. - Inkscape::XML::Node *repr = SP_OBJECT_REPR(desktop->namedview); + Inkscape::XML::Node *repr = desktop->namedview->getRepr(); g_assert(repr != NULL); purge_repr_listener( holder, holder ); -- cgit v1.2.3 From eb7359f33a6d3ceaa7a7385cd500aefde23c7294 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 21 Feb 2011 00:57:28 -0800 Subject: Conditional code to handle data change in libpng > 1.5. Fixes bug #721029. Fixed bugs: - https://launchpad.net/bugs/721029 (bzr r10061) --- src/sp-image.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/sp-image.cpp b/src/sp-image.cpp index ed9d84b70..8bd1bfadd 100644 --- a/src/sp-image.cpp +++ b/src/sp-image.cpp @@ -387,9 +387,13 @@ static bool readPngAndHeaders( PushPull &youme, gint & dpiX, gint & dpiY ) #if defined(PNG_iCCP_SUPPORTED) { - char* name = 0; + png_charp name = 0; int compression_type = 0; - char* profile = 0; +#if (PNG_LIBPNG_VER < 10500) + png_charp profile = 0; +#else + png_bytep profile = 0; +#endif png_uint_32 proflen = 0; if ( png_get_iCCP(pngPtr, infoPtr, &name, &compression_type, &profile, &proflen) ) { // g_message("Found an iCCP chunk named [%s] with %d bytes and comp %d", name, proflen, compression_type); -- cgit v1.2.3 From 7bb97e4ea8d3eab474e48c4c5af426e5b97bca78 Mon Sep 17 00:00:00 2001 From: Nicolas Dufour Date: Mon, 21 Feb 2011 20:17:17 +0100 Subject: Preferences. New bitmap editor selector (fixes Bug #262617, Edit externally doesn't work on Windows). Fixed bugs: - https://launchpad.net/bugs/262617 (bzr r10062) --- src/preferences-skeleton.h | 2 +- src/ui/context-menu.cpp | 62 ++++-- src/ui/dialog/filedialog.h | 3 +- src/ui/dialog/filedialogimpl-gtkmm.cpp | 224 ++++++++++--------- src/ui/dialog/filedialogimpl-win32.cpp | 383 +++++++++++++++++++-------------- src/ui/dialog/filedialogimpl-win32.h | 3 +- src/ui/dialog/inkscape-preferences.cpp | 20 +- src/ui/dialog/inkscape-preferences.h | 2 +- src/ui/widget/preferences-widget.cpp | 138 ++++++++++++ src/ui/widget/preferences-widget.h | 13 ++ 10 files changed, 539 insertions(+), 311 deletions(-) (limited to 'src') diff --git a/src/preferences-skeleton.h b/src/preferences-skeleton.h index 40e1c892a..0acb3c9e2 100644 --- a/src/preferences-skeleton.h +++ b/src/preferences-skeleton.h @@ -277,7 +277,7 @@ static char const preferences_skeleton[] = " \n" " \n" " \n" -" \n" +" \n" " \n" " \n" " getString("/options/bitmapeditor/choices"); + Glib::ustring choices = prefs->getString("/options/bitmapeditor/value"); if (!choices.empty()) { - gchar** splits = g_strsplit(choices.data(), ",", 0); - gint numIems = g_strv_length(splits); - - int setting = prefs->getIntLimited("/options/bitmapeditor/value", 0, 0, numIems); - value = g_strdup(splits[setting]); - - g_strfreev(splits); + value = g_strdup(choices.c_str()); } - if (!value) { value = g_strdup("gimp"); } @@ -460,16 +453,46 @@ static void sp_image_image_edit(GtkMenuItem *menuitem, SPAnchor *anchor) const gchar *href = ir->attribute("xlink:href"); GError* errThing = 0; - gchar* editorBin = getImageEditorName(); - gchar const* args[] = {editorBin, href, 0}; - g_spawn_async(0, // working dir - const_cast(args), - 0, //envp - G_SPAWN_SEARCH_PATH, - 0, // child_setup - 0, // user_data - 0, //GPid *child_pid - &errThing); + Glib::ustring cmdline = getImageEditorName(); + Glib::ustring fullname; + +#ifdef WIN32 + // g_spawn_command_line_sync parsing is done according to Unix shell rules, + // not Windows command interpreter rules. Thus we need to enclose the + // executable path with sigle quotes. + int index = cmdline.find(".exe"); + if ( index < 0 ) index = cmdline.find(".bat"); + if ( index < 0 ) index = cmdline.find(".com"); + if ( index >= 0 ) { + Glib::ustring editorBin = cmdline.substr(0, index + 4).c_str(); + Glib::ustring args = cmdline.substr(index + 4, cmdline.length()).c_str(); + editorBin.insert(0, "'"); + editorBin.append("'"); + cmdline = editorBin; + cmdline.append(args); + } else { + // Enclose the whole command line if no executable path can be extracted. + cmdline.insert(0, "'"); + cmdline.append("'"); + } +#endif + + if (strncmp (href,"file:",5) == 0) { + // URI to filename conversion + fullname = g_filename_from_uri(href, NULL, NULL); + } else { + fullname.append(href); + } + + cmdline.append(" '"); + cmdline.append(fullname.c_str()); + cmdline.append("'"); + + //printf("##Command line: %s\n", cmdline.c_str()); + + g_spawn_command_line_async(cmdline.c_str(), + &errThing); + if ( errThing ) { g_warning("Problem launching editor (%d). %s", errThing->code, errThing->message); SPDesktop *desktop = (SPDesktop*)gtk_object_get_data(GTK_OBJECT(menuitem), "desktop"); @@ -477,7 +500,6 @@ static void sp_image_image_edit(GtkMenuItem *menuitem, SPAnchor *anchor) g_error_free(errThing); errThing = 0; } - g_free(editorBin); } /* Fill and Stroke entry */ diff --git a/src/ui/dialog/filedialog.h b/src/ui/dialog/filedialog.h index 9f13308fb..a7441e9bb 100644 --- a/src/ui/dialog/filedialog.h +++ b/src/ui/dialog/filedialog.h @@ -46,7 +46,8 @@ namespace Dialog typedef enum { SVG_TYPES, IMPORT_TYPES, - EXPORT_TYPES + EXPORT_TYPES, + EXE_TYPES } FileDialogType; /** diff --git a/src/ui/dialog/filedialogimpl-gtkmm.cpp b/src/ui/dialog/filedialogimpl-gtkmm.cpp index 855d5a223..8e0b9294b 100644 --- a/src/ui/dialog/filedialogimpl-gtkmm.cpp +++ b/src/ui/dialog/filedialogimpl-gtkmm.cpp @@ -572,32 +572,36 @@ SVGPreview::~SVGPreview() void FileDialogBaseGtk::internalSetup() { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - bool enablePreview = prefs->getBool( preferenceBase + "/enable_preview", true); - - previewCheckbox.set_label( Glib::ustring(_("Enable preview")) ); - previewCheckbox.set_active( enablePreview ); + // Open executable file dialogs don't need the preview panel + if (_dialogType != EXE_TYPES) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + bool enablePreview = prefs->getBool( preferenceBase + "/enable_preview", true); - previewCheckbox.signal_toggled().connect( - sigc::mem_fun(*this, &FileDialogBaseGtk::_previewEnabledCB) ); + previewCheckbox.set_label( Glib::ustring(_("Enable preview")) ); + previewCheckbox.set_active( enablePreview ); - //Catch selection-changed events, so we can adjust the text widget - signal_update_preview().connect( - sigc::mem_fun(*this, &FileDialogBaseGtk::_updatePreviewCallback) ); + previewCheckbox.signal_toggled().connect( + sigc::mem_fun(*this, &FileDialogBaseGtk::_previewEnabledCB) ); - //###### Add a preview widget - set_preview_widget(svgPreview); - set_preview_widget_active( enablePreview ); - set_use_preview_label (false); + //Catch selection-changed events, so we can adjust the text widget + signal_update_preview().connect( + sigc::mem_fun(*this, &FileDialogBaseGtk::_updatePreviewCallback) ); + //###### Add a preview widget + set_preview_widget(svgPreview); + set_preview_widget_active( enablePreview ); + set_use_preview_label (false); + } } void FileDialogBaseGtk::cleanup( bool showConfirmed ) { - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - if ( showConfirmed ) - prefs->setBool( preferenceBase + "/enable_preview", previewCheckbox.get_active() ); + if (_dialogType != EXE_TYPES) { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + if ( showConfirmed ) + prefs->setBool( preferenceBase + "/enable_preview", previewCheckbox.get_active() ); + } } @@ -648,9 +652,13 @@ FileOpenDialogImplGtk::FileOpenDialogImplGtk(Gtk::Window& parentWindow, { - /* One file at a time */ - /* And also Multiple Files */ - set_select_multiple(true); + if (_dialogType == EXE_TYPES) { + /* One file at a time */ + set_select_multiple(false); + } else { + /* And also Multiple Files */ + set_select_multiple(true); + } #ifdef WITH_GNOME_VFS if (gnome_vfs_initialized()) { @@ -668,19 +676,22 @@ FileOpenDialogImplGtk::FileOpenDialogImplGtk(Gtk::Window& parentWindow, /* Set the pwd and/or the filename */ - if (dir.size() > 0) - { + if (dir.size() > 0) { Glib::ustring udir(dir); Glib::ustring::size_type len = udir.length(); // leaving a trailing backslash on the directory name leads to the infamous // double-directory bug on win32 if (len != 0 && udir[len - 1] == '\\') udir.erase(len - 1); - set_current_folder(udir.c_str()); + if (_dialogType == EXE_TYPES) { + set_filename(udir.c_str()); + } else { + set_current_folder(udir.c_str()); } + } - - set_extra_widget( previewCheckbox ); - + if (_dialogType != EXE_TYPES) { + set_extra_widget( previewCheckbox ); + } //###### Add the file types menu createFilterMenu(); @@ -708,84 +719,91 @@ FileOpenDialogImplGtk::~FileOpenDialogImplGtk() void FileOpenDialogImplGtk::createFilterMenu() { - Gtk::FileFilter allInkscapeFilter; - allInkscapeFilter.set_name(_("All Inkscape Files")); - extensionMap[Glib::ustring(_("All Inkscape Files"))]=NULL; - add_filter(allInkscapeFilter); - - Gtk::FileFilter allFilter; - allFilter.set_name(_("All Files")); - extensionMap[Glib::ustring(_("All Files"))]=NULL; - allFilter.add_pattern("*"); - add_filter(allFilter); - - Gtk::FileFilter allImageFilter; - allImageFilter.set_name(_("All Images")); - extensionMap[Glib::ustring(_("All Images"))]=NULL; - add_filter(allImageFilter); - - Gtk::FileFilter allVectorFilter; - allVectorFilter.set_name(_("All Vectors")); - extensionMap[Glib::ustring(_("All Vectors"))]=NULL; - add_filter(allVectorFilter); - - Gtk::FileFilter allBitmapFilter; - allBitmapFilter.set_name(_("All Bitmaps")); - extensionMap[Glib::ustring(_("All Bitmaps"))]=NULL; - add_filter(allBitmapFilter); - - //patterns added dynamically below - Inkscape::Extension::DB::InputList extension_list; - Inkscape::Extension::db.get_input_list(extension_list); - - for (Inkscape::Extension::DB::InputList::iterator current_item = extension_list.begin(); - current_item != extension_list.end(); current_item++) - { - Inkscape::Extension::Input * imod = *current_item; - - // FIXME: would be nice to grey them out instead of not listing them - if (imod->deactivated()) continue; - - Glib::ustring upattern("*"); - Glib::ustring extension = imod->get_extension(); - fileDialogExtensionToPattern(upattern, extension); - - Gtk::FileFilter filter; - Glib::ustring uname(_(imod->get_filetypename())); - filter.set_name(uname); - filter.add_pattern(upattern); - add_filter(filter); - extensionMap[uname] = imod; - - //g_message("ext %s:%s '%s'\n", ioext->name, ioext->mimetype, upattern.c_str()); - allInkscapeFilter.add_pattern(upattern); - if ( strncmp("image", imod->get_mimetype(), 5)==0 ) - allImageFilter.add_pattern(upattern); - - // uncomment this to find out all mime types supported by Inkscape import/open - // g_print ("%s\n", imod->get_mimetype()); - - // I don't know of any other way to define "bitmap" formats other than by listing them - if ( - strncmp("image/png", imod->get_mimetype(), 9)==0 || - strncmp("image/jpeg", imod->get_mimetype(), 10)==0 || - strncmp("image/gif", imod->get_mimetype(), 9)==0 || - strncmp("image/x-icon", imod->get_mimetype(), 12)==0 || - strncmp("image/x-navi-animation", imod->get_mimetype(), 22)==0 || - strncmp("image/x-cmu-raster", imod->get_mimetype(), 18)==0 || - strncmp("image/x-xpixmap", imod->get_mimetype(), 15)==0 || - strncmp("image/bmp", imod->get_mimetype(), 9)==0 || - strncmp("image/vnd.wap.wbmp", imod->get_mimetype(), 18)==0 || - strncmp("image/tiff", imod->get_mimetype(), 10)==0 || - strncmp("image/x-xbitmap", imod->get_mimetype(), 15)==0 || - strncmp("image/x-tga", imod->get_mimetype(), 11)==0 || - strncmp("image/x-pcx", imod->get_mimetype(), 11)==0 - ) - allBitmapFilter.add_pattern(upattern); - else - allVectorFilter.add_pattern(upattern); + if (_dialogType == EXE_TYPES) { + Gtk::FileFilter allFilter; + allFilter.set_name(_("All Files")); + extensionMap[Glib::ustring(_("All Files"))]=NULL; + allFilter.add_pattern("*"); + add_filter(allFilter); + } else { + Gtk::FileFilter allInkscapeFilter; + allInkscapeFilter.set_name(_("All Inkscape Files")); + extensionMap[Glib::ustring(_("All Inkscape Files"))]=NULL; + add_filter(allInkscapeFilter); + + Gtk::FileFilter allFilter; + allFilter.set_name(_("All Files")); + extensionMap[Glib::ustring(_("All Files"))]=NULL; + allFilter.add_pattern("*"); + add_filter(allFilter); + + Gtk::FileFilter allImageFilter; + allImageFilter.set_name(_("All Images")); + extensionMap[Glib::ustring(_("All Images"))]=NULL; + add_filter(allImageFilter); + + Gtk::FileFilter allVectorFilter; + allVectorFilter.set_name(_("All Vectors")); + extensionMap[Glib::ustring(_("All Vectors"))]=NULL; + add_filter(allVectorFilter); + + Gtk::FileFilter allBitmapFilter; + allBitmapFilter.set_name(_("All Bitmaps")); + extensionMap[Glib::ustring(_("All Bitmaps"))]=NULL; + add_filter(allBitmapFilter); + + //patterns added dynamically below + Inkscape::Extension::DB::InputList extension_list; + Inkscape::Extension::db.get_input_list(extension_list); + + for (Inkscape::Extension::DB::InputList::iterator current_item = extension_list.begin(); + current_item != extension_list.end(); current_item++) + { + Inkscape::Extension::Input * imod = *current_item; + + // FIXME: would be nice to grey them out instead of not listing them + if (imod->deactivated()) continue; + + Glib::ustring upattern("*"); + Glib::ustring extension = imod->get_extension(); + fileDialogExtensionToPattern(upattern, extension); + + Gtk::FileFilter filter; + Glib::ustring uname(_(imod->get_filetypename())); + filter.set_name(uname); + filter.add_pattern(upattern); + add_filter(filter); + extensionMap[uname] = imod; + + //g_message("ext %s:%s '%s'\n", ioext->name, ioext->mimetype, upattern.c_str()); + allInkscapeFilter.add_pattern(upattern); + if ( strncmp("image", imod->get_mimetype(), 5)==0 ) + allImageFilter.add_pattern(upattern); + + // uncomment this to find out all mime types supported by Inkscape import/open + // g_print ("%s\n", imod->get_mimetype()); + + // I don't know of any other way to define "bitmap" formats other than by listing them + if ( + strncmp("image/png", imod->get_mimetype(), 9)==0 || + strncmp("image/jpeg", imod->get_mimetype(), 10)==0 || + strncmp("image/gif", imod->get_mimetype(), 9)==0 || + strncmp("image/x-icon", imod->get_mimetype(), 12)==0 || + strncmp("image/x-navi-animation", imod->get_mimetype(), 22)==0 || + strncmp("image/x-cmu-raster", imod->get_mimetype(), 18)==0 || + strncmp("image/x-xpixmap", imod->get_mimetype(), 15)==0 || + strncmp("image/bmp", imod->get_mimetype(), 9)==0 || + strncmp("image/vnd.wap.wbmp", imod->get_mimetype(), 18)==0 || + strncmp("image/tiff", imod->get_mimetype(), 10)==0 || + strncmp("image/x-xbitmap", imod->get_mimetype(), 15)==0 || + strncmp("image/x-tga", imod->get_mimetype(), 11)==0 || + strncmp("image/x-pcx", imod->get_mimetype(), 11)==0 + ) + allBitmapFilter.add_pattern(upattern); + else + allVectorFilter.add_pattern(upattern); + } } - return; } diff --git a/src/ui/dialog/filedialogimpl-win32.cpp b/src/ui/dialog/filedialogimpl-win32.cpp index e5175be4c..b18d5a1bc 100644 --- a/src/ui/dialog/filedialogimpl-win32.cpp +++ b/src/ui/dialog/filedialogimpl-win32.cpp @@ -124,11 +124,11 @@ FileDialogBaseWin32::FileDialogBaseWin32(Gtk::Window &parent, { _main_loop = NULL; - _filter_index = 1; - _filter_count = 0; + _filter_index = 1; + _filter_count = 0; _title = (wchar_t*)g_utf8_to_utf16(title, -1, NULL, NULL, NULL); - g_assert(_title != NULL); + g_assert(_title != NULL); Glib::RefPtr parentWindow = parent.get_window(); g_assert(parentWindow->gobj() != NULL); @@ -185,7 +185,7 @@ FileOpenDialogImplWin32::FileOpenDialogImplWin32(Gtk::Window &parent, _preview_image_height = 0; _preview_emf_image = false; - _mutex = NULL; + _mutex = NULL; createFilterMenu(); } @@ -206,143 +206,180 @@ void FileOpenDialogImplWin32::createFilterMenu() { list filter_list; - // Compose the filter string - Inkscape::Extension::DB::InputList extension_list; - Inkscape::Extension::db.get_input_list(extension_list); - - ustring all_inkscape_files_filter, all_image_files_filter, all_vectors_filter, all_bitmaps_filter; - Filter all_files, all_inkscape_files, all_image_files, all_vectors, all_bitmaps; - - const gchar *all_files_filter_name = _("All Files"); - const gchar *all_inkscape_files_filter_name = _("All Inkscape Files"); - const gchar *all_image_files_filter_name = _("All Images"); - const gchar *all_vectors_filter_name = _("All Vectors"); - const gchar *all_bitmaps_filter_name = _("All Bitmaps"); - - // Calculate the amount of memory required - int filter_count = 5; // 5 - one for each filter type + int extension_index = 0; int filter_length = 1; + + if (dialogType != EXE_TYPES) { + // Compose the filter string + Inkscape::Extension::DB::InputList extension_list; + Inkscape::Extension::db.get_input_list(extension_list); + + ustring all_inkscape_files_filter, all_image_files_filter, all_vectors_filter, all_bitmaps_filter; + Filter all_files, all_inkscape_files, all_image_files, all_vectors, all_bitmaps; + + const gchar *all_files_filter_name = _("All Files"); + const gchar *all_inkscape_files_filter_name = _("All Inkscape Files"); + const gchar *all_image_files_filter_name = _("All Images"); + const gchar *all_vectors_filter_name = _("All Vectors"); + const gchar *all_bitmaps_filter_name = _("All Bitmaps"); + + // Calculate the amount of memory required + int filter_count = 5; // 5 - one for each filter type + + for (Inkscape::Extension::DB::InputList::iterator current_item = extension_list.begin(); + current_item != extension_list.end(); current_item++) + { + Filter filter; - for (Inkscape::Extension::DB::InputList::iterator current_item = extension_list.begin(); - current_item != extension_list.end(); current_item++) - { - Filter filter; + Inkscape::Extension::Input *imod = *current_item; + if (imod->deactivated()) continue; - Inkscape::Extension::Input *imod = *current_item; - if (imod->deactivated()) continue; + // Type + filter.name = g_utf8_to_utf16(_(imod->get_filetypename()), + -1, NULL, &filter.name_length, NULL); - // Type - filter.name = g_utf8_to_utf16(_(imod->get_filetypename()), - -1, NULL, &filter.name_length, NULL); + // Extension + const gchar *file_extension_name = imod->get_extension(); + filter.filter = g_utf8_to_utf16(file_extension_name, + -1, NULL, &filter.filter_length, NULL); - // Extension - const gchar *file_extension_name = imod->get_extension(); - filter.filter = g_utf8_to_utf16(file_extension_name, - -1, NULL, &filter.filter_length, NULL); + filter.mod = imod; + filter_list.push_back(filter); - filter.mod = imod; - filter_list.push_back(filter); + filter_length += filter.name_length + + filter.filter_length + 3; // Add 3 for two \0s and a * - filter_length += filter.name_length + - filter.filter_length + 3; // Add 3 for two \0s and a * + // Add to the "All Inkscape Files" Entry + if(all_inkscape_files_filter.length() > 0) + all_inkscape_files_filter += ";*"; + all_inkscape_files_filter += file_extension_name; + if( strncmp("image", imod->get_mimetype(), 5) == 0) + { + // Add to the "All Image Files" Entry + if(all_image_files_filter.length() > 0) + all_image_files_filter += ";*"; + all_image_files_filter += file_extension_name; + } - // Add to the "All Inkscape Files" Entry - if(all_inkscape_files_filter.length() > 0) - all_inkscape_files_filter += ";*"; - all_inkscape_files_filter += file_extension_name; - if( strncmp("image", imod->get_mimetype(), 5) == 0) - { - // Add to the "All Image Files" Entry - if(all_image_files_filter.length() > 0) - all_image_files_filter += ";*"; - all_image_files_filter += file_extension_name; - } + // I don't know of any other way to define "bitmap" formats other than by listing them + // if you change it here, do the same change in filedialogimpl-gtkmm + if ( + strncmp("image/png", imod->get_mimetype(), 9)==0 || + strncmp("image/jpeg", imod->get_mimetype(), 10)==0 || + strncmp("image/gif", imod->get_mimetype(), 9)==0 || + strncmp("image/x-icon", imod->get_mimetype(), 12)==0 || + strncmp("image/x-navi-animation", imod->get_mimetype(), 22)==0 || + strncmp("image/x-cmu-raster", imod->get_mimetype(), 18)==0 || + strncmp("image/x-xpixmap", imod->get_mimetype(), 15)==0 || + strncmp("image/bmp", imod->get_mimetype(), 9)==0 || + strncmp("image/vnd.wap.wbmp", imod->get_mimetype(), 18)==0 || + strncmp("image/tiff", imod->get_mimetype(), 10)==0 || + strncmp("image/x-xbitmap", imod->get_mimetype(), 15)==0 || + strncmp("image/x-tga", imod->get_mimetype(), 11)==0 || + strncmp("image/x-pcx", imod->get_mimetype(), 11)==0 + ) { + if(all_bitmaps_filter.length() > 0) + all_bitmaps_filter += ";*"; + all_bitmaps_filter += file_extension_name; + } else { + if(all_vectors_filter.length() > 0) + all_vectors_filter += ";*"; + all_vectors_filter += file_extension_name; + } - // I don't know of any other way to define "bitmap" formats other than by listing them - // if you change it here, do the same change in filedialogimpl-gtkmm - if ( - strncmp("image/png", imod->get_mimetype(), 9)==0 || - strncmp("image/jpeg", imod->get_mimetype(), 10)==0 || - strncmp("image/gif", imod->get_mimetype(), 9)==0 || - strncmp("image/x-icon", imod->get_mimetype(), 12)==0 || - strncmp("image/x-navi-animation", imod->get_mimetype(), 22)==0 || - strncmp("image/x-cmu-raster", imod->get_mimetype(), 18)==0 || - strncmp("image/x-xpixmap", imod->get_mimetype(), 15)==0 || - strncmp("image/bmp", imod->get_mimetype(), 9)==0 || - strncmp("image/vnd.wap.wbmp", imod->get_mimetype(), 18)==0 || - strncmp("image/tiff", imod->get_mimetype(), 10)==0 || - strncmp("image/x-xbitmap", imod->get_mimetype(), 15)==0 || - strncmp("image/x-tga", imod->get_mimetype(), 11)==0 || - strncmp("image/x-pcx", imod->get_mimetype(), 11)==0 - ) { - if(all_bitmaps_filter.length() > 0) - all_bitmaps_filter += ";*"; - all_bitmaps_filter += file_extension_name; - } else { - if(all_vectors_filter.length() > 0) - all_vectors_filter += ";*"; - all_vectors_filter += file_extension_name; + filter_count++; } - filter_count++; + _extension_map = new Inkscape::Extension::Extension*[filter_count]; + + // Filter bitmap files + all_bitmaps.name = g_utf8_to_utf16(all_bitmaps_filter_name, + -1, NULL, &all_bitmaps.name_length, NULL); + all_bitmaps.filter = g_utf8_to_utf16(all_bitmaps_filter.data(), + -1, NULL, &all_bitmaps.filter_length, NULL); + all_bitmaps.mod = NULL; + filter_list.push_front(all_bitmaps); + + // Filter vector files + all_vectors.name = g_utf8_to_utf16(all_vectors_filter_name, + -1, NULL, &all_vectors.name_length, NULL); + all_vectors.filter = g_utf8_to_utf16(all_vectors_filter.data(), + -1, NULL, &all_vectors.filter_length, NULL); + all_vectors.mod = NULL; + filter_list.push_front(all_vectors); + + // Filter Image Files + all_image_files.name = g_utf8_to_utf16(all_image_files_filter_name, + -1, NULL, &all_image_files.name_length, NULL); + all_image_files.filter = g_utf8_to_utf16(all_image_files_filter.data(), + -1, NULL, &all_image_files.filter_length, NULL); + all_image_files.mod = NULL; + filter_list.push_front(all_image_files); + + // Filter Inkscape Files + all_inkscape_files.name = g_utf8_to_utf16(all_inkscape_files_filter_name, + -1, NULL, &all_inkscape_files.name_length, NULL); + all_inkscape_files.filter = g_utf8_to_utf16(all_inkscape_files_filter.data(), + -1, NULL, &all_inkscape_files.filter_length, NULL); + all_inkscape_files.mod = NULL; + filter_list.push_front(all_inkscape_files); + + // Filter All Files + all_files.name = g_utf8_to_utf16(all_files_filter_name, + -1, NULL, &all_files.name_length, NULL); + all_files.filter = NULL; + all_files.filter_length = 0; + all_files.mod = NULL; + filter_list.push_front(all_files); + + filter_length += all_files.name_length + 3 + + all_inkscape_files.filter_length + + all_inkscape_files.name_length + 3 + + all_image_files.filter_length + + all_image_files.name_length + 3 + + all_vectors.filter_length + + all_vectors.name_length + 3 + + all_bitmaps.filter_length + + all_bitmaps.name_length + 3 + + 1; + // Add 3 for 2*2 \0s and a *, and 1 for a trailing \0 + } else { + // Executables only + ustring all_exe_files_filter = "*.exe;*.bat;*.com"; + Filter all_exe_files, all_files; + + const gchar *all_files_filter_name = _("All Files"); + const gchar *all_exe_files_filter_name = _("All Executable Files"); + + // Calculate the amount of memory required + int filter_count = 2; // 2 - All Files and All Executable Files + + _extension_map = new Inkscape::Extension::Extension*[filter_count]; + + // Filter Executable Files + all_exe_files.name = g_utf8_to_utf16(all_exe_files_filter_name, + -1, NULL, &all_exe_files.name_length, NULL); + all_exe_files.filter = g_utf8_to_utf16(all_exe_files_filter.data(), + -1, NULL, &all_exe_files.filter_length, NULL); + all_exe_files.mod = NULL; + filter_list.push_front(all_exe_files); + + // Filter All Files + all_files.name = g_utf8_to_utf16(all_files_filter_name, + -1, NULL, &all_files.name_length, NULL); + all_files.filter = NULL; + all_files.filter_length = 0; + all_files.mod = NULL; + filter_list.push_front(all_files); + + filter_length += all_files.name_length + 3 + + all_exe_files.filter_length + + all_exe_files.name_length + 3 + + 1; + // Add 3 for 2*2 \0s and a *, and 1 for a trailing \0 } - - int extension_index = 0; - _extension_map = new Inkscape::Extension::Extension*[filter_count]; - - // Filter bitmap files - all_bitmaps.name = g_utf8_to_utf16(all_bitmaps_filter_name, - -1, NULL, &all_bitmaps.name_length, NULL); - all_bitmaps.filter = g_utf8_to_utf16(all_bitmaps_filter.data(), - -1, NULL, &all_bitmaps.filter_length, NULL); - all_bitmaps.mod = NULL; - filter_list.push_front(all_bitmaps); - - // Filter vector files - all_vectors.name = g_utf8_to_utf16(all_vectors_filter_name, - -1, NULL, &all_vectors.name_length, NULL); - all_vectors.filter = g_utf8_to_utf16(all_vectors_filter.data(), - -1, NULL, &all_vectors.filter_length, NULL); - all_vectors.mod = NULL; - filter_list.push_front(all_vectors); - - // Filter Image Files - all_image_files.name = g_utf8_to_utf16(all_image_files_filter_name, - -1, NULL, &all_image_files.name_length, NULL); - all_image_files.filter = g_utf8_to_utf16(all_image_files_filter.data(), - -1, NULL, &all_image_files.filter_length, NULL); - all_image_files.mod = NULL; - filter_list.push_front(all_image_files); - - // Filter Inkscape Files - all_inkscape_files.name = g_utf8_to_utf16(all_inkscape_files_filter_name, - -1, NULL, &all_inkscape_files.name_length, NULL); - all_inkscape_files.filter = g_utf8_to_utf16(all_inkscape_files_filter.data(), - -1, NULL, &all_inkscape_files.filter_length, NULL); - all_inkscape_files.mod = NULL; - filter_list.push_front(all_inkscape_files); - - // Filter All Files - all_files.name = g_utf8_to_utf16(all_files_filter_name, - -1, NULL, &all_files.name_length, NULL); - all_files.filter = NULL; - all_files.filter_length = 0; - all_files.mod = NULL; - filter_list.push_front(all_files); - - filter_length += all_files.name_length + 3 + - all_inkscape_files.filter_length + - all_inkscape_files.name_length + 3 + - all_image_files.filter_length + - all_image_files.name_length + 3 + - all_vectors.filter_length + - all_vectors.name_length + 3 + - all_bitmaps.filter_length + - all_bitmaps.name_length + 3 + - 1; - // Add 3 for 2*2 \0s and a *, and 1 for a trailing \0 - - _filter = new wchar_t[filter_length]; + + _filter = new wchar_t[filter_length]; wchar_t *filterptr = _filter; for(list::iterator filter_iterator = filter_list.begin(); @@ -371,7 +408,7 @@ void FileOpenDialogImplWin32::createFilterMenu() } *(filterptr++) = L'\0'; - _filter_count = extension_index; + _filter_count = extension_index; _filter_index = 2; // Select the 2nd filter in the list - 2 is NOT the 3rd } @@ -380,7 +417,7 @@ void FileOpenDialogImplWin32::GetOpenFileName_thread() OPENFILENAMEEXW ofn; g_assert(this != NULL); - g_assert(_mutex != NULL); + g_assert(_mutex != NULL); WCHAR* current_directory_string = (WCHAR*)g_utf8_to_utf16( _current_directory.data(), _current_directory.length(), @@ -411,7 +448,7 @@ void FileOpenDialogImplWin32::GetOpenFileName_thread() _result = GetOpenFileNameW(&ofn) != 0; - g_assert(ofn.nFilterIndex >= 1 && ofn.nFilterIndex <= _filter_count); + g_assert(ofn.nFilterIndex >= 1 && ofn.nFilterIndex <= _filter_count); _filter_index = ofn.nFilterIndex; _extension = _extension_map[ofn.nFilterIndex - 1]; @@ -459,56 +496,70 @@ UINT_PTR CALLBACK FileOpenDialogImplWin32::GetOpenFileName_hookproc( HWND hParentWnd = GetParent(hdlg); HINSTANCE hInstance = GetModuleHandle(NULL); - // Make the window a bit wider - RECT rcRect; - GetWindowRect(hParentWnd, &rcRect); - MoveWindow(hParentWnd, rcRect.left, rcRect.top, - rcRect.right - rcRect.left + PREVIEW_WIDENING, - rcRect.bottom - rcRect.top, - FALSE); - // Set the pointer to the object OPENFILENAMEW *ofn = (OPENFILENAMEW*)lParam; SetWindowLongPtr(hdlg, GWLP_USERDATA, ofn->lCustData); SetWindowLongPtr(hParentWnd, GWLP_USERDATA, ofn->lCustData); pImpl = (FileOpenDialogImplWin32*)ofn->lCustData; + + // Make the window a bit wider + RECT rcRect; + GetWindowRect(hParentWnd, &rcRect); + + // Don't show the preview when opening executable files + if ( pImpl->dialogType == EXE_TYPES) { + MoveWindow(hParentWnd, rcRect.left, rcRect.top, + rcRect.right - rcRect.left, + rcRect.bottom - rcRect.top, + FALSE); + } else { + MoveWindow(hParentWnd, rcRect.left, rcRect.top, + rcRect.right - rcRect.left + PREVIEW_WIDENING, + rcRect.bottom - rcRect.top, + FALSE); + } // Subclass the parent pImpl->_base_window_proc = (WNDPROC)GetWindowLongPtr(hParentWnd, GWLP_WNDPROC); SetWindowLongPtr(hParentWnd, GWLP_WNDPROC, reinterpret_cast(file_dialog_subclass_proc)); - // Add a button to the toolbar - pImpl->_toolbar_wnd = FindWindowEx(hParentWnd, NULL, "ToolbarWindow32", NULL); - - pImpl->_show_preview_button_bitmap = LoadBitmap( - hInstance, MAKEINTRESOURCE(IDC_SHOW_PREVIEW)); - TBADDBITMAP tbAddBitmap = {NULL, reinterpret_cast(pImpl->_show_preview_button_bitmap)}; - const int iBitmapIndex = SendMessage(pImpl->_toolbar_wnd, - TB_ADDBITMAP, 1, (LPARAM)&tbAddBitmap); - - TBBUTTON tbButton; - memset(&tbButton, 0, sizeof(TBBUTTON)); - tbButton.iBitmap = iBitmapIndex; - tbButton.idCommand = IDC_SHOW_PREVIEW; - tbButton.fsState = (pImpl->_show_preview ? TBSTATE_CHECKED : 0) - | TBSTATE_ENABLED; - tbButton.fsStyle = TBSTYLE_CHECK; - tbButton.iString = (INT_PTR)_("Show Preview"); - SendMessage(pImpl->_toolbar_wnd, TB_ADDBUTTONS, 1, (LPARAM)&tbButton); - - // Create preview pane - register_preview_wnd_class(); + if ( pImpl->dialogType != EXE_TYPES) { + // Add a button to the toolbar + pImpl->_toolbar_wnd = FindWindowEx(hParentWnd, NULL, "ToolbarWindow32", NULL); + + pImpl->_show_preview_button_bitmap = LoadBitmap( + hInstance, MAKEINTRESOURCE(IDC_SHOW_PREVIEW)); + TBADDBITMAP tbAddBitmap = {NULL, reinterpret_cast(pImpl->_show_preview_button_bitmap)}; + const int iBitmapIndex = SendMessage(pImpl->_toolbar_wnd, + TB_ADDBITMAP, 1, (LPARAM)&tbAddBitmap); + + + TBBUTTON tbButton; + memset(&tbButton, 0, sizeof(TBBUTTON)); + tbButton.iBitmap = iBitmapIndex; + tbButton.idCommand = IDC_SHOW_PREVIEW; + tbButton.fsState = (pImpl->_show_preview ? TBSTATE_CHECKED : 0) + | TBSTATE_ENABLED; + tbButton.fsStyle = TBSTYLE_CHECK; + tbButton.iString = (INT_PTR)_("Show Preview"); + SendMessage(pImpl->_toolbar_wnd, TB_ADDBUTTONS, 1, (LPARAM)&tbButton); + + // Create preview pane + register_preview_wnd_class(); + } pImpl->_mutex->lock(); - pImpl->_file_dialog_wnd = hParentWnd; + pImpl->_file_dialog_wnd = hParentWnd; + if ( pImpl->dialogType != EXE_TYPES) { pImpl->_preview_wnd = CreateWindowA(PreviewWindowClassName, "", WS_CHILD | WS_VISIBLE, 0, 0, 100, 100, hParentWnd, NULL, hInstance, NULL); SetWindowLongPtr(pImpl->_preview_wnd, GWLP_USERDATA, ofn->lCustData); - + } + pImpl->_mutex->unlock(); pImpl->layout_dialog(); @@ -775,7 +826,7 @@ void FileOpenDialogImplWin32::layout_dialog() rcClient.right - iPadding, rcFileList.r.bottom}; rcFileList.r.right = rcBody.right; - if(_show_preview) + if(_show_preview && dialogType != EXE_TYPES) { rcPreview.top = rcBody.top; rcPreview.left = rcClient.right - (rcBody.bottom - rcBody.top); @@ -1603,7 +1654,7 @@ void FileSaveDialogImplWin32::createFilterMenu() } *(filterptr++) = 0; - _filter_count = extension_index; + _filter_count = extension_index; _filter_index = 1; // A value of 1 selects the 1st filter - NOT the 2nd } @@ -1643,7 +1694,7 @@ void FileSaveDialogImplWin32::GetSaveFileName_thread() _result = GetSaveFileNameW(&ofn) != 0; - g_assert(ofn.nFilterIndex >= 1 && ofn.nFilterIndex <= _filter_count); + g_assert(ofn.nFilterIndex >= 1 && ofn.nFilterIndex <= _filter_count); _filter_index = ofn.nFilterIndex; _extension = _extension_map[ofn.nFilterIndex - 1]; diff --git a/src/ui/dialog/filedialogimpl-win32.h b/src/ui/dialog/filedialogimpl-win32.h index 00d9cf37f..a6f7d6239 100644 --- a/src/ui/dialog/filedialogimpl-win32.h +++ b/src/ui/dialog/filedialogimpl-win32.h @@ -150,9 +150,10 @@ public: private: - /// Create a filter menu for this type of dialog + /// Create filter menu for this type of dialog void createFilterMenu(); + /// The handle of the preview pane window HWND _preview_wnd; diff --git a/src/ui/dialog/inkscape-preferences.cpp b/src/ui/dialog/inkscape-preferences.cpp index 13491312a..d10902722 100644 --- a/src/ui/dialog/inkscape-preferences.cpp +++ b/src/ui/dialog/inkscape-preferences.cpp @@ -1220,24 +1220,8 @@ void InkscapePreferences::initPageBitmaps() _misc_bitmap_autoreload.init(_("Automatically reload bitmaps"), "/options/bitmapautoreload/value", true); _page_bitmaps.add_line( false, "", _misc_bitmap_autoreload, "", _("Automatically reload linked images when file is changed on disk")); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Glib::ustring choices = prefs->getString("/options/bitmapeditor/choices"); - if (!choices.empty()) { - gchar** splits = g_strsplit(choices.data(), ",", 0); - gint numIems = g_strv_length(splits); - - Glib::ustring labels[numIems]; - int values[numIems]; - for ( gint i = 0; i < numIems; i++) { - values[i] = i; - labels[i] = splits[i]; - } - _misc_bitmap_editor.init("/options/bitmapeditor/value", labels, values, numIems, 0); - _page_bitmaps.add_line( false, _("Bitmap editor:"), _misc_bitmap_editor, "", "", false); - - g_strfreev(splits); - } - + _misc_bitmap_editor.init("/options/bitmapeditor/value", true); + _page_bitmaps.add_line( false, _("Bitmap editor:"), _misc_bitmap_editor, "", "", true); _bitmap_copy_res.init("/options/createbitmap/resolution", 1.0, 6000.0, 1.0, 1.0, PX_PER_IN, true, false); _page_bitmaps.add_line( false, _("Resolution for Create Bitmap Copy:"), _bitmap_copy_res, _("dpi"), _("Resolution used by the Create Bitmap Copy command"), false); diff --git a/src/ui/dialog/inkscape-preferences.h b/src/ui/dialog/inkscape-preferences.h index 5ee916e4c..f09409d4a 100644 --- a/src/ui/dialog/inkscape-preferences.h +++ b/src/ui/dialog/inkscape-preferences.h @@ -297,7 +297,7 @@ protected: UI::Widget::PrefCheckButton _spell_ignoreallcaps; UI::Widget::PrefCombo _misc_overs_bitmap; - UI::Widget::PrefCombo _misc_bitmap_editor; + UI::Widget::PrefEntryFileButtonHBox _misc_bitmap_editor; UI::Widget::PrefCheckButton _misc_bitmap_autoreload; UI::Widget::PrefSpinButton _bitmap_copy_res; diff --git a/src/ui/widget/preferences-widget.cpp b/src/ui/widget/preferences-widget.cpp index 4816304db..afcaa338e 100644 --- a/src/ui/widget/preferences-widget.cpp +++ b/src/ui/widget/preferences-widget.cpp @@ -14,6 +14,10 @@ # include #endif +#ifdef WIN32 +#include +#endif + #include #include #include @@ -22,7 +26,9 @@ #include "ui/widget/preferences-widget.h" #include "verbs.h" #include "selcue.h" +#include "io/sys.h" #include +#include "desktop.h" #include "enums.h" #include "inkscape.h" #include "desktop-handles.h" @@ -30,6 +36,7 @@ #include "style.h" #include "selection.h" #include "selection-chemistry.h" +#include "ui/dialog/filedialog.h" #include "xml/repr.h" using namespace Inkscape::UI::Widget; @@ -618,6 +625,137 @@ void PrefEntryButtonHBox::onRelatedButtonClickedCallback() } } +void PrefEntryFileButtonHBox::init(Glib::ustring const &prefs_path, + bool visibility) +{ + _prefs_path = prefs_path; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + relatedEntry = new Gtk::Entry(); + relatedEntry->set_invisible_char('*'); + relatedEntry->set_visibility(visibility); + relatedEntry->set_text(prefs->getString(_prefs_path)); + + relatedButton = new Gtk::Button(); + Gtk::HBox* pixlabel = new Gtk::HBox(false, 3); + Gtk::Image *im = new Gtk::Image(Gtk::StockID(Gtk::Stock::INDEX), + Gtk::ICON_SIZE_BUTTON); + pixlabel->pack_start(*im); + Gtk::Label *l = new Gtk::Label(); + l->set_markup_with_mnemonic(_("_Browse...")); + pixlabel->pack_start(*l); + relatedButton->add(*pixlabel); + + this->pack_end(*relatedButton, false, false, 4); + this->pack_start(*relatedEntry, true, true, 0); + + relatedButton->signal_clicked().connect( + sigc::mem_fun(*this, &PrefEntryFileButtonHBox::onRelatedButtonClickedCallback)); + relatedEntry->signal_changed().connect( + sigc::mem_fun(*this, &PrefEntryFileButtonHBox::onRelatedEntryChangedCallback)); +} + +void PrefEntryFileButtonHBox::onRelatedEntryChangedCallback() +{ + if (this->is_visible()) //only take action if user changed value + { + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + prefs->setString(_prefs_path, relatedEntry->get_text()); + } +} + +static Inkscape::UI::Dialog::FileOpenDialog * selectPrefsFileInstance = NULL; + +void PrefEntryFileButtonHBox::onRelatedButtonClickedCallback() +{ + if (this->is_visible()) //only take action if user changed value + { + //# Get the current directory for finding files + static Glib::ustring open_path; + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + + + Glib::ustring attr = prefs->getString(_prefs_path); + if (!attr.empty()) open_path = attr; + + //# Test if the open_path directory exists + if (!Inkscape::IO::file_test(open_path.c_str(), + (GFileTest)(G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR))) + open_path = ""; + +#ifdef WIN32 + //# If no open path, default to our win32 documents folder + if (open_path.empty()) + { + // The path to the My Documents folder is read from the + // value "HKEY_CURRENT_USER\Software\Windows\CurrentVersion\Explorer\Shell Folders\Personal" + HKEY key = NULL; + if(RegOpenKeyExA(HKEY_CURRENT_USER, + "Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Shell Folders", + 0, KEY_QUERY_VALUE, &key) == ERROR_SUCCESS) + { + WCHAR utf16path[_MAX_PATH]; + DWORD value_type; + DWORD data_size = sizeof(utf16path); + if(RegQueryValueExW(key, L"Personal", NULL, &value_type, + (BYTE*)utf16path, &data_size) == ERROR_SUCCESS) + { + g_assert(value_type == REG_SZ); + gchar *utf8path = g_utf16_to_utf8( + (const gunichar2*)utf16path, -1, NULL, NULL, NULL); + if(utf8path) + { + open_path = Glib::ustring(utf8path); + g_free(utf8path); + } + } + } + } +#endif + + //# If no open path, default to our home directory + if (open_path.empty()) + { + open_path = g_get_home_dir(); + open_path.append(G_DIR_SEPARATOR_S); + } + + //# Create a dialog + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + if (!selectPrefsFileInstance) { + selectPrefsFileInstance = + Inkscape::UI::Dialog::FileOpenDialog::create( + *desktop->getToplevel(), + open_path, + Inkscape::UI::Dialog::EXE_TYPES, + _("Select a bitmap editor")); + } + + //# Show the dialog + bool const success = selectPrefsFileInstance->show(); + + if (!success) { + return; + } + + //# User selected something. Get name and type + Glib::ustring fileName = selectPrefsFileInstance->getFilename(); + + if (!fileName.empty()) + { + Glib::ustring newFileName = Glib::filename_to_utf8(fileName); + + if ( newFileName.size() > 0) + open_path = newFileName; + else + g_warning( "ERROR CONVERTING OPEN FILENAME TO UTF-8" ); + + prefs->setString(_prefs_path, open_path); + } + + relatedEntry->set_text(fileName); + } +} void PrefFileButton::init(Glib::ustring const &prefs_path) { diff --git a/src/ui/widget/preferences-widget.h b/src/ui/widget/preferences-widget.h index 6c4533451..565b3468e 100644 --- a/src/ui/widget/preferences-widget.h +++ b/src/ui/widget/preferences-widget.h @@ -176,6 +176,19 @@ protected: void onRelatedButtonClickedCallback(); }; +class PrefEntryFileButtonHBox : public Gtk::HBox +{ +public: + void init(Glib::ustring const &prefs_path, + bool mask); +protected: + Glib::ustring _prefs_path; + Gtk::Button *relatedButton; + Gtk::Entry *relatedEntry; + void onRelatedEntryChangedCallback(); + void onRelatedButtonClickedCallback(); +}; + class PrefFileButton : public Gtk::FileChooserButton { public: -- cgit v1.2.3 From a85e8dc0f9158f740f613d8263d547e507d917f1 Mon Sep 17 00:00:00 2001 From: Alvin Penner Date: Mon, 21 Feb 2011 15:30:46 -0500 Subject: emf import. support for round rectangle (Bug 247695) Fixed bugs: - https://launchpad.net/bugs/247695 (bzr r10063) --- src/extension/internal/emf-win32-inout.cpp | 60 +++++++++++++++++++++++------- 1 file changed, 47 insertions(+), 13 deletions(-) (limited to 'src') diff --git a/src/extension/internal/emf-win32-inout.cpp b/src/extension/internal/emf-win32-inout.cpp index 76a1132ca..2a8b99e87 100644 --- a/src/extension/internal/emf-win32-inout.cpp +++ b/src/extension/internal/emf-win32-inout.cpp @@ -687,7 +687,7 @@ select_font(PEMF_CALLBACK_DATA d, int index) g_free(d->dc[d->level].tstyle.font_family.value); d->dc[d->level].tstyle.font_family.value = (gchar *) g_utf16_to_utf8( (gunichar2*) pEmr->elfw.elfLogFont.lfFaceName, -1, NULL, NULL, NULL ); - d->dc[d->level].style.text_transform.value = ((pEmr->elfw.elfLogFont.lfEscapement + 3600) % 3600) / 10; + d->dc[d->level].style.baseline_shift.value = ((pEmr->elfw.elfLogFont.lfEscapement + 3600) % 3600) / 10; // use baseline_shift instead of text_transform to avoid overflow } static void @@ -1563,8 +1563,42 @@ myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD const * break; } case EMR_ROUNDRECT: + { dbg_str << "\n"; + + PEMRROUNDRECT pEmr = (PEMRROUNDRECT) lpEMFR; + RECTL rc = pEmr->rclBox; + SIZEL corner = pEmr->szlCorner; + double f = 4.*(sqrt(2) - 1)/3; + + double l = pix_to_x_point(d, rc.left, rc.top); + double t = pix_to_y_point(d, rc.left, rc.top); + double r = pix_to_x_point(d, rc.right, rc.bottom); + double b = pix_to_y_point(d, rc.right, rc.bottom); + double cnx = pix_to_size_point(d, corner.cx/2); + double cny = pix_to_size_point(d, corner.cy/2); + + SVGOStringStream tmp_rectangle; + tmp_rectangle << "d=\""; + tmp_rectangle << "\n\tM " << l << ", " << t + cny << " "; + tmp_rectangle << "\n\tC " << l << ", " << t + (1-f)*cny << " " << l + (1-f)*cnx << ", " << t << " " << l + cnx << ", " << t << " "; + tmp_rectangle << "\n\tL " << r - cnx << ", " << t << " "; + tmp_rectangle << "\n\tC " << r - (1-f)*cnx << ", " << t << " " << r << ", " << t + (1-f)*cny << " " << r << ", " << t + cny << " "; + tmp_rectangle << "\n\tL " << r << ", " << b - cny << " "; + tmp_rectangle << "\n\tC " << r << ", " << b - (1-f)*cny << " " << r - (1-f)*cnx << ", " << b << " " << r - cnx << ", " << b << " "; + tmp_rectangle << "\n\tL " << l + cnx << ", " << b << " "; + tmp_rectangle << "\n\tC " << l + (1-f)*cnx << ", " << b << " " << l << ", " << b - (1-f)*cny << " " << l << ", " << b - cny << " "; + tmp_rectangle << "\n\tz"; + assert_empty_path(d, "EMR_ROUNDRECT"); + + *(d->outsvg) += " iType); + *(d->outsvg) += "\n\t"; + *(d->outsvg) += tmp_rectangle.str().c_str(); + *(d->outsvg) += " \" /> \n"; + *(d->path) = ""; break; + } case EMR_ARC: dbg_str << "\n"; break; @@ -1777,9 +1811,9 @@ myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD const * } if (!(d->dc[d->level].textAlign & TA_BOTTOM)) - if (d->dc[d->level].style.text_transform.value) { - x1 += std::sin(d->dc[d->level].style.text_transform.value*M_PI/180.0)*fabs(d->dc[d->level].style.font_size.computed); - y1 += std::cos(d->dc[d->level].style.text_transform.value*M_PI/180.0)*fabs(d->dc[d->level].style.font_size.computed); + if (d->dc[d->level].style.baseline_shift.value) { + x1 += std::sin(d->dc[d->level].style.baseline_shift.value*M_PI/180.0)*fabs(d->dc[d->level].style.font_size.computed); + y1 += std::cos(d->dc[d->level].style.baseline_shift.value*M_PI/180.0)*fabs(d->dc[d->level].style.font_size.computed); } else y1 += fabs(d->dc[d->level].style.font_size.computed); @@ -1807,14 +1841,14 @@ myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD const * gchar *escaped_text = g_markup_escape_text(ansi_text, -1); - float text_rgb[3]; - sp_color_get_rgb_floatv( &(d->dc[d->level].style.fill.value.color), text_rgb ); +// float text_rgb[3]; +// sp_color_get_rgb_floatv( &(d->dc[d->level].style.fill.value.color), text_rgb ); - if (!d->dc[d->level].textColorSet) { - d->dc[d->level].textColor = RGB(SP_COLOR_F_TO_U(text_rgb[0]), - SP_COLOR_F_TO_U(text_rgb[1]), - SP_COLOR_F_TO_U(text_rgb[2])); - } +// if (!d->dc[d->level].textColorSet) { +// d->dc[d->level].textColor = RGB(SP_COLOR_F_TO_U(text_rgb[0]), +// SP_COLOR_F_TO_U(text_rgb[1]), +// SP_COLOR_F_TO_U(text_rgb[2])); +// } char tmp[128]; snprintf(tmp, 127, @@ -1836,9 +1870,9 @@ myEnhMetaFileProc(HDC /*hDC*/, HANDLETABLE * /*lpHTable*/, ENHMETARECORD const * ts << " xml:space=\"preserve\"\n"; ts << " x=\"" << x << "\"\n"; ts << " y=\"" << y << "\"\n"; - if (d->dc[d->level].style.text_transform.value) { + if (d->dc[d->level].style.baseline_shift.value) { ts << " transform=\"" - << "rotate(-" << d->dc[d->level].style.text_transform.value + << "rotate(-" << d->dc[d->level].style.baseline_shift.value << " " << x << " " << y << ")" << "\"\n"; } -- cgit v1.2.3 From aa8c0d876949c952ab355c096017301a00734456 Mon Sep 17 00:00:00 2001 From: "Jon A. Cruz" Date: Mon, 21 Feb 2011 13:43:30 -0800 Subject: Finished cleanup of outdated SP_OBJECT_PARENT C macro. (bzr r10064) --- src/desktop-style.cpp | 146 ++++++++++++++++++++----------- src/dialogs/clonetiler.cpp | 46 +++++----- src/dialogs/xml-tree.cpp | 2 +- src/interface.cpp | 26 +++--- src/layer-manager.cpp | 12 +-- src/live_effects/lpeobject-reference.cpp | 4 +- src/object-hierarchy.cpp | 6 +- src/path-chemistry.cpp | 95 ++++++++++---------- src/selection-describer.cpp | 4 +- src/selection.cpp | 14 +-- src/sp-flowregion.cpp | 4 +- src/sp-object.h | 1 - src/sp-style-elem.cpp | 2 +- src/sp-tspan.cpp | 36 ++++---- src/sp-use-reference.cpp | 12 +-- src/sp-use.cpp | 72 +++++++-------- src/text-chemistry.cpp | 76 ++++++++-------- src/text-editing.cpp | 2 +- src/ui/widget/layer-selector.cpp | 14 +-- src/widgets/icon.cpp | 2 +- 20 files changed, 317 insertions(+), 259 deletions(-) (limited to 'src') diff --git a/src/desktop-style.cpp b/src/desktop-style.cpp index b8de8aadc..d2ec093fc 100644 --- a/src/desktop-style.cpp +++ b/src/desktop-style.cpp @@ -108,9 +108,9 @@ sp_desktop_apply_css_recursive(SPObject *o, SPCSSAttr *css, bool skip_lines) !(SP_IS_FLOWREGION(o) || SP_IS_FLOWREGIONEXCLUDE(o) || (SP_IS_USE(o) && - SP_OBJECT_PARENT(o) && - (SP_IS_FLOWREGION(SP_OBJECT_PARENT(o)) || - SP_IS_FLOWREGIONEXCLUDE(SP_OBJECT_PARENT(o)) + o->parent && + (SP_IS_FLOWREGION(o->parent) || + SP_IS_FLOWREGIONEXCLUDE(o->parent) ) ) ) @@ -431,7 +431,7 @@ stroke_average_width (GSList const *objects) notstroked = false; } - avgwidth += SP_OBJECT_STYLE (object)->stroke_width.computed * i2d.descrim(); + avgwidth += object->style->stroke_width.computed * i2d.descrim(); } if (notstroked) @@ -482,13 +482,15 @@ objects_query_fillstroke (GSList *objects, SPStyle *style_res, bool const isfill for (GSList const *i = objects; i != NULL; i = i->next) { SPObject *obj = SP_OBJECT (i->data); - SPStyle *style = SP_OBJECT_STYLE (obj); - if (!style) continue; + SPStyle *style = obj->style; + if (!style) { + continue; + } SPIPaint *paint = isfill? &style->fill : &style->stroke; // We consider paint "effectively set" for anything within text hierarchy - SPObject *parent = SP_OBJECT_PARENT (obj); + SPObject *parent = obj->parent; bool paint_effectively_set = paint->set || (SP_IS_TEXT(parent) || SP_IS_TEXTPATH(parent) || SP_IS_TSPAN(parent) || SP_IS_FLOWTEXT(parent) || SP_IS_FLOWDIV(parent) || SP_IS_FLOWPARA(parent) @@ -649,18 +651,22 @@ objects_query_opacity (GSList *objects, SPStyle *style_res) for (GSList const *i = objects; i != NULL; i = i->next) { SPObject *obj = SP_OBJECT (i->data); - SPStyle *style = SP_OBJECT_STYLE (obj); - if (!style) continue; + SPStyle *style = obj->style; + if (!style) { + continue; + } double opacity = SP_SCALE24_TO_FLOAT(style->opacity.value); opacity_sum += opacity; - if (opacity_prev != -1 && opacity != opacity_prev) + if (opacity_prev != -1 && opacity != opacity_prev) { same_opacity = false; + } opacity_prev = opacity; opacity_items ++; } - if (opacity_items > 1) + if (opacity_items > 1) { opacity_sum /= opacity_items; + } style_res->opacity.value = SP_SCALE24_FROM_FLOAT(opacity_sum); @@ -669,10 +675,11 @@ objects_query_opacity (GSList *objects, SPStyle *style_res) } else if (opacity_items == 1) { return QUERY_STYLE_SINGLE; } else { - if (same_opacity) + if (same_opacity) { return QUERY_STYLE_MULTIPLE_SAME; - else + } else { return QUERY_STYLE_MULTIPLE_AVERAGED; + } } } @@ -697,9 +704,13 @@ objects_query_strokewidth (GSList *objects, SPStyle *style_res) for (GSList const *i = objects; i != NULL; i = i->next) { SPObject *obj = SP_OBJECT (i->data); - if (!SP_IS_ITEM(obj)) continue; - SPStyle *style = SP_OBJECT_STYLE (obj); - if (!style) continue; + if (!SP_IS_ITEM(obj)) { + continue; + } + SPStyle *style = obj->style; + if (!style) { + continue; + } if ( style->stroke.isNone() && !( style->marker[SP_MARKER_LOC].set || // stroke width affects markers, so if there's no stroke but only markers then we should @@ -762,9 +773,13 @@ objects_query_miterlimit (GSList *objects, SPStyle *style_res) for (GSList const *i = objects; i != NULL; i = i->next) { SPObject *obj = SP_OBJECT (i->data); - if (!SP_IS_ITEM(obj)) continue; - SPStyle *style = SP_OBJECT_STYLE (obj); - if (!style) continue; + if (!SP_IS_ITEM(obj)) { + continue; + } + SPStyle *style = obj->style; + if (!style) { + continue; + } if ( style->stroke.isNone() ) { continue; @@ -772,15 +787,17 @@ objects_query_miterlimit (GSList *objects, SPStyle *style_res) n_stroked ++; - if (prev_ml != -1 && fabs(style->stroke_miterlimit.value - prev_ml) > 1e-3) + if (prev_ml != -1 && fabs(style->stroke_miterlimit.value - prev_ml) > 1e-3) { same_ml = false; + } prev_ml = style->stroke_miterlimit.value; avgml += style->stroke_miterlimit.value; } - if (n_stroked > 1) + if (n_stroked > 1) { avgml /= (n_stroked); + } style_res->stroke_miterlimit.value = avgml; style_res->stroke_miterlimit.set = true; @@ -815,9 +832,13 @@ objects_query_strokecap (GSList *objects, SPStyle *style_res) for (GSList const *i = objects; i != NULL; i = i->next) { SPObject *obj = SP_OBJECT (i->data); - if (!SP_IS_ITEM(obj)) continue; - SPStyle *style = SP_OBJECT_STYLE (obj); - if (!style) continue; + if (!SP_IS_ITEM(obj)) { + continue; + } + SPStyle *style = obj->style; + if (!style) { + continue; + } if ( style->stroke.isNone() ) { continue; @@ -865,9 +886,13 @@ objects_query_strokejoin (GSList *objects, SPStyle *style_res) for (GSList const *i = objects; i != NULL; i = i->next) { SPObject *obj = SP_OBJECT (i->data); - if (!SP_IS_ITEM(obj)) continue; - SPStyle *style = SP_OBJECT_STYLE (obj); - if (!style) continue; + if (!SP_IS_ITEM(obj)) { + continue; + } + SPStyle *style = obj->style; + if (!style) { + continue; + } if ( style->stroke.isNone() ) { continue; @@ -875,8 +900,9 @@ objects_query_strokejoin (GSList *objects, SPStyle *style_res) n_stroked ++; - if (prev_join != -1 && style->stroke_linejoin.value != prev_join) + if (prev_join != -1 && style->stroke_linejoin.value != prev_join) { same_join = false; + } prev_join = style->stroke_linejoin.value; join = style->stroke_linejoin.value; @@ -925,26 +951,31 @@ objects_query_fontnumbers (GSList *objects, SPStyle *style_res) if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj) && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj) - && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) + && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) { continue; + } - SPStyle *style = SP_OBJECT_STYLE (obj); - if (!style) continue; + SPStyle *style = obj->style; + if (!style) { + continue; + } texts ++; size += style->font_size.computed * Geom::Affine(SP_ITEM(obj)->i2d_affine()).descrim(); /// \todo FIXME: we assume non-% units here if (style->letter_spacing.normal) { - if (!different && (letterspacing_prev == 0 || letterspacing_prev == letterspacing)) + if (!different && (letterspacing_prev == 0 || letterspacing_prev == letterspacing)) { letterspacing_normal = true; + } } else { letterspacing += style->letter_spacing.computed; /// \todo FIXME: we assume non-% units here letterspacing_normal = false; } if (style->word_spacing.normal) { - if (!different && (wordspacing_prev == 0 || wordspacing_prev == wordspacing)) + if (!different && (wordspacing_prev == 0 || wordspacing_prev == wordspacing)) { wordspacing_normal = true; + } } else { wordspacing += style->word_spacing.computed; /// \todo FIXME: we assume non-% units here wordspacing_normal = false; @@ -1035,8 +1066,10 @@ objects_query_fontstyle (GSList *objects, SPStyle *style_res) && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) continue; - SPStyle *style = SP_OBJECT_STYLE (obj); - if (!style) continue; + SPStyle *style = obj->style; + if (!style) { + continue; + } texts ++; @@ -1095,11 +1128,14 @@ objects_query_baselines (GSList *objects, SPStyle *style_res) if (!SP_IS_TEXT(obj) && !SP_IS_FLOWTEXT(obj) && !SP_IS_TSPAN(obj) && !SP_IS_TREF(obj) && !SP_IS_TEXTPATH(obj) - && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) + && !SP_IS_FLOWDIV(obj) && !SP_IS_FLOWPARA(obj) && !SP_IS_FLOWTSPAN(obj)) { continue; + } - SPStyle *style = SP_OBJECT_STYLE (obj); - if (!style) continue; + SPStyle *style = obj->style; + if (!style) { + continue; + } texts ++; @@ -1187,8 +1223,10 @@ objects_query_fontfamily (GSList *objects, SPStyle *style_res) continue; } - SPStyle *style = SP_OBJECT_STYLE (obj); - if (!style) continue; + SPStyle *style = obj->style; + if (!style) { + continue; + } texts ++; @@ -1206,8 +1244,9 @@ objects_query_fontfamily (GSList *objects, SPStyle *style_res) style_res->text->font_family.value = g_strdup(style->text->font_family.value); } - if (texts == 0 || !style_res->text->font_family.set) + if (texts == 0 || !style_res->text->font_family.set) { return QUERY_STYLE_NOTHING; + } if (texts > 1) { if (different) { @@ -1242,8 +1281,10 @@ objects_query_fontspecification (GSList *objects, SPStyle *style_res) continue; } - SPStyle *style = SP_OBJECT_STYLE (obj); - if (!style) continue; + SPStyle *style = obj->style; + if (!style) { + continue; + } texts ++; @@ -1265,8 +1306,9 @@ objects_query_fontspecification (GSList *objects, SPStyle *style_res) } } - if (texts == 0) + if (texts == 0) { return QUERY_STYLE_NOTHING; + } if (texts > 1) { if (different) { @@ -1291,8 +1333,10 @@ objects_query_blend (GSList *objects, SPStyle *style_res) for (GSList const *i = objects; i != NULL; i = i->next) { SPObject *obj = SP_OBJECT (i->data); - SPStyle *style = SP_OBJECT_STYLE (obj); - if(!style || !SP_IS_ITEM(obj)) continue; + SPStyle *style = obj->style; + if (!style || !SP_IS_ITEM(obj)) { + continue; + } items++; @@ -1376,9 +1420,13 @@ objects_query_blur (GSList *objects, SPStyle *style_res) for (GSList const *i = objects; i != NULL; i = i->next) { SPObject *obj = SP_OBJECT (i->data); - SPStyle *style = SP_OBJECT_STYLE (obj); - if (!style) continue; - if (!SP_IS_ITEM(obj)) continue; + SPStyle *style = obj->style; + if (!style) { + continue; + } + if (!SP_IS_ITEM(obj)) { + continue; + } Geom::Affine i2d = SP_ITEM(obj)->i2d_affine(); diff --git a/src/dialogs/clonetiler.cpp b/src/dialogs/clonetiler.cpp index bd5be5be5..c83c38a01 100644 --- a/src/dialogs/clonetiler.cpp +++ b/src/dialogs/clonetiler.cpp @@ -803,27 +803,29 @@ clonetiler_get_transform ( static bool clonetiler_is_a_clone_of (SPObject *tile, SPObject *obj) { + bool result = false; char *id_href = NULL; if (obj) { - Inkscape::XML::Node *obj_repr = SP_OBJECT_REPR(obj); + Inkscape::XML::Node *obj_repr = obj->getRepr(); id_href = g_strdup_printf("#%s", obj_repr->attribute("id")); } if (SP_IS_USE(tile) && - SP_OBJECT_REPR(tile)->attribute("xlink:href") && - (!id_href || !strcmp(id_href, SP_OBJECT_REPR(tile)->attribute("xlink:href"))) && - SP_OBJECT_REPR(tile)->attribute("inkscape:tiled-clone-of") && - (!id_href || !strcmp(id_href, SP_OBJECT_REPR(tile)->attribute("inkscape:tiled-clone-of")))) + tile->getRepr()->attribute("xlink:href") && + (!id_href || !strcmp(id_href, tile->getRepr()->attribute("xlink:href"))) && + tile->getRepr()->attribute("inkscape:tiled-clone-of") && + (!id_href || !strcmp(id_href, tile->getRepr()->attribute("inkscape:tiled-clone-of")))) { - if (id_href) - g_free (id_href); - return true; + result = true; } else { - if (id_href) - g_free (id_href); - return false; + result = false; } + if (id_href) { + g_free(id_href); + id_href = 0; + } + return result; } static NRArena const *trace_arena = NULL; @@ -856,7 +858,7 @@ clonetiler_trace_setup (SPDocument *doc, gdouble zoom, SPItem *original) // hide the (current) original and any tiled clones, we only want to pick the background original->invoke_hide(trace_visionkey); - clonetiler_trace_hide_tiled_clones_recursively(SP_OBJECT(trace_doc->getRoot())); + clonetiler_trace_hide_tiled_clones_recursively(trace_doc->getRoot()); trace_doc->getRoot()->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG); trace_doc->ensureUpToDate(); @@ -965,8 +967,8 @@ clonetiler_unclump( GtkWidget */*widget*/, void * ) return; } - SPObject *obj = SP_OBJECT(selection->singleItem()); - SPObject *parent = SP_OBJECT_PARENT (obj); + SPObject *obj = selection->singleItem(); + SPObject *parent = obj->parent; GSList *to_unclump = NULL; // not including the original @@ -989,7 +991,7 @@ clonetiler_unclump( GtkWidget */*widget*/, void * ) static guint clonetiler_number_of_clones (SPObject *obj) { - SPObject *parent = SP_OBJECT_PARENT (obj); + SPObject *parent = obj->parent; guint n = 0; @@ -1017,8 +1019,8 @@ clonetiler_remove( GtkWidget */*widget*/, void *, bool do_undo = true ) return; } - SPObject *obj = SP_OBJECT(selection->singleItem()); - SPObject *parent = SP_OBJECT_PARENT (obj); + SPObject *obj = selection->singleItem(); + SPObject *parent = obj->parent; // remove old tiling GSList *to_delete = NULL; @@ -1102,10 +1104,10 @@ clonetiler_apply( GtkWidget */*widget*/, void * ) gtk_widget_queue_draw(GTK_WIDGET(status)); gdk_window_process_all_updates(); - SPObject *obj = SP_OBJECT(selection->singleItem()); - Inkscape::XML::Node *obj_repr = SP_OBJECT_REPR(obj); + SPObject *obj = selection->singleItem(); + Inkscape::XML::Node *obj_repr = obj->getRepr(); const char *id_href = g_strdup_printf("#%s", obj_repr->attribute("id")); - SPObject *parent = SP_OBJECT_PARENT (obj); + SPObject *parent = obj->parent; clonetiler_remove (NULL, NULL, false); @@ -1462,7 +1464,7 @@ clonetiler_apply( GtkWidget */*widget*/, void * ) } // add the new clone to the top of the original's parent - SP_OBJECT_REPR(parent)->appendChild(clone); + parent->getRepr()->appendChild(clone); if (blur > 0.0) { SPObject *clone_object = sp_desktop_document(desktop)->getObjectByRepr(clone); @@ -1475,7 +1477,7 @@ clonetiler_apply( GtkWidget */*widget*/, void * ) // that we can take bbox of; however here we only need a lower bound so that blur // margins are not too small, and the perimeter should work SPFilter *constructed = new_filter_gaussian_blur(sp_desktop_document(desktop), radius, t.descrim(), t.expansionX(), t.expansionY(), perimeter, perimeter); - sp_style_set_property_url (clone_object, "filter", SP_OBJECT(constructed), false); + sp_style_set_property_url (clone_object, "filter", constructed, false); } if (center_set) { diff --git a/src/dialogs/xml-tree.cpp b/src/dialogs/xml-tree.cpp index d25bdad72..ddb419dcd 100644 --- a/src/dialogs/xml-tree.cpp +++ b/src/dialogs/xml-tree.cpp @@ -1602,7 +1602,7 @@ bool in_dt_coordsys(SPObject const &item) if (!SP_IS_ITEM(child)) { return false; } - SPObject const * const parent = SP_OBJECT_PARENT(child); + SPObject const * const parent = child->parent; if (parent == NULL) { break; } diff --git a/src/interface.cpp b/src/interface.cpp index 551e2bf91..3c310b8d1 100644 --- a/src/interface.cpp +++ b/src/interface.cpp @@ -1025,7 +1025,7 @@ sp_ui_main_menubar(Inkscape::UI::View::View *view) } static void leave_group(GtkMenuItem *, SPDesktop *desktop) { - desktop->setCurrentLayer(SP_OBJECT_PARENT(desktop->currentLayer())); + desktop->setCurrentLayer(desktop->currentLayer()->parent); } static void enter_group(GtkMenuItem *mi, SPDesktop *desktop) { @@ -1071,13 +1071,13 @@ sp_ui_context_menu(Inkscape::UI::View::View *view, SPItem *item) if (item) { if (SP_IS_GROUP(item)) { group = SP_GROUP(item); - } else if ( item != dt->currentRoot() && SP_IS_GROUP(SP_OBJECT_PARENT(item)) ) { - group = SP_GROUP(SP_OBJECT_PARENT(item)); + } else if ( item != dt->currentRoot() && SP_IS_GROUP(item->parent) ) { + group = SP_GROUP(item->parent); } } if (( group && group != dt->currentLayer() ) || - ( dt->currentLayer() != dt->currentRoot() && SP_OBJECT_PARENT(dt->currentLayer()) != dt->currentRoot() ) ) { + ( dt->currentLayer() != dt->currentRoot() && dt->currentLayer()->parent != dt->currentRoot() ) ) { /* Separator */ sp_ui_menu_append_item(GTK_MENU(m), NULL, NULL, NULL, NULL, NULL, NULL); } @@ -1094,7 +1094,7 @@ sp_ui_context_menu(Inkscape::UI::View::View *view, SPItem *item) } if ( dt->currentLayer() != dt->currentRoot() ) { - if ( SP_OBJECT_PARENT(dt->currentLayer()) != dt->currentRoot() ) { + if ( dt->currentLayer()->parent != dt->currentRoot() ) { GtkWidget *w = gtk_menu_item_new_with_label(_("Go to parent")); g_signal_connect(G_OBJECT(w), "activate", GCallback(leave_group), dt); gtk_widget_show(w); @@ -1167,10 +1167,10 @@ sp_ui_drag_data_received(GtkWidget *widget, g_free(str); str = 0; - SP_OBJECT(item)->setAttribute( - fillnotstroke ? "inkscape:x-fill-tag":"inkscape:x-stroke-tag", - palName.c_str(), - false ); + item->setAttribute( + fillnotstroke ? "inkscape:x-fill-tag":"inkscape:x-stroke-tag", + palName.c_str(), + false ); item->updateRepr(); sp_repr_css_set_property( css, fillnotstroke ? "fill":"stroke", c ); @@ -1251,9 +1251,9 @@ sp_ui_drag_data_received(GtkWidget *widget, Inkscape::Preferences *prefs = Inkscape::Preferences::get(); delta = desktop->d2w(delta); double stroke_tolerance = - ( !SP_OBJECT_STYLE(item)->stroke.isNone() ? + ( !item->style->stroke.isNone() ? desktop->current_zoom() * - SP_OBJECT_STYLE (item)->stroke_width.computed * + item->style->stroke_width.computed * to_2geom(item->i2d_affine()).descrim() * 0.5 : 0.0) + prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); @@ -1354,9 +1354,9 @@ sp_ui_drag_data_received(GtkWidget *widget, Inkscape::Preferences *prefs = Inkscape::Preferences::get(); delta = desktop->d2w(delta); double stroke_tolerance = - ( !SP_OBJECT_STYLE(item)->stroke.isNone() ? + ( !item->style->stroke.isNone() ? desktop->current_zoom() * - SP_OBJECT_STYLE (item)->stroke_width.computed * + item->style->stroke_width.computed * to_2geom(item->i2d_affine()).descrim() * 0.5 : 0.0) + prefs->getIntLimited("/options/dragtolerance/value", 0, 0, 100); diff --git a/src/layer-manager.cpp b/src/layer-manager.cpp index 95cefc229..e07d7b945 100644 --- a/src/layer-manager.cpp +++ b/src/layer-manager.cpp @@ -236,7 +236,7 @@ void LayerManager::_rebuild() { LayerWatcher* one = _watchers.back(); _watchers.pop_back(); if ( one->_obj ) { - Node* node = SP_OBJECT_REPR(one->_obj); + Node* node = one->_obj->getRepr(); if ( node ) { node->removeObserver(*one); } @@ -264,7 +264,7 @@ void LayerManager::_rebuild() { if ( root->isAncestorOf(layer) ) { needsAdd = true; - for ( SPObject* curr = layer; curr && (curr != root) && needsAdd; curr = SP_OBJECT_PARENT(curr) ) { + for ( SPObject* curr = layer; curr && (curr != root) && needsAdd; curr = curr->parent ) { if ( SP_IS_GROUP(curr) ) { SPGroup* group = SP_GROUP(curr); if ( group->layerMode() == SPGroup::LAYER ) { @@ -307,10 +307,10 @@ void LayerManager::_rebuild() { // See http://sourceforge.net/tracker/index.php?func=detail&aid=1339397&group_id=93438&atid=604306 SPObject const *higher = layer; - while ( higher && (SP_OBJECT_PARENT(higher) != root) ) { - higher = SP_OBJECT_PARENT(higher); + while ( higher && (higher->parent != root) ) { + higher = higher->parent; } - Node* node = higher ? SP_OBJECT_REPR(higher) : 0; + Node const* node = higher ? higher->getRepr() : 0; if ( node && node->parent() ) { // Debug::EventTracker tracker(*layer); @@ -318,7 +318,7 @@ void LayerManager::_rebuild() { LayerWatcher *eye = new LayerWatcher(this, layer, connection); _watchers.push_back( eye ); - SP_OBJECT_REPR(layer)->addObserver(*eye); + layer->getRepr()->addObserver(*eye); _addOne(layer); } diff --git a/src/live_effects/lpeobject-reference.cpp b/src/live_effects/lpeobject-reference.cpp index 9163d1c91..573c8a2fd 100644 --- a/src/live_effects/lpeobject-reference.cpp +++ b/src/live_effects/lpeobject-reference.cpp @@ -45,7 +45,7 @@ bool LPEObjectReference::_acceptObject(SPObject * const obj) const if (IS_LIVEPATHEFFECT(obj)) { SPObject * const owner = getOwner(); /* Refuse references to us or to an ancestor. */ - for ( SPObject *iter = owner ; iter ; iter = SP_OBJECT_PARENT(iter) ) { + for ( SPObject *iter = owner ; iter ; iter = iter->parent ) { if ( iter == obj ) { return false; } @@ -94,7 +94,7 @@ LPEObjectReference::start_listening(LivePathEffectObject* to) return; } lpeobject = to; - lpeobject_repr = SP_OBJECT_REPR(to); + lpeobject_repr = to->getRepr(); _delete_connection = to->connectDelete(sigc::bind(sigc::ptr_fun(&lpeobjectreference_delete_self), this)); _modified_connection = to->connectModified(sigc::bind<2>(sigc::ptr_fun(&lpeobjectreference_source_modified), this)); } diff --git a/src/object-hierarchy.cpp b/src/object-hierarchy.cpp index 55af55f28..e6a1618a7 100644 --- a/src/object-hierarchy.cpp +++ b/src/object-hierarchy.cpp @@ -70,10 +70,10 @@ void ObjectHierarchy::_addTop(SPObject *senior, SPObject *junior) { g_assert(junior != NULL); g_assert(senior != NULL); - SPObject *object=SP_OBJECT_PARENT(junior); + SPObject *object = junior->parent; do { _addTop(object); - object = SP_OBJECT_PARENT(object); + object = object->parent; } while ( object != senior ); } @@ -160,7 +160,7 @@ void ObjectHierarchy::_addBottom(SPObject *senior, SPObject *junior) { g_assert(senior != NULL); if ( junior != senior ) { - _addBottom(senior, SP_OBJECT_PARENT(junior)); + _addBottom(senior, junior->parent); _addBottom(junior); } } diff --git a/src/path-chemistry.cpp b/src/path-chemistry.cpp index bec3c5cbf..607d0ab6a 100644 --- a/src/path-chemistry.cpp +++ b/src/path-chemistry.cpp @@ -95,8 +95,9 @@ sp_selected_path_combine(SPDesktop *desktop) for (GSList *i = items; i != NULL; i = i->next) { // going from top to bottom SPItem *item = (SPItem *) i->data; - if (!SP_IS_PATH(item)) + if (!SP_IS_PATH(item)) { continue; + } if (!did) { selection->clear(); @@ -106,17 +107,17 @@ sp_selected_path_combine(SPDesktop *desktop) SPCurve *c = sp_path_get_curve_for_edit(SP_PATH(item)); if (first == NULL) { // this is the topmost path first = item; - parent = SP_OBJECT_REPR(first)->parent(); - position = SP_OBJECT_REPR(first)->position(); - id = SP_OBJECT_REPR(first)->attribute("id"); - transform = SP_OBJECT_REPR(first)->attribute("transform"); + parent = first->getRepr()->parent(); + position = first->getRepr()->position(); + id = first->getRepr()->attribute("id"); + transform = first->getRepr()->attribute("transform"); // FIXME: merge styles of combined objects instead of using the first one's style - style = g_strdup(SP_OBJECT_REPR(first)->attribute("style")); - path_effect = g_strdup(SP_OBJECT_REPR(first)->attribute("inkscape:path-effect")); + style = g_strdup(first->getRepr()->attribute("style")); + path_effect = g_strdup(first->getRepr()->attribute("inkscape:path-effect")); //c->transform(item->transform); curve = c; } else { - c->transform(item->getRelativeTransform(SP_OBJECT(first))); + c->transform(item->getRelativeTransform(first)); curve->append(c, false); c->unref(); } @@ -124,17 +125,18 @@ sp_selected_path_combine(SPDesktop *desktop) // unless this is the topmost object, if (item != first) { // reduce position only if the same parent - if (SP_OBJECT_REPR(item)->parent() == parent) + if (item->getRepr()->parent() == parent) { position--; + } // delete the object for real, so that its clones can take appropriate action - SP_OBJECT(item)->deleteObject(); + item->deleteObject(); } } g_slist_free(items); if (did) { - SP_OBJECT(first)->deleteObject(false); + first->deleteObject(false); // delete the topmost. Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc(); @@ -214,21 +216,21 @@ sp_selected_path_break_apart(SPDesktop *desktop) did = true; - Inkscape::XML::Node *parent = SP_OBJECT_REPR(item)->parent(); - gint pos = SP_OBJECT_REPR(item)->position(); - char const *id = SP_OBJECT_REPR(item)->attribute("id"); + Inkscape::XML::Node *parent = item->getRepr()->parent(); + gint pos = item->getRepr()->position(); + char const *id = item->getRepr()->attribute("id"); // XML Tree being used directly here while it shouldn't be... - gchar *style = g_strdup(SP_OBJECT(item)->getRepr()->attribute("style")); + gchar *style = g_strdup(item->getRepr()->attribute("style")); // XML Tree being used directly here while it shouldn't be... - gchar *path_effect = g_strdup(SP_OBJECT(item)->getRepr()->attribute("inkscape:path-effect")); + gchar *path_effect = g_strdup(item->getRepr()->attribute("inkscape:path-effect")); Geom::PathVector apv = curve->get_pathvector() * SP_ITEM(path)->transform; curve->unref(); // it's going to resurrect as one of the pieces, so we delete without advertisement - SP_OBJECT(item)->deleteObject(false); + item->deleteObject(false); curve = new SPCurve(apv); g_assert(curve != NULL); @@ -380,7 +382,7 @@ sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_selec if (SP_IS_BOX3D(item)) { // convert 3D box to ordinary group of paths; replace the old element in 'selected' with the new group - Inkscape::XML::Node *repr = SP_OBJECT_REPR(box3d_convert_to_group(SP_BOX3D(item))); + Inkscape::XML::Node *repr = box3d_convert_to_group(SP_BOX3D(item))->getRepr(); if (repr) { *to_select = g_slist_prepend (*to_select, repr); @@ -416,18 +418,18 @@ sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_selec *selected = g_slist_remove (*selected, item); // remember the position of the item - gint pos = SP_OBJECT_REPR(item)->position(); + gint pos = item->getRepr()->position(); // remember parent - Inkscape::XML::Node *parent = SP_OBJECT_REPR(item)->parent(); + Inkscape::XML::Node *parent = item->getRepr()->parent(); // remember id - char const *id = SP_OBJECT_REPR(item)->attribute("id"); + char const *id = item->getRepr()->attribute("id"); // remember title gchar *title = item->title(); // remember description gchar *desc = item->desc(); // It's going to resurrect, so we delete without notifying listeners. - SP_OBJECT(item)->deleteObject(false); + item->deleteObject(false); // restore id repr->setAttribute("id", id); @@ -461,26 +463,26 @@ sp_selected_item_to_curved_repr(SPItem *item, guint32 /*text_grouping_policy*/) if (!item) return NULL; - Inkscape::XML::Document *xml_doc = SP_OBJECT_REPR(item)->document(); + Inkscape::XML::Document *xml_doc = item->getRepr()->document(); if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { // Special treatment for text: convert each glyph to separate path, then group the paths Inkscape::XML::Node *g_repr = xml_doc->createElement("svg:g"); - g_repr->setAttribute("transform", SP_OBJECT_REPR(item)->attribute("transform")); + g_repr->setAttribute("transform", item->getRepr()->attribute("transform")); /* Mask */ - gchar *mask_str = (gchar *) SP_OBJECT_REPR(item)->attribute("mask"); + gchar *mask_str = (gchar *) item->getRepr()->attribute("mask"); if ( mask_str ) g_repr->setAttribute("mask", mask_str); /* Clip path */ - gchar *clip_path_str = (gchar *) SP_OBJECT_REPR(item)->attribute("clip-path"); + gchar *clip_path_str = (gchar *) item->getRepr()->attribute("clip-path"); if ( clip_path_str ) g_repr->setAttribute("clip-path", clip_path_str); /* Rotation center */ - g_repr->setAttribute("inkscape:transform-center-x", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-x"), false); - g_repr->setAttribute("inkscape:transform-center-y", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-y"), false); + g_repr->setAttribute("inkscape:transform-center-x", item->getRepr()->attribute("inkscape:transform-center-x"), false); + g_repr->setAttribute("inkscape:transform-center-y", item->getRepr()->attribute("inkscape:transform-center-y"), false); /* Whole text's style */ - gchar *style_str = sp_style_write_difference(SP_OBJECT_STYLE(item), - SP_OBJECT_STYLE(SP_OBJECT_PARENT(item))); + gchar *style_str = sp_style_write_difference(item->style, + item->parent->style); g_repr->setAttribute("style", style_str); g_free(style_str); Inkscape::Text::Layout::iterator iter = te_get_layout(item)->begin(); @@ -497,11 +499,11 @@ sp_selected_item_to_curved_repr(SPItem *item, guint32 /*text_grouping_policy*/) if (!rawptr || !SP_IS_OBJECT(rawptr)) // no source for glyph, abort break; pos_obj = SP_OBJECT(rawptr); - while (SP_IS_STRING(pos_obj) && SP_OBJECT_PARENT(pos_obj)) { - pos_obj = SP_OBJECT_PARENT(pos_obj); // SPStrings don't have style + while (SP_IS_STRING(pos_obj) && pos_obj->parent) { + pos_obj = pos_obj->parent; // SPStrings don't have style } - gchar *style_str = sp_style_write_difference(SP_OBJECT_STYLE(pos_obj), - SP_OBJECT_STYLE(SP_OBJECT_PARENT(pos_obj))); + gchar *style_str = sp_style_write_difference(pos_obj->style, + pos_obj->parent->style); // get path from iter to iter_next: SPCurve *curve = te_get_layout(item)->convertToCurves(iter, iter_next); @@ -555,26 +557,26 @@ sp_selected_item_to_curved_repr(SPItem *item, guint32 /*text_grouping_policy*/) Inkscape::XML::Node *repr = xml_doc->createElement("svg:path"); /* Transformation */ - repr->setAttribute("transform", SP_OBJECT_REPR(item)->attribute("transform")); + repr->setAttribute("transform", item->getRepr()->attribute("transform")); /* Style */ - gchar *style_str = sp_style_write_difference(SP_OBJECT_STYLE(item), - SP_OBJECT_STYLE(SP_OBJECT_PARENT(item))); + gchar *style_str = sp_style_write_difference(item->style, + item->parent->style); repr->setAttribute("style", style_str); g_free(style_str); /* Mask */ - gchar *mask_str = (gchar *) SP_OBJECT_REPR(item)->attribute("mask"); + gchar *mask_str = (gchar *) item->getRepr()->attribute("mask"); if ( mask_str ) repr->setAttribute("mask", mask_str); /* Clip path */ - gchar *clip_path_str = (gchar *) SP_OBJECT_REPR(item)->attribute("clip-path"); + gchar *clip_path_str = (gchar *) item->getRepr()->attribute("clip-path"); if ( clip_path_str ) repr->setAttribute("clip-path", clip_path_str); /* Rotation center */ - repr->setAttribute("inkscape:transform-center-x", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-x"), false); - repr->setAttribute("inkscape:transform-center-y", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-y"), false); + repr->setAttribute("inkscape:transform-center-x", item->getRepr()->attribute("inkscape:transform-center-x"), false); + repr->setAttribute("inkscape:transform-center-y", item->getRepr()->attribute("inkscape:transform-center-y"), false); /* Definition */ gchar *def_str = sp_svg_write_path(curve->get_pathvector()); @@ -605,8 +607,9 @@ sp_selected_path_reverse(SPDesktop *desktop) for (GSList *i = items; i != NULL; i = i->next) { - if (!SP_IS_PATH(i->data)) + if (!SP_IS_PATH(i->data)) { continue; + } did = true; SPPath *path = SP_PATH(i->data); @@ -615,18 +618,18 @@ sp_selected_path_reverse(SPDesktop *desktop) gchar *str = sp_svg_write_path(rcurve->get_pathvector()); if ( sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(path)) ) { - SP_OBJECT_REPR(path)->setAttribute("inkscape:original-d", str); + path->getRepr()->setAttribute("inkscape:original-d", str); } else { - SP_OBJECT_REPR(path)->setAttribute("d", str); + path->getRepr()->setAttribute("d", str); } g_free(str); rcurve->unref(); // reverse nodetypes order (Bug #179866) - gchar *nodetypes = g_strdup(SP_OBJECT_REPR(path)->attribute("sodipodi:nodetypes")); + gchar *nodetypes = g_strdup(path->getRepr()->attribute("sodipodi:nodetypes")); if ( nodetypes ) { - SP_OBJECT_REPR(path)->setAttribute("sodipodi:nodetypes", g_strreverse(nodetypes)); + path->getRepr()->setAttribute("sodipodi:nodetypes", g_strreverse(nodetypes)); g_free(nodetypes); } } diff --git a/src/selection-describer.cpp b/src/selection-describer.cpp index 7bc6adf38..5693ce351 100644 --- a/src/selection-describer.cpp +++ b/src/selection-describer.cpp @@ -128,7 +128,7 @@ void SelectionDescriber::_updateMessageFromSelection(Inkscape::Selection *select _context.set(Inkscape::NORMAL_MESSAGE, _when_nothing); } else { SPItem *item = SP_ITEM(items->data); - SPObject *layer = selection->desktop()->layerForObject (SP_OBJECT (item)); + SPObject *layer = selection->desktop()->layerForObject(item); SPObject *root = selection->desktop()->currentRoot(); // Layer name @@ -154,7 +154,7 @@ void SelectionDescriber::_updateMessageFromSelection(Inkscape::Selection *select } // Parent name - SPObject *parent = SP_OBJECT_PARENT (item); + SPObject *parent = item->parent; gchar const *parent_label = parent->getId(); char *quoted_parent_label = xml_quote_strdup(parent_label); gchar *parent_name = g_strdup_printf(_("%s"), quoted_parent_label); diff --git a/src/selection.cpp b/src/selection.cpp index 79a71afbd..7564fad3a 100644 --- a/src/selection.cpp +++ b/src/selection.cpp @@ -308,7 +308,7 @@ GSList const *Selection::reprList() { for ( GSList const *iter=itemList() ; iter != NULL ; iter = iter->next ) { SPObject *obj=reinterpret_cast(iter->data); - _reprs = g_slist_prepend(_reprs, SP_OBJECT_REPR(obj)); + _reprs = g_slist_prepend(_reprs, obj->getRepr()); } _reprs = g_slist_reverse(_reprs); @@ -359,7 +359,7 @@ SPItem *Selection::singleItem() { Inkscape::XML::Node *Selection::singleRepr() { SPObject *obj=single(); - return obj ? SP_OBJECT_REPR(obj) : NULL; + return obj ? obj->getRepr() : NULL; } NRRect *Selection::bounds(NRRect *bbox, SPItem::BBoxType type) const @@ -489,24 +489,24 @@ void Selection::_removeObjectDescendants(SPObject *obj) { for ( iter = _objs ; iter ; iter = next ) { next = iter->next; SPObject *sel_obj=reinterpret_cast(iter->data); - SPObject *parent=SP_OBJECT_PARENT(sel_obj); + SPObject *parent = sel_obj->parent; while (parent) { if ( parent == obj ) { _remove(sel_obj); break; } - parent = SP_OBJECT_PARENT(parent); + parent = parent->parent; } } } void Selection::_removeObjectAncestors(SPObject *obj) { - SPObject *parent=SP_OBJECT_PARENT(obj); + SPObject *parent = obj->parent; while (parent) { if (includes(parent)) { _remove(parent); } - parent = SP_OBJECT_PARENT(parent); + parent = parent->parent; } } @@ -537,7 +537,7 @@ guint Selection::numberOfParents() { GSList const *items = const_cast(this)->itemList(); GSList *parents = NULL; for (GSList const *iter = items; iter != NULL; iter = iter->next) { - SPObject *parent = SP_OBJECT_PARENT(iter->data); + SPObject *parent = SP_OBJECT(iter->data)->parent; if (g_slist_find (parents, parent) == NULL) { parents = g_slist_prepend (parents, parent); } diff --git a/src/sp-flowregion.cpp b/src/sp-flowregion.cpp index 210f350b8..46690167f 100644 --- a/src/sp-flowregion.cpp +++ b/src/sp-flowregion.cpp @@ -507,7 +507,7 @@ static void GetDest(SPObject* child,Shape **computed) SPObject* u_child=child; if ( SP_IS_USE(u_child) ) { u_child=SP_USE(u_child)->child; - tr_mat = SP_ITEM(u_child)->getRelativeTransform(SP_OBJECT_PARENT(child)); + tr_mat = SP_ITEM(u_child)->getRelativeTransform(child->parent); } else { tr_mat = SP_ITEM(u_child)->transform; } @@ -524,7 +524,7 @@ static void GetDest(SPObject* child,Shape **computed) temp->Convert(0.25); temp->Fill(n_shp,0); Shape* uncross=new Shape; - SPStyle* style=SP_OBJECT_STYLE(u_child); + SPStyle* style = u_child->style; if ( style && style->fill_rule.computed == SP_WIND_RULE_EVENODD ) { uncross->ConvertToShape(n_shp,fill_oddEven); } else { diff --git a/src/sp-object.h b/src/sp-object.h index 094ad5bb0..5d9ac88ff 100644 --- a/src/sp-object.h +++ b/src/sp-object.h @@ -56,7 +56,6 @@ class SPObjectClass; /* Convenience stuff */ #define SP_OBJECT_REPR(o) (((SPObject *) (o))->getRepr()) -#define SP_OBJECT_PARENT(o) (((SPObject *) (o))->parent) #define SP_OBJECT_STYLE(o) (((SPObject *) (o))->style) #include diff --git a/src/sp-style-elem.cpp b/src/sp-style-elem.cpp index 02ed80445..2e14ae5ff 100644 --- a/src/sp-style-elem.cpp +++ b/src/sp-style-elem.cpp @@ -366,7 +366,7 @@ sp_style_elem_read_content(SPObject *const object) // Below is a partial hack that fixes this for a single case: when the