作図ソフト dia の改良版
Revisão | 7546391a16212dfadc514f353712e04618df4928 (tree) |
---|---|
Hora | 2014-09-14 21:12:29 |
Autor | Hans Breuer <hans@breu...> |
Commiter | Hans Breuer |
path: handle special cases of combinations w/o crossing
@@ -238,15 +238,18 @@ _combine_to_path_callback (GtkAction *action, gpointer data) | ||
238 | 238 | (change->apply)(change, dia); |
239 | 239 | /* add the new object with undo */ |
240 | 240 | undo_insert_objects(dia, g_list_prepend(NULL, obj), 1); |
241 | - undo_set_transactionpoint(ddisp->diagram->undo); | |
242 | - | |
243 | 241 | diagram_add_object (dia, obj); |
244 | 242 | diagram_select(dia, obj); |
243 | + undo_set_transactionpoint(ddisp->diagram->undo); | |
245 | 244 | object_add_updates(obj, dia); |
246 | - | |
247 | - ddisplay_do_update_menu_sensitivity(ddisp); | |
248 | - diagram_flush(dia); | |
245 | + } else { | |
246 | + /* path combination result is empty, this is just a delete */ | |
247 | + Change *change = undo_delete_objects_children(ddisp->diagram, cut_list); | |
248 | + (change->apply)(change, ddisp->diagram); | |
249 | + undo_set_transactionpoint(ddisp->diagram->undo); | |
249 | 250 | } |
251 | + ddisplay_do_update_menu_sensitivity(ddisp); | |
252 | + diagram_flush(dia); | |
250 | 253 | g_list_free (cut_list); |
251 | 254 | } |
252 | 255 | static void |
@@ -874,12 +874,11 @@ create_standard_path_from_list (GList *objects, | ||
874 | 874 | } |
875 | 875 | if (p1 && p2) { |
876 | 876 | GArray *combined = path_combine (p1, p2, mode); |
877 | - if (combined) { | |
878 | - g_array_free (p1, TRUE); | |
879 | - p1 = combined; | |
880 | - g_array_free (p2, TRUE); | |
881 | - p2 = NULL; | |
882 | - } | |
877 | + /* combined == NULL is just passed on */ | |
878 | + g_array_free (p1, TRUE); | |
879 | + p1 = combined; | |
880 | + g_array_free (p2, TRUE); | |
881 | + p2 = NULL; | |
883 | 882 | } else { |
884 | 883 | p1 = p2; |
885 | 884 | p2 = NULL; |
@@ -302,6 +302,13 @@ struct _Split { | ||
302 | 302 | GArray *path; /*!< subpath copy */ |
303 | 303 | }; |
304 | 304 | |
305 | +/*! | |
306 | + * \brief Extract splits from crossing | |
307 | + * | |
308 | + * Crossing is the array of Intersection which contains split information | |
309 | + * from crossing between two paths. This function separates the | |
310 | + * information into splits specific to a single path. | |
311 | + */ | |
305 | 312 | static GArray * |
306 | 313 | _extract_splits (const GArray *crossing, gboolean one) |
307 | 314 | { |
@@ -619,8 +626,8 @@ _make_path0 (GArray *one, /*!< array<BezierSegment> from first path */ | ||
619 | 626 | for (i = 0; i < segs->len; ++i) { |
620 | 627 | BezierSegment *seg = &g_array_index (segs, BezierSegment, i); |
621 | 628 | /* every split starts with a move-to */ |
622 | - if ( isp < splits->len | |
623 | - && 0 | |
629 | + if ( splits | |
630 | + && isp < splits->len | |
624 | 631 | && i == g_array_index (splits, Split, isp).seg |
625 | 632 | && g_array_index (result, BezPoint, result->len - 1).type != BEZ_MOVE_TO) { |
626 | 633 | bp.type = BEZ_MOVE_TO; |
@@ -727,6 +734,16 @@ _make_path (GArray *one, /*!< array<BezierSegment> from first path */ | ||
727 | 734 | return result; |
728 | 735 | } |
729 | 736 | |
737 | +static GArray * | |
738 | +_path_copy (const GArray *p) | |
739 | +{ | |
740 | + GArray *result = g_array_new (FALSE, FALSE, sizeof(BezPoint)); | |
741 | + | |
742 | + g_array_append_vals (result, &g_array_index (p, BezPoint, 0), p->len); | |
743 | + | |
744 | + return result; | |
745 | +} | |
746 | + | |
730 | 747 | /*! |
731 | 748 | * \brief Combine two path into a single one with the given operation |
732 | 749 | * |
@@ -780,6 +797,46 @@ path_combine (const GArray *p1, | ||
780 | 797 | _free_splits (one_splits); |
781 | 798 | _free_splits (two_splits); |
782 | 799 | g_array_free (crossing, TRUE); |
800 | + } else { | |
801 | + gboolean two_in_one = distance_bez_shape_point (&g_array_index (p1, BezPoint, 0), p1->len, | |
802 | + 0 /* line width */, &g_array_index (p2, BezPoint, 0).p1) == 0; | |
803 | + gboolean one_in_two = distance_bez_shape_point (&g_array_index (p2, BezPoint, 0), p2->len, | |
804 | + 0 /* line width */, &g_array_index (p1, BezPoint, 0).p1) == 0; | |
805 | + | |
806 | + switch (mode) { | |
807 | + case PATH_UNION: /* Union and Exclusion just join the pathes */ | |
808 | + if (two_in_one) | |
809 | + result = _path_copy (p1); | |
810 | + else if (one_in_two) /* the bigger one */ | |
811 | + result = _path_copy (p2); | |
812 | + else | |
813 | + result = _make_path0 (one, NULL, two, NULL); | |
814 | + break; | |
815 | + case PATH_DIFFERENCE: /* Difference does it too, if p2 is inside p1 */ | |
816 | + if (two_in_one) | |
817 | + result = _make_path0 (one, NULL, two, NULL); | |
818 | + else if (one_in_two) | |
819 | + result = NULL; | |
820 | + else | |
821 | + result = _path_copy (p1); | |
822 | + break; | |
823 | + case PATH_INTERSECTION: | |
824 | + if (two_in_one) | |
825 | + result = _path_copy (p2); | |
826 | + else if (one_in_two) | |
827 | + result = _path_copy (p1); | |
828 | + else | |
829 | + result = NULL; /* Intersection is just emtpy w/o crossing */ | |
830 | + break; | |
831 | + case PATH_EXCLUSION: | |
832 | + if (two_in_one)/* with two_in_one this is like difference */ | |
833 | + result = _make_path0 (one, NULL, two, NULL); | |
834 | + else if (one_in_two) | |
835 | + result = _make_path0 (two, NULL, one, NULL); | |
836 | + else /* join */ | |
837 | + result = _make_path0 (one, NULL, two, NULL); | |
838 | + break; | |
839 | + } | |
783 | 840 | } |
784 | 841 | g_array_free (one, TRUE); |
785 | 842 | g_array_free (two, TRUE); |