Code

patch 1705533
[inkscape.git] / src / nodepath.cpp
index ec3066cfc2ff9c22e40a55b8dc49293f24db7b42..0ad4c66a030c190776b9c53cc158dd6c1ea7ae5e 100644 (file)
@@ -99,6 +99,8 @@ static void sp_nodepath_node_select(Inkscape::NodePath::Node *node, gboolean inc
 
 static void sp_node_set_selected(Inkscape::NodePath::Node *node, gboolean selected);
 
+static Inkscape::NodePath::Node *sp_nodepath_set_node_type(Inkscape::NodePath::Node *node, Inkscape::NodePath::NodeType type);
+
 /* Adjust handle placement, if the node or the other handle is moved */
 static void sp_node_adjust_handle(Inkscape::NodePath::Node *node, gint which_adjust);
 static void sp_node_adjust_handles(Inkscape::NodePath::Node *node);
@@ -134,7 +136,7 @@ static Inkscape::NodePath::NodeSide *sp_node_opposite_side(Inkscape::NodePath::N
 static NRPathcode sp_node_path_code_from_side(Inkscape::NodePath::Node *node,Inkscape::NodePath::NodeSide *me);
 
 // active_node indicates mouseover node
-static Inkscape::NodePath::Node *active_node = NULL;
+Inkscape::NodePath::Node * Inkscape::NodePath::Path::active_node = NULL;
 
 /**
  * \brief Creates new nodepath from item
@@ -698,7 +700,7 @@ static void sp_nodepath_line_midpoint(Inkscape::NodePath::Node *new_path,Inkscap
     if (end->code == NR_LINETO) {
         new_path->type =Inkscape::NodePath::NODE_CUSP;
         new_path->code = NR_LINETO;
-        new_path->pos  = (t * start->pos + (1 - t) * end->pos);
+        new_path->pos = new_path->n.pos = new_path->p.pos = (t * start->pos + (1 - t) * end->pos);
     } else {
         new_path->type =Inkscape::NodePath::NODE_SMOOTH;
         new_path->code = NR_CURVETO;
@@ -737,13 +739,16 @@ static Inkscape::NodePath::Node *sp_nodepath_line_add_node(Inkscape::NodePath::N
     g_assert( start->n.other == end );
    Inkscape::NodePath::Node *newnode = sp_nodepath_node_new(end->subpath,
                                                end,
-                                              Inkscape::NodePath::NODE_SMOOTH,
+                                               (NRPathcode)end->code == NR_LINETO? 
+                                                  Inkscape::NodePath::NODE_CUSP : Inkscape::NodePath::NODE_SMOOTH,
                                                (NRPathcode)end->code,
                                                &start->pos, &start->pos, &start->n.pos);
     sp_nodepath_line_midpoint(newnode, end, t);
 
+    sp_node_adjust_handles(start);
     sp_node_update_handles(start);
     sp_node_update_handles(newnode);
+    sp_node_adjust_handles(end);
     sp_node_update_handles(end);
 
     return newnode;
@@ -839,12 +844,14 @@ static void sp_nodepath_set_line_type(Inkscape::NodePath::Node *end, NRPathcode
     end->code = code;
 
     if (code == NR_LINETO) {
-        if (start->code == NR_LINETO) start->type =Inkscape::NodePath::NODE_CUSP;
+        if (start->code == NR_LINETO) {
+            sp_nodepath_set_node_type (start, Inkscape::NodePath::NODE_CUSP);
+        }
         if (end->n.other) {
-            if (end->n.other->code == NR_LINETO) end->type =Inkscape::NodePath::NODE_CUSP;
+            if (end->n.other->code == NR_LINETO) {
+                sp_nodepath_set_node_type (end, Inkscape::NodePath::NODE_CUSP);
+            }
         }
-        sp_node_adjust_handle(start, -1);
-        sp_node_adjust_handle(end, 1);
     } else {
         NR::Point delta = end->pos - start->pos;
         start->n.pos = start->pos + delta / 3;
@@ -919,26 +926,18 @@ void sp_nodepath_convert_node_type(Inkscape::NodePath::Node *node, Inkscape::Nod
             // BEFORE:
             {
             node->code = NR_CURVETO;
-            NR::Point delta;
-            if (node->n.other != NULL)
-                delta = node->n.other->pos - node->p.other->pos;
-            else
-                delta = node->pos - node->p.other->pos;
+            NR::Point delta = node->n.other->pos - node->p.other->pos;
             node->p.pos = node->pos - delta / 4;
-            sp_node_update_handles(node);
             }
 
             // AFTER:
             {
             node->n.other->code = NR_CURVETO;
-            NR::Point delta;
-            if (node->p.other != NULL)
-                delta = node->p.other->pos - node->n.other->pos;
-            else
-                delta = node->pos - node->n.other->pos;
+            NR::Point delta = node->p.other->pos - node->n.other->pos;
             node->n.pos = node->pos - delta / 4;
-            sp_node_update_handles(node);
             }
+
+            sp_node_update_handles(node);
         }
     }
 
@@ -1000,7 +999,7 @@ static void sp_nodepath_selected_nodes_move(Inkscape::NodePath::Path *nodepath,
         
         for (GList *l = nodepath->selected; l != NULL; l = l->next) {
             Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) l->data;
-            Inkscape::SnappedPoint const s = m.freeSnap(Inkscape::Snapper::SNAP_POINT, n->pos + delta, NULL);
+            Inkscape::SnappedPoint const s = m.freeSnap(Inkscape::Snapper::SNAP_POINT, n->pos + delta, n->subpath->nodepath->path);
             if (s.getDistance() < best) {
                 best = s.getDistance();
                 best_pt = s.getPoint() - n->pos;
@@ -2898,10 +2897,10 @@ static gboolean node_event(SPKnot *knot, GdkEvent *event, Inkscape::NodePath::No
     gboolean ret = FALSE;
     switch (event->type) {
         case GDK_ENTER_NOTIFY:
-            active_node = n;
+            Inkscape::NodePath::Path::active_node = n;
             break;
         case GDK_LEAVE_NOTIFY:
-            active_node = NULL;
+            Inkscape::NodePath::Path::active_node = NULL;
             break;
         case GDK_SCROLL:
             if ((event->scroll.state & GDK_CONTROL_MASK) && !(event->scroll.state & GDK_SHIFT_MASK)) { // linearly
@@ -2972,33 +2971,33 @@ gboolean node_key(GdkEvent *event)
     Inkscape::NodePath::Path *np;
 
     // there is no way to verify nodes so set active_node to nil when deleting!!
-    if (active_node == NULL) return FALSE;
+    if (Inkscape::NodePath::Path::active_node == NULL) return FALSE;
 
     if ((event->type == GDK_KEY_PRESS) && !(event->key.state & (GDK_SHIFT_MASK | GDK_CONTROL_MASK))) {
         gint ret = FALSE;
         switch (get_group0_keyval (&event->key)) {
             /// \todo FIXME: this does not seem to work, the keys are stolen by tool contexts!
             case GDK_BackSpace:
-                np = active_node->subpath->nodepath;
-                sp_nodepath_node_destroy(active_node);
+                np = Inkscape::NodePath::Path::active_node->subpath->nodepath;
+                sp_nodepath_node_destroy(Inkscape::NodePath::Path::active_node);
                 sp_nodepath_update_repr(np, _("Delete node"));
-                active_node = NULL;
+                Inkscape::NodePath::Path::active_node = NULL;
                 ret = TRUE;
                 break;
             case GDK_c:
-                sp_nodepath_set_node_type(active_node,Inkscape::NodePath::NODE_CUSP);
+                sp_nodepath_set_node_type(Inkscape::NodePath::Path::active_node,Inkscape::NodePath::NODE_CUSP);
                 ret = TRUE;
                 break;
             case GDK_s:
-                sp_nodepath_set_node_type(active_node,Inkscape::NodePath::NODE_SMOOTH);
+                sp_nodepath_set_node_type(Inkscape::NodePath::Path::active_node,Inkscape::NodePath::NODE_SMOOTH);
                 ret = TRUE;
                 break;
             case GDK_y:
-                sp_nodepath_set_node_type(active_node,Inkscape::NodePath::NODE_SYMM);
+                sp_nodepath_set_node_type(Inkscape::NodePath::Path::active_node,Inkscape::NodePath::NODE_SYMM);
                 ret = TRUE;
                 break;
             case GDK_b:
-                sp_nodepath_node_break(active_node);
+                sp_nodepath_node_break(Inkscape::NodePath::Path::active_node);
                 ret = TRUE;
                 break;
         }
@@ -3453,12 +3452,14 @@ static void node_handle_moved(SPKnot *knot, NR::Point *p, guint state, gpointer
     }
 
     if (( n->type !=Inkscape::NodePath::NODE_CUSP || (state & GDK_SHIFT_MASK))
-        && rme.a != HUGE_VAL && rnew.a != HUGE_VAL && fabs(rme.a - rnew.a) > 0.001) {
+        && rme.a != HUGE_VAL && rnew.a != HUGE_VAL && (fabs(rme.a - rnew.a) > 0.001 || n->type ==Inkscape::NodePath::NODE_SYMM)) {
         // rotate the other handle correspondingly, if both old and new angles exist and are not the same
         rother.a += rnew.a - rme.a;
         other->pos = NR::Point(rother) + n->pos;
-        sp_ctrlline_set_coords(SP_CTRLLINE(other->line), n->pos, other->pos);
-        sp_knot_set_position(other->knot, &other->pos, 0);
+        if (other->knot) {
+            sp_ctrlline_set_coords(SP_CTRLLINE(other->line), n->pos, other->pos);
+            sp_knot_moveto(other->knot, &other->pos);
+        }
     }
 
     me->pos = NR::Point(rnew) + n->pos;
@@ -3512,6 +3513,16 @@ static gboolean node_handle_event(SPKnot *knot, GdkEvent *event,Inkscape::NodePa
                     break;
             }
             break;
+        case GDK_ENTER_NOTIFY:
+            // we use an experimentally determined threshold that seems to work fine
+            if (NR::L2(n->pos - knot->pos) < 0.75)
+                Inkscape::NodePath::Path::active_node = n;
+            break;
+        case GDK_LEAVE_NOTIFY:
+            // we use an experimentally determined threshold that seems to work fine
+            if (NR::L2(n->pos - knot->pos) < 0.75)
+                Inkscape::NodePath::Path::active_node = NULL;
+            break;
         default:
             break;
     }
@@ -3802,11 +3813,11 @@ void sp_nodepath_selected_nodes_scale_screen(Inkscape::NodePath::Path *nodepath,
 /**
  * Flip selected nodes horizontally/vertically.
  */
-void sp_nodepath_flip (Inkscape::NodePath::Path *nodepath, NR::Dim2 axis)
+void sp_nodepath_flip (Inkscape::NodePath::Path *nodepath, NR::Dim2 axis, NR::Maybe<NR::Point> center)
 {
     if (!nodepath || !nodepath->selected) return;
 
-    if (g_list_length(nodepath->selected) == 1) {
+    if (g_list_length(nodepath->selected) == 1 && !center) {
         // flip handles of the single selected node
         Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) nodepath->selected->data;
         double temp = n->p.pos[axis];
@@ -3823,10 +3834,13 @@ void sp_nodepath_flip (Inkscape::NodePath::Path *nodepath, NR::Dim2 axis)
             box.expandTo (n->pos); // contain all selected nodes
         }
 
+        if (!center) {
+            center = box.midpoint();
+        }
         NR::Matrix t =
-            NR::Matrix (NR::translate(-box.midpoint())) *
+            NR::Matrix (NR::translate(- *center)) *
             NR::Matrix ((axis == NR::X)? NR::scale(-1, 1) : NR::scale(1, -1)) *
-            NR::Matrix (NR::translate(box.midpoint()));
+            NR::Matrix (NR::translate(*center));
 
         for (GList *l = nodepath->selected; l != NULL; l = l->next) {
             Inkscape::NodePath::Node *n = (Inkscape::NodePath::Node *) l->data;
@@ -4168,7 +4182,7 @@ static NRPathcode sp_node_path_code_from_side(Inkscape::NodePath::Node *node,Ink
 }
 
 /**
- * Call sp_nodepath_line_add_node() at t on the segment denoted by piece
+ * Return node with the given index
  */
 Inkscape::NodePath::Node *
 sp_nodepath_get_node_by_index(int index)