[dia] path: handle special cases of combinations w/o crossing



commit 7546391a16212dfadc514f353712e04618df4928
Author: Hans Breuer <hans breuer org>
Date:   Tue Sep 9 21:25:56 2014 +0200

    path: handle special cases of combinations w/o crossing
    
     - path_combine(): implement the respective !crossing branch
     - create_standard_path_from_list(): may return empty now
     - _combine_to_path_callback(): an empty result is like a delete
       Also fix transaction point position.

 app/disp_callbacks.c  |   13 ++++++----
 lib/diapathrenderer.c |   11 ++++-----
 lib/path-math.c       |   61 +++++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 72 insertions(+), 13 deletions(-)
---
diff --git a/app/disp_callbacks.c b/app/disp_callbacks.c
index 62f06dc..8255566 100644
--- a/app/disp_callbacks.c
+++ b/app/disp_callbacks.c
@@ -238,15 +238,18 @@ _combine_to_path_callback (GtkAction *action, gpointer data)
     (change->apply)(change, dia);
     /* add the new object with undo */
     undo_insert_objects(dia, g_list_prepend(NULL, obj), 1);
-    undo_set_transactionpoint(ddisp->diagram->undo);
-
     diagram_add_object (dia, obj);
     diagram_select(dia, obj);
+    undo_set_transactionpoint(ddisp->diagram->undo);
     object_add_updates(obj, dia);
-
-    ddisplay_do_update_menu_sensitivity(ddisp);
-    diagram_flush(dia);
+  } else {
+    /* path combination result is empty, this is just a delete */
+    Change *change = undo_delete_objects_children(ddisp->diagram, cut_list);
+    (change->apply)(change, ddisp->diagram);
+    undo_set_transactionpoint(ddisp->diagram->undo);
   }
+  ddisplay_do_update_menu_sensitivity(ddisp);
+  diagram_flush(dia);
   g_list_free (cut_list);
 }
 static void
diff --git a/lib/diapathrenderer.c b/lib/diapathrenderer.c
index ebc5e40..71616a1 100644
--- a/lib/diapathrenderer.c
+++ b/lib/diapathrenderer.c
@@ -874,12 +874,11 @@ create_standard_path_from_list (GList           *objects,
     }
     if (p1 && p2) {
       GArray *combined = path_combine (p1, p2, mode);
-      if (combined) {
-       g_array_free (p1, TRUE);
-       p1 = combined;
-       g_array_free (p2, TRUE);
-       p2 = NULL;
-      }
+      /* combined == NULL is just passed on */
+      g_array_free (p1, TRUE);
+      p1 = combined;
+      g_array_free (p2, TRUE);
+      p2 = NULL;
     } else {
       p1 = p2;
       p2 = NULL;
diff --git a/lib/path-math.c b/lib/path-math.c
index a9bef7f..df4b292 100644
--- a/lib/path-math.c
+++ b/lib/path-math.c
@@ -302,6 +302,13 @@ struct _Split {
   GArray  *path;    /*!< subpath copy */
 };
 
+/*!
+ * \brief Extract splits from crossing
+ *
+ * Crossing is the array of Intersection which contains split information
+ * from crossing between two paths. This function separates the
+ * information into splits specific to a single path.
+ */
 static GArray *
 _extract_splits (const GArray *crossing, gboolean one)
 {
@@ -619,8 +626,8 @@ _make_path0 (GArray *one, /*!< array<BezierSegment> from first path */
     for (i = 0; i < segs->len; ++i) {
       BezierSegment *seg = &g_array_index (segs, BezierSegment, i);
       /* every split starts with a move-to */
-      if (   isp < splits->len
-         && 0
+      if (   splits
+         && isp < splits->len
          && i == g_array_index (splits, Split, isp).seg
          && g_array_index (result, BezPoint, result->len - 1).type != BEZ_MOVE_TO) {
        bp.type = BEZ_MOVE_TO;
@@ -727,6 +734,16 @@ _make_path (GArray *one, /*!< array<BezierSegment> from first path */
   return result;
 }
 
+static GArray *
+_path_copy (const GArray *p)
+{
+  GArray *result = g_array_new (FALSE, FALSE, sizeof(BezPoint));
+
+  g_array_append_vals (result,  &g_array_index (p, BezPoint, 0), p->len);
+
+  return result;
+}
+
 /*!
  * \brief Combine two path into a single one with the given operation
  *
@@ -780,6 +797,46 @@ path_combine (const GArray   *p1,
     _free_splits (one_splits);
     _free_splits (two_splits);
     g_array_free (crossing, TRUE);
+  } else {
+    gboolean two_in_one = distance_bez_shape_point (&g_array_index (p1, BezPoint, 0), p1->len,
+                                   0 /* line width */, &g_array_index (p2, BezPoint, 0).p1) == 0;
+    gboolean one_in_two = distance_bez_shape_point (&g_array_index (p2, BezPoint, 0), p2->len,
+                                   0 /* line width */, &g_array_index (p1, BezPoint, 0).p1) == 0;
+
+    switch (mode) {
+    case PATH_UNION: /* Union and Exclusion just join the pathes */
+      if (two_in_one)
+       result = _path_copy (p1);
+      else if (one_in_two) /* the bigger one */
+       result = _path_copy (p2);
+      else
+       result = _make_path0 (one, NULL, two, NULL);
+      break;
+    case PATH_DIFFERENCE: /* Difference does it too, if p2 is inside p1 */
+      if (two_in_one)
+       result = _make_path0 (one, NULL, two, NULL);
+      else if (one_in_two)
+       result = NULL;
+      else
+       result = _path_copy (p1);
+      break;
+    case PATH_INTERSECTION:
+      if (two_in_one)
+       result = _path_copy (p2);
+      else if (one_in_two)
+       result = _path_copy (p1);
+      else
+       result = NULL; /* Intersection is just emtpy w/o crossing */
+      break;
+    case PATH_EXCLUSION:
+      if (two_in_one)/* with two_in_one this is like difference */
+       result = _make_path0 (one, NULL, two, NULL);
+      else if (one_in_two)
+       result = _make_path0 (two, NULL, one, NULL);
+      else /* join */
+       result = _make_path0 (one, NULL, two, NULL);
+      break;
+    }
   }
   g_array_free (one, TRUE);
   g_array_free (two, TRUE);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]