[cairo] [Bug] Current Point and Curve_to

Nis Martensen nis.martensen at web.de
Tue Jun 16 23:51:12 PDT 2009


Hi,

When a new subpath is started with
    cairo_new_sub_path(); cairo_curve_to();
then a call to
    cairo_close_path();
will move the current point to the previous position of
the current point, and not the position where the path
is closed to.

The attached patches contain the fix and a test. Please
review and commit if you find they are correct.

Regards,
 Nis
-------------- next part --------------
From bbb5d1ccf276ff180e1c1da8871c0c34f6687952 Mon Sep 17 00:00:00 2001
From: Nis Martensen <nis.martensen at web.de>
Date: Tue, 16 Jun 2009 23:27:20 +0200
Subject: [PATCH] [path-fixed] fix missing implicit _move_to

When cairo_curve_to happens to start a new subpath (e.g., after a call
to cairo_new_sub_path()), it also needs to update the last_move_point.
Otherwise the new current point after a close_path() will be at an
unexpected position.

Therefore, call _cairo_path_fixed_move_to explicitly.
---
 src/cairo-path-fixed.c |    6 +++---
 1 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/src/cairo-path-fixed.c b/src/cairo-path-fixed.c
index 53d6cd4..f95c64a 100644
--- a/src/cairo-path-fixed.c
+++ b/src/cairo-path-fixed.c
@@ -414,7 +414,7 @@ _cairo_path_fixed_line_to (cairo_path_fixed_t *path,
 
     /* When there is not yet a current point, the line_to operation
      * becomes a move_to instead. Note: We have to do this by
-     * explicitly calling into _cairo_path_fixed_line_to to ensure
+     * explicitly calling into _cairo_path_fixed_move_to to ensure
      * that the last_move_point state is updated properly.
      */
     if (! path->has_current_point)
@@ -460,9 +460,9 @@ _cairo_path_fixed_curve_to (cairo_path_fixed_t	*path,
     point[1].x = x1; point[1].y = y1;
     point[2].x = x2; point[2].y = y2;
 
+    /* make sure subpaths are started properly */
     if (! path->has_current_point) {
-	status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO,
-					&point[0], 1);
+	status = _cairo_path_fixed_move_to (path, point[0].x, point[0].y);
 	if (unlikely (status))
 	    return status;
     }
-- 
1.5.6.5
-------------- next part --------------
From 056cda6118824a78d08ac1d08e7d915711757b9e Mon Sep 17 00:00:00 2001
From: Nis Martensen <nis.martensen at web.de>
Date: Tue, 16 Jun 2009 23:38:50 +0200
Subject: [PATCH] [test] Verify current point position after subpath closure

Make sure cairo_close_path always takes the current point where it
should be.
---
 test/Makefile.am                      |    1 +
 test/Makefile.sources                 |    1 +
 test/close-path-current-point.c       |   98 +++++++++++++++++++++++++++++++++
 test/close-path-current-point.ref.png |  Bin 0 -> 1916 bytes
 4 files changed, 100 insertions(+), 0 deletions(-)
 create mode 100644 test/close-path-current-point.c
 create mode 100644 test/close-path-current-point.ref.png

diff --git a/test/Makefile.am b/test/Makefile.am
index f6cb2f2..23146e4 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -202,6 +202,7 @@ REFERENCE_IMAGES = \
 	close-path.ps2.ref.png \
 	close-path.ps3.ref.png \
 	close-path.ref.png \
+	close-path-current-point.ref.png \
 	composite-integer-translate-over.ps2.ref.png \
 	composite-integer-translate-over.ps3.ref.png \
 	composite-integer-translate-over.ref.png \
diff --git a/test/Makefile.sources b/test/Makefile.sources
index 23596f8..4604b1f 100644
--- a/test/Makefile.sources
+++ b/test/Makefile.sources
@@ -24,6 +24,7 @@ test_sources = \
 	clipped-group.c					\
 	clipped-surface.c				\
 	close-path.c					\
+	close-path-current-point.c			\
 	composite-integer-translate-source.c		\
 	composite-integer-translate-over.c		\
 	composite-integer-translate-over-repeat.c	\
diff --git a/test/close-path-current-point.c b/test/close-path-current-point.c
new file mode 100644
index 0000000..2efa953
--- /dev/null
+++ b/test/close-path-current-point.c
@@ -0,0 +1,98 @@
+/*
+ * Copyright © 2009 Nis Martensen
+ *
+ * Permission to use, copy, modify, distribute, and sell this software
+ * and its documentation for any purpose is hereby granted without fee,
+ * provided that the above copyright notice appear in all copies and
+ * that both that copyright notice and this permission notice appear in
+ * supporting documentation, and that the name of the copyright holder
+ * not be used in advertising or publicity pertaining to distribution of
+ * the software without specific, written prior permission. The
+ * copyright holder makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without
+ * express or implied warranty.
+ *
+ * THE COPYRIGHT HOLDER DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
+ * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
+ * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
+ * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ * Author: Nis Martensen <nis.martensen at web.de>
+ */
+
+#include <stdlib.h>
+#include "cairo-test.h"
+
+#define SIZE 20
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+    cairo_path_t *path;
+
+    /* We draw in the default black, so paint white first. */
+    cairo_save (cr);
+    cairo_set_source_rgb (cr, 1.0, 1.0, 1.0); /* white */
+    cairo_paint (cr);
+    cairo_restore (cr);
+
+    /* subpath starts with cairo_move_to */
+    cairo_new_sub_path (cr);
+    cairo_move_to (cr, SIZE, SIZE);
+    cairo_rel_line_to (cr, SIZE, 0);
+    cairo_rel_line_to (cr, 0, SIZE);
+    cairo_close_path (cr);
+    cairo_rel_line_to (cr, 0.5 * SIZE, SIZE);
+
+    /* subpath starts with cairo_line_to */
+    cairo_new_sub_path (cr);
+    cairo_line_to (cr, SIZE, 3 * SIZE);
+    cairo_rel_line_to (cr, SIZE, 0);
+    cairo_rel_line_to (cr, 0, SIZE);
+    cairo_close_path (cr);
+    cairo_rel_line_to (cr, 0, SIZE);
+
+    /* subpath starts with cairo_curve_to */
+    cairo_new_sub_path (cr);
+    cairo_curve_to (cr,
+		    SIZE, 5 * SIZE,
+		    1.5 * SIZE, 6 * SIZE,
+		    2 * SIZE, 5 * SIZE);
+    cairo_rel_line_to (cr, 0, SIZE);
+    cairo_close_path (cr);
+    cairo_rel_line_to (cr, -0.5 * SIZE, SIZE);
+
+    /* subpath starts with cairo_arc */
+    cairo_new_sub_path (cr);
+    cairo_arc (cr,
+	       1.5 * SIZE, 7 * SIZE,
+	       0.5 * SIZE,
+	       M_PI, 2 * M_PI);
+    cairo_rel_line_to (cr, 0, SIZE);
+    cairo_close_path (cr);
+    cairo_rel_line_to (cr, -0.7 * SIZE, 0.7 * SIZE);
+
+    /* subpath starts with cairo_arc_negative */
+    cairo_new_sub_path (cr);
+    cairo_arc_negative (cr,
+	       1.5 * SIZE, 9 * SIZE,
+	       0.5 * SIZE,
+	       M_PI, 2 * M_PI);
+    cairo_rel_line_to (cr, 0, SIZE);
+    cairo_close_path (cr);
+    cairo_rel_line_to (cr, -0.8 * SIZE, 0.3 * SIZE);
+
+    cairo_stroke (cr);
+
+    return CAIRO_TEST_SUCCESS;
+}
+
+CAIRO_TEST (close_path_current_point,
+	    "Test some corner cases related to cairo path operations and the current point",
+	    "path", /* keywords */
+	    NULL, /* requirements */
+	    3 * SIZE, 11 * SIZE,
+	    NULL, draw)
diff --git a/test/close-path-current-point.ref.png b/test/close-path-current-point.ref.png
new file mode 100644
index 0000000000000000000000000000000000000000..f30002c6bb2859f2e74d687a49a776573a08dc74
GIT binary patch
literal 1916
zcmZWqc~sKr8veDYja at V+w_HohH8)ZzaUTTKYRa&56f061OL5F)P*bcKN6m#w$)M0O
z(J at OKHw-~7bH8e!xC<)diVnHt0%Dixp8Lm~`+ev8-uJwJyyrd7bDsA}KX(=ZQq)oe
z0088Pg!#y#qwJ0C+b#QFjQEzwf;`3>0Rz7LeV?&PasWWV#uMg-!arSl+Ut$FtlHEo
z!Ia6rUjV6|^f)89fBwGb6>D~}uc at U$WfpGavvFON%F!Q>$+@*BuU(6k7OGo<Quf{A
zW`5&#4c?$*&=PukSZaym!LQGBvu2%o>!+lz_Rca_$<5RfQGP-zCiC4zLE{@aYt2xz
zOj|WLMbYp~%7fzf$O~7CO07AlFzwK`$ZTCGc1zwOd@^4}w=Et1V(yjBn!xl{+)%BP
zwRIB#hr{I;6kIo(c)0VOssE{Rp}oERN=9{cwMm at hbQUo<lhzlyJVRnO=f<KT50Hmt
z3HD|SE-WkzhkLZ4<o|<e!j&t}XfzKFG&r>O;v&qz1_Cjj*KMdaiFKgLTIVe*U8a!K
zMq|*2A}or!GP*U(gs)R<11^VM><!SE2en}Hc?@LLJxtXIPs{U?`V;P_0VKuO+`eq)
zbzU?VQ>7TeD)P_5RDI at +cn+G`o39R>rMy<Fr_<>xm!^4h!iam-LWV#fs7W$svIqI9
z^NgP&qED`bj=5wDhHA4iKxamjN3p4<(f<e0kUgiEn6`_LP<1I=7wpDgbaz23Ui+2K
z at 83iM!2QKbsH~QfRz&$RI6l>?yPs8aAA3(W>j|}ptRiwXJ&1F<Cjc5+9Hq~O{!yIx
zfsr1wXxMplpqywz_N#C%yp72cr+KBv%p1Nm8Ym>DA$5}URr37!&V`U-A~Iv%5GVJ~
zk)9uy{xuG5i`+KekxC%WexLd7gE93C21=qvLgf>46;{7QJ5b?k{+*KuD0@;fG at nC+
zxD2Legv=S|DJbiG;@UwVC0g~BmAC$ES8?GaiS#5JqD#_1Uj5G^K^w85(ttPj+o>va
zeQZZXj)>nV;<2=;lwY<F?{+nKfTa02CW6ViYYj<KMnQa}HQh0?STahF0D(Ybt}{_v
z3taQA%GkvrHw)I}+V&Gj1Z<kgav|(6e-;G+b#bdkrP16Ms~aMIg^=1iOVo2x1ax(E
z2|L?INac1#ANhPMrn0U>^}B={Hx`=i>;Zn--duKn-ef|LcQR5P636dp%FwW?99|R-
zR#c$tTL-1&6W8l(N~2$c_wyPFgsBhdo%IVnRH#HE$!M8sd}Yhwg;>sRt<Jh{{MnHM
z!HsRMOn0@)$}wGm+3Ja~E%5&LB11Eh{{gJN%6Y8YkBP8AvfPn16=|-&>o{V~AG-^!
zZ*w2KKTVwGM)G%MBNmsIKrjEj`=0aE<|h7Ji27q^1B+r}otjKbGKt;IwN%d_pPuO?
znRf((zfFf3JO~C4kB?J3g739plGE>Q34F{*@(K!D@;<&{qk39eW+bmWMf+VH3VP|a
zwY!r;{Hau`43|!9mG{>(9JW5$oGL5ceo3pTu`B3JwUQzCghBxhKR_}QCA9-xM#jcl
z at c0WCatINZIgLruDLdzc^;bhqFFl^0n+RwQ4-YptH&0p-Kh)FF*_(`a+!3 at XlLs{v
zQ}B*T03A2JlA~e8Vlu-<YeW3?$_gKLba-}E7P9A7R=^H+LE>dW8}O0KrD@@pr#yi6
zVDMc3rev+J<ojI{9GdsbJ9$=@)hCf3Bl28UXKtP1HU(NL07;aBb}wl52`48IP&jMQ
z+mI*$CS;`5^#i|q<+(ha64%c46PkVZ{2FPiH64{Z7YF0^e|b*|VqJZ)4>H(hLMt=7
z;Y6G}QZny|L0c@%s2oeNr65o~Y>b}DAAaBEBVha<_a_LLw)bxeR!e<;GX}f76)=Gt
zKD)g6Z=;M4TvI~pFaI at Oe@8QFje^KUyoiGxizXvb9vN}4y_3C$Q`W0#)sLO0)US?i
z1h)T|y#Fb!#Xd(Vc;}!(ka+BE)blt)Jsm6-D;A3n*JYXbsupQzXdvKlpHkG;#_z2d
z8(&d at 3!zZhQmX%!!Ems*AL#2lm=42NB9C(V`V5)ALTWb_a-L%Ki{J6qD8EM}FB%*U
zSJ%)ubZvZm{G^D at W>3(}^W2WB3x&cbWU?t?ILG*V;2DdBj=A|*pSlmu7yxT(YX_jw
zuQOFsQ9%v2O+`*NHb-u#B(L at Nqqrdx?>>G!0DKTE&(DV*5~ZZbCFz*7Pe)F^Pw5Pq
za4SVQ#4M-+MLwm0ma|K&H*cDhgQ(7l at qHpaUYa3p8NWSTb-jjZY-FUQ@BFWuh%xs^
z*v#&po|X83M_eASCq+rmadW<}L|NZCGdnvrI{H)0*ua226xwAwjIttm(IfclLo=1(
z33$Ap&S<|orCGT>h!r2xoA2blvAwmroxI3+B}V2Q+;KEe(rp|>$uBhwqQ31zY|FM=
uJVyLC3ttuFF@#NsJA(P at O8+#gDZ+aCbzYn4GqB7~0Z)&!uyXe+cmD%7?ZnRj

literal 0
HcmV?d00001

-- 
1.5.6.5


More information about the cairo mailing list