path-manipulator.cpp revision 5049dd33573bc5b0bf07823e92db5cc44b3938bf
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Path manipulator - implementation.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Krzysztof KosiĆski <tweenk.pl@gmail.com>
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Abhishek Sharma
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Copyright (C) 2009 Authors
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Released under GNU GPL, read the file 'COPYING' for more information
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major/// Types of path changes that we must react to.
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major} // anonymous namespace
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * Notifies the path manipulator when something changes the path being edited
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major * (e.g. undo / redo)
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Majorclass PathManipulatorObserver : public Inkscape::XML::NodeObserver {
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major PathManipulatorObserver(PathManipulator *p, Inkscape::XML::Node *node)
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major virtual void notifyAttributeChanged(Inkscape::XML::Node &/*node*/, GQuark attr,
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major // do nothing if blocked
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major GQuark path_d = g_quark_from_static_string("d");
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major GQuark path_transform = g_quark_from_static_string("transform");
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major GQuark lpe_quark = _pm->_lpe_key.empty() ? 0 : g_quark_from_string(_pm->_lpe_key.data());
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Major // only react to "d" (path data) and "transform" attribute changes
fb379c70e3fd8a537f311b99be4759ae41e02750Peter Majorvoid build_segment(Geom::PathBuilder &, Node *, Node *);
//spanish: una propiedad isBSpline, por defecto falsa y una funciĂłn al final de la funciĂłn (BSpline()) que la define realmente
, isBSpline(false)
, _subpaths(*this)
, /* XML Tree being used here directly while it shouldn't be*/_observer(new PathManipulatorObserver(this, path->getRepr()))
, _num_selected(0)
, _show_handles(true)
, _show_outline(false)
, _show_path_direction(false)
, _live_outline(true)
, _live_objects(true)
_getGeometry();
BSpline();
delete _dragpoint;
delete _observer;
clear();
if (empty()) return false;
case GDK_MOTION_NOTIFY:
* \param alert_LPE if true, alerts an applied LPE to what the path is going to be changed to, so it can adjust its parameters for nicer user interfacing
if (!_live_outline)
if (!_live_objects)
_setGeometry();
if (!_path) return;
if (!empty()) {
if (j->selected()) {
if (j->selected()) {
if ( !Geom::are_near(t - std::floor(t+0.5),0.) ) // std::floor(t+0.5) is another way of writing round(t)
if (_num_selected == 0) return;
if (j->selected()) {
n->sink();
(*i)->insert(k, n);
_selectionChanged(n, false);
else ++num_unselected;
if (num_unselected == 0) {
while (num_selected > 0) {
unsigned num_points = 0;
bool use_pos = false;
++num_points;
if (use_pos) {
pos_valid = false;
--num_selected;
else ++num_unselected;
while (num_selected > 0) {
unsigned num_points = 0;
++num_points;
++cur;
--end;
bool becomes_open = false;
becomes_open = true;
n->sink();
if (becomes_open) {
if (_num_selected == 0) return;
else ++num_unselected;
if (num_selected == 0) {
while (num_selected > 0) {
unsigned PathManipulator::_deleteStretch(NodeList::iterator start, NodeList::iterator end, bool keep_shape)
unsigned del_len = 0;
++del_len;
if (del_len == 0) return 0;
unsigned seg = 0;
for (unsigned s = 0; s < samples_per_segment; ++s) {
++seg;
delete[] bezier_data;
if(isBSpline){
if(end){
return del_len;
if (_num_selected == 0) return;
bool has_unselected = false;
unsigned num_selected = 0;
if (j->selected()) {
++num_selected;
has_unselected = true;
if (!has_unselected) {
while (num_selected > 0) {
unsigned num_points = 0;
++num_points;
if (selected_only) {
if (j->selected()) {
(*i)->reverse();
(*i)->reverse();
if (_num_selected == 0) return;
switch (type) {
case SEGMENT_STRAIGHT:
case SEGMENT_CUBIC_BEZIER:
double length_change;
if (pixel) {
if (h->isDegenerate()) {
if (dir < 0) return;
if (!nh) return;
update();
if (h->isDegenerate()) return;
double angle;
if (pixel) {
update();
if (which < 0) {
return n->front();
return n->back();
if (show) {
if (!j->selected()) continue;
j->showHandles(true);
j->showHandles(false);
j->updateHandles();
++insert_at;
return inserted;
if(j->selected()) {
if (!search_selected) continue;
if (!search_unselected) continue;
if (cond) {
match = j;
return match;
switch (type) {
case PATH_CHANGE_D: {
_getGeometry();
++curpos;
case PATH_CHANGE_TRANSFORM: {
clear();
if (i->empty()) {
if (i->empty()) continue;
if ((*i)->closed()) {
Inkscape::LivePathEffect::Effect* thisEffect = SP_LPE_ITEM(_path)->getPathEffectOfType(Inkscape::LivePathEffect::BSPLINE);
if(thisEffect){
int steps = 0;
if(lpe_bsp){
return steps;
isBSpline = false;
if(this->BSplineGetSteps()>0){
isBSpline = true;
using Geom::X;
using Geom::Y;
return pos;
using Geom::X;
using Geom::Y;
return ret;
if(prevNode){
if(nextNode){
* \param alert_LPE if true, first the LPE is warned what the new path is going to be before updating it
BSpline();
prev = i;
++spi;
if (alert_LPE) {
/// \todo note that _path can be an Inkscape::LivePathEffect::Effect* too, kind of confusing, rework member naming?
LivePathEffect::LPEPowerStroke *lpe_pwr = dynamic_cast<LivePathEffect::LPEPowerStroke*>( effect_list.front()->lpeobject->get_lpe() );
if (lpe_pwr) {
if (_live_outline)
if (_live_objects)
_setGeometry();
if (!_show_outline) {
if (_show_path_direction) {
if (lpe) {
if (empty()) return;
// copied from nodepath.cpp
if (lpe) {
if (!empty()) {
update(true);
if (!n->isEndNode()) {
update();
update();
else --_num_selected;
if (!_show_handles) return;
if (!node) return;
if (selected) {
writeXML();
writeXML();
if (!pvp) return;
double fracpart;
return ret;