[cairo-commit] 6 commits - src/cairo.c src/cairo-pdf-surface.c
src/cairo-svg-surface.c test/dash-scale.c
test/dash-scale-ps-argb32-ref.png test/dash-scale-ref.png
test/.gitignore test/line-width-scale.c
test/line-width-scale-ps-argb32-ref.png
test/line-width-scale-ref.png test/Makefile.am
Carl Worth
cworth at kemper.freedesktop.org
Tue May 23 12:19:27 PDT 2006
src/cairo-pdf-surface.c | 140 +++++++++++---------------------
src/cairo-svg-surface.c | 63 +++++++++-----
src/cairo.c | 35 +++++---
test/.gitignore | 1
test/Makefile.am | 2
test/dash-scale-ps-argb32-ref.png |binary
test/dash-scale-ref.png |binary
test/dash-scale.c | 125 ++++++++++++++++++++++++++++
test/line-width-scale-ps-argb32-ref.png |binary
test/line-width-scale-ref.png |binary
test/line-width-scale.c | 30 +++---
11 files changed, 261 insertions(+), 135 deletions(-)
New commits:
diff-tree 59885c6a122f593b417cb47dbd676eeac0cd8f69 (from 68b41cfd06dd6c798f8045ba1580342669ef5539)
Author: Carl Worth <cworth at cworth.org>
Date: Tue May 23 12:08:20 2006 -0700
Clarify the documentation for cairo_set_dash
Note that dash length units are evaluated in the user space
at the time of the stroke operation, (not the user space at
the time of cairo_set_dash).
diff --git a/src/cairo.c b/src/cairo.c
index cf87464..e9a0f33 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -897,9 +897,13 @@ cairo_set_line_join (cairo_t *cr, cairo_
*
* Sets the dash pattern to be used by cairo_stroke(). A dash pattern
* is specified by @dashes, an array of positive values. Each value
- * provides the user-space length of alternate "on" and "off" portions
- * of the stroke. The @offset specifies an offset into the pattern at
- * which the stroke begins.
+ * provides the length of alternate "on" and "off" portions of the
+ * stroke. The @offset specifies an offset into the pattern at which
+ * the stroke begins.
+ *
+ * Note: The length values are in user-space units as evaluated at the
+ * time of stroking. This is not necessarily the same as the user
+ * space at the time of cairo_set_dash().
*
* If @num_dashes is 0 dashing is disabled.
*
diff-tree 68b41cfd06dd6c798f8045ba1580342669ef5539 (from 7e5bef2439be93e46583c0922f68ad770179fa1e)
Author: Carl Worth <cworth at cworth.org>
Date: Tue May 23 11:23:27 2006 -0700
PDF: Share path callbacks for fill and stroke.
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index a3bc73d..0c063c6 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1324,63 +1324,6 @@ emit_pattern (cairo_pdf_surface_t *surfa
return CAIRO_STATUS_PATTERN_TYPE_MISMATCH;
}
-static cairo_status_t
-_cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
-{
- cairo_output_stream_t *output = closure;
-
- _cairo_output_stream_printf (output,
- "%f %f m ",
- _cairo_fixed_to_double (point->x),
- _cairo_fixed_to_double (point->y));
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
-{
- cairo_output_stream_t *output = closure;
-
- _cairo_output_stream_printf (output,
- "%f %f l ",
- _cairo_fixed_to_double (point->x),
- _cairo_fixed_to_double (point->y));
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_pdf_path_curve_to (void *closure,
- cairo_point_t *b,
- cairo_point_t *c,
- cairo_point_t *d)
-{
- cairo_output_stream_t *output = closure;
-
- _cairo_output_stream_printf (output,
- "%f %f %f %f %f %f c ",
- _cairo_fixed_to_double (b->x),
- _cairo_fixed_to_double (b->y),
- _cairo_fixed_to_double (c->x),
- _cairo_fixed_to_double (c->y),
- _cairo_fixed_to_double (d->x),
- _cairo_fixed_to_double (d->y));
-
- return CAIRO_STATUS_SUCCESS;
-}
-
-static cairo_status_t
-_cairo_pdf_path_close_path (void *closure)
-{
- cairo_output_stream_t *output = closure;
-
- _cairo_output_stream_printf (output,
- "h\r\n");
-
- return CAIRO_STATUS_SUCCESS;
-}
-
static cairo_int_status_t
_cairo_pdf_surface_copy_page (void *abstract_surface)
{
@@ -1429,13 +1372,14 @@ typedef struct _pdf_path_info {
} pdf_path_info_t;
static cairo_status_t
-_cairo_pdf_stroke_move_to (void *closure, cairo_point_t *point)
+_cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
{
pdf_path_info_t *info = closure;
double x = _cairo_fixed_to_double (point->x);
double y = _cairo_fixed_to_double (point->y);
- cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
+ if (info->ctm_inverse)
+ cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
_cairo_output_stream_printf (info->output,
"%f %f m ", x, y);
@@ -1444,13 +1388,14 @@ _cairo_pdf_stroke_move_to (void *closure
}
static cairo_status_t
-_cairo_pdf_stroke_line_to (void *closure, cairo_point_t *point)
+_cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
{
pdf_path_info_t *info = closure;
double x = _cairo_fixed_to_double (point->x);
double y = _cairo_fixed_to_double (point->y);
- cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
+ if (info->ctm_inverse)
+ cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
_cairo_output_stream_printf (info->output,
"%f %f l ", x, y);
@@ -1458,10 +1403,10 @@ _cairo_pdf_stroke_line_to (void *closure
}
static cairo_status_t
-_cairo_pdf_stroke_curve_to (void *closure,
- cairo_point_t *b,
- cairo_point_t *c,
- cairo_point_t *d)
+_cairo_pdf_path_curve_to (void *closure,
+ cairo_point_t *b,
+ cairo_point_t *c,
+ cairo_point_t *d)
{
pdf_path_info_t *info = closure;
double bx = _cairo_fixed_to_double (b->x);
@@ -1471,9 +1416,11 @@ _cairo_pdf_stroke_curve_to (void
double dx = _cairo_fixed_to_double (d->x);
double dy = _cairo_fixed_to_double (d->y);
- cairo_matrix_transform_point (info->ctm_inverse, &bx, &by);
- cairo_matrix_transform_point (info->ctm_inverse, &cx, &cy);
- cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy);
+ if (info->ctm_inverse) {
+ cairo_matrix_transform_point (info->ctm_inverse, &bx, &by);
+ cairo_matrix_transform_point (info->ctm_inverse, &cx, &cy);
+ cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy);
+ }
_cairo_output_stream_printf (info->output,
"%f %f %f %f %f %f c ",
@@ -1482,7 +1429,7 @@ _cairo_pdf_stroke_curve_to (void
}
static cairo_status_t
-_cairo_pdf_stroke_close_path (void *closure)
+_cairo_pdf_path_close_path (void *closure)
{
pdf_path_info_t *info = closure;
@@ -1502,6 +1449,7 @@ _cairo_pdf_surface_intersect_clip_path (
cairo_pdf_surface_t *surface = abstract_surface;
cairo_status_t status;
const char *pdf_operator;
+ pdf_path_info_t info;
if (path == NULL) {
if (surface->has_clip)
@@ -1515,13 +1463,16 @@ _cairo_pdf_surface_intersect_clip_path (
surface->has_clip = TRUE;
}
+ info.output = surface->output;
+ info.ctm_inverse = NULL;
+
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_pdf_path_move_to,
_cairo_pdf_path_line_to,
_cairo_pdf_path_curve_to,
_cairo_pdf_path_close_path,
- surface->output);
+ &info);
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
@@ -1672,6 +1623,7 @@ _cairo_pdf_surface_emit_glyph (cairo_pdf
{
cairo_scaled_glyph_t *scaled_glyph;
cairo_status_t status;
+ pdf_path_info_t info;
status = _cairo_scaled_glyph_lookup (scaled_font,
scaled_font_glyph_index,
@@ -1705,13 +1657,16 @@ _cairo_pdf_surface_emit_glyph (cairo_pdf
_cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
-_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
+ info.output = surface->output;
+ info.ctm_inverse = NULL;
+
status = _cairo_path_fixed_interpret (scaled_glyph->path,
CAIRO_DIRECTION_FORWARD,
_cairo_pdf_path_move_to,
_cairo_pdf_path_line_to,
_cairo_pdf_path_curve_to,
_cairo_pdf_path_close_path,
- surface->output);
+ &info);
_cairo_output_stream_printf (surface->output,
" f");
@@ -2238,12 +2193,13 @@ _cairo_pdf_surface_stroke (void *abstr
info.output = surface->output;
info.ctm_inverse = ctm_inverse;
+
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
- _cairo_pdf_stroke_move_to,
- _cairo_pdf_stroke_line_to,
- _cairo_pdf_stroke_curve_to,
- _cairo_pdf_stroke_close_path,
+ _cairo_pdf_path_move_to,
+ _cairo_pdf_path_line_to,
+ _cairo_pdf_path_curve_to,
+ _cairo_pdf_path_close_path,
&info);
_cairo_output_stream_printf (surface->output,
@@ -2273,6 +2229,7 @@ _cairo_pdf_surface_fill (void *abstrac
cairo_pdf_surface_t *surface = abstract_surface;
const char *pdf_operator;
cairo_status_t status;
+ pdf_path_info_t info;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
/* XXX: Does PDF provide a way we can preserve this hint? For now,
@@ -2289,13 +2246,16 @@ _cairo_pdf_surface_fill (void *abstrac
if (status)
return status;
+ info.output = surface->output;
+ info.ctm_inverse = NULL;
+
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_pdf_path_move_to,
_cairo_pdf_path_line_to,
_cairo_pdf_path_curve_to,
_cairo_pdf_path_close_path,
- surface->output);
+ &info);
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
diff-tree 7e5bef2439be93e46583c0922f68ad770179fa1e (from 1b1b59a4a9cdeab0f3c360c09721aff23154015f)
Author: Carl Worth <cworth at cworth.org>
Date: Tue May 23 11:17:01 2006 -0700
PDF: Rename pdf_stroke_t to pdf_path_into_t for future sharing with fill
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index ff7c342..a3bc73d 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1423,21 +1423,21 @@ _cairo_pdf_surface_get_extents (void
return CAIRO_STATUS_SUCCESS;
}
-typedef struct _pdf_stroke {
+typedef struct _pdf_path_info {
cairo_output_stream_t *output;
cairo_matrix_t *ctm_inverse;
-} pdf_stroke_t;
+} pdf_path_info_t;
static cairo_status_t
_cairo_pdf_stroke_move_to (void *closure, cairo_point_t *point)
{
- pdf_stroke_t *stroke = closure;
+ pdf_path_info_t *info = closure;
double x = _cairo_fixed_to_double (point->x);
double y = _cairo_fixed_to_double (point->y);
- cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y);
+ cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
- _cairo_output_stream_printf (stroke->output,
+ _cairo_output_stream_printf (info->output,
"%f %f m ", x, y);
return CAIRO_STATUS_SUCCESS;
@@ -1446,13 +1446,13 @@ _cairo_pdf_stroke_move_to (void *closure
static cairo_status_t
_cairo_pdf_stroke_line_to (void *closure, cairo_point_t *point)
{
- pdf_stroke_t *stroke = closure;
+ pdf_path_info_t *info = closure;
double x = _cairo_fixed_to_double (point->x);
double y = _cairo_fixed_to_double (point->y);
- cairo_matrix_transform_point (stroke->ctm_inverse, &x, &y);
+ cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
- _cairo_output_stream_printf (stroke->output,
+ _cairo_output_stream_printf (info->output,
"%f %f l ", x, y);
return CAIRO_STATUS_SUCCESS;
}
@@ -1463,7 +1463,7 @@ _cairo_pdf_stroke_curve_to (void
cairo_point_t *c,
cairo_point_t *d)
{
- pdf_stroke_t *stroke = closure;
+ pdf_path_info_t *info = closure;
double bx = _cairo_fixed_to_double (b->x);
double by = _cairo_fixed_to_double (b->y);
double cx = _cairo_fixed_to_double (c->x);
@@ -1471,11 +1471,11 @@ _cairo_pdf_stroke_curve_to (void
double dx = _cairo_fixed_to_double (d->x);
double dy = _cairo_fixed_to_double (d->y);
- cairo_matrix_transform_point (stroke->ctm_inverse, &bx, &by);
- cairo_matrix_transform_point (stroke->ctm_inverse, &cx, &cy);
- cairo_matrix_transform_point (stroke->ctm_inverse, &dx, &dy);
+ cairo_matrix_transform_point (info->ctm_inverse, &bx, &by);
+ cairo_matrix_transform_point (info->ctm_inverse, &cx, &cy);
+ cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy);
- _cairo_output_stream_printf (stroke->output,
+ _cairo_output_stream_printf (info->output,
"%f %f %f %f %f %f c ",
bx, by, cx, cy, dx, dy);
return CAIRO_STATUS_SUCCESS;
@@ -1484,9 +1484,9 @@ _cairo_pdf_stroke_curve_to (void
static cairo_status_t
_cairo_pdf_stroke_close_path (void *closure)
{
- pdf_stroke_t *stroke = closure;
+ pdf_path_info_t *info = closure;
- _cairo_output_stream_printf (stroke->output,
+ _cairo_output_stream_printf (info->output,
"h\r\n");
return CAIRO_STATUS_SUCCESS;
@@ -2218,7 +2218,7 @@ _cairo_pdf_surface_stroke (void *abstr
cairo_antialias_t antialias)
{
cairo_pdf_surface_t *surface = abstract_surface;
- pdf_stroke_t stroke;
+ pdf_path_info_t info;
cairo_status_t status;
if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
@@ -2236,15 +2236,15 @@ _cairo_pdf_surface_stroke (void *abstr
if (status)
return status;
- stroke.output = surface->output;
- stroke.ctm_inverse = ctm_inverse;
+ info.output = surface->output;
+ info.ctm_inverse = ctm_inverse;
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_pdf_stroke_move_to,
_cairo_pdf_stroke_line_to,
_cairo_pdf_stroke_curve_to,
_cairo_pdf_stroke_close_path,
- &stroke);
+ &info);
_cairo_output_stream_printf (surface->output,
"q %f %f %f %f %f %f cm\r\n",
diff-tree 1b1b59a4a9cdeab0f3c360c09721aff23154015f (from 0755a619a101b89f5c5439f12e0544ab5ecac997)
Author: Carl Worth <cworth at cworth.org>
Date: Tue May 23 11:12:09 2006 -0700
New test: dash-scale
Tests interactions of cairo_set_dash and cairo_scale, (in particular with a
non-uniformly scaled pen).
diff --git a/test/.gitignore b/test/.gitignore
index c0881dc..5588698 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -19,6 +19,7 @@ coverage
create-from-png
create-from-png-stream
dash-caps-joins
+dash-scale
dash-offset-negative
dash-zero-length
extend-reflect
diff --git a/test/Makefile.am b/test/Makefile.am
index b7b440a..fde3873 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -16,6 +16,7 @@ composite-integer-translate-over-repeat
create-from-png \
create-from-png-stream \
dash-caps-joins \
+dash-scale \
dash-offset-negative \
dash-zero-length \
extend-reflect \
@@ -151,6 +152,7 @@ create-from-png-ref.png \
create-from-png-stream-ref.png \
dash-caps-joins-ref.png \
dash-caps-joins-ps-argb32-ref.png \
+dash-scale-ref.png \
dash-offset-negative-ref.png \
dash-offset-negative-ps-argb32-ref.png \
dash-zero-length-ref.png \
diff --git a/test/dash-scale-ps-argb32-ref.png b/test/dash-scale-ps-argb32-ref.png
new file mode 100644
index 0000000..0320a8b
Binary files /dev/null and b/test/dash-scale-ps-argb32-ref.png differ
diff --git a/test/dash-scale-ref.png b/test/dash-scale-ref.png
new file mode 100644
index 0000000..cba93aa
Binary files /dev/null and b/test/dash-scale-ref.png differ
diff --git a/test/dash-scale.c b/test/dash-scale.c
new file mode 100644
index 0000000..3d8a2f7
--- /dev/null
+++ b/test/dash-scale.c
@@ -0,0 +1,125 @@
+/*
+ * Copyright © 2005 Red Hat, Inc.
+ *
+ * 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
+ * Red Hat, Inc. not be used in advertising or publicity pertaining to
+ * distribution of the software without specific, written prior
+ * permission. Red Hat, Inc. makes no representations about the
+ * suitability of this software for any purpose. It is provided "as
+ * is" without express or implied warranty.
+ *
+ * RED HAT, INC. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS
+ * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS, IN NO EVENT SHALL RED HAT, INC. 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: Carl D. Worth <cworth at cworth.org>
+ */
+
+#include "cairo-test.h"
+
+#define LINE_WIDTH 8.
+#define SIZE (5 * LINE_WIDTH)
+#define PAD (2 * LINE_WIDTH)
+
+cairo_test_t test = {
+ "dash-scale",
+ "Test interactions of cairo_set_dash and cairo_scale, (in particular with a non-uniformly scaled pen)",
+ 3 * (PAD + SIZE) + PAD,
+ PAD + 5 * SIZE + 2 * (2 * PAD) + PAD
+};
+
+static void
+make_path (cairo_t *cr)
+{
+ cairo_move_to (cr, 0., 0.);
+ cairo_rel_line_to (cr, 0., SIZE);
+ cairo_rel_line_to (cr, SIZE, 0.);
+ cairo_close_path (cr);
+
+ cairo_move_to (cr, 2 * LINE_WIDTH, 0.);
+ cairo_rel_line_to (cr, 3 * LINE_WIDTH, 0.);
+ cairo_rel_line_to (cr, 0., 3 * LINE_WIDTH);
+}
+
+static void
+draw_three_shapes (cairo_t *cr)
+{
+ cairo_save (cr);
+
+ make_path (cr);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_BUTT);
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_BEVEL);
+ cairo_stroke (cr);
+
+ cairo_translate (cr, SIZE + PAD, 0.);
+
+ make_path (cr);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_ROUND);
+ cairo_stroke (cr);
+
+ cairo_translate (cr, SIZE + PAD, 0.);
+
+ make_path (cr);
+ cairo_set_line_cap (cr, CAIRO_LINE_CAP_SQUARE);
+ cairo_set_line_join (cr, CAIRO_LINE_JOIN_MITER);
+ cairo_stroke (cr);
+
+ cairo_restore (cr);
+}
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ double dash[] = {1.5 * LINE_WIDTH};
+
+ /* 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);
+
+ cairo_translate (cr, PAD, PAD);
+
+ cairo_set_dash (cr, dash, sizeof(dash)/sizeof(dash[0]), - 2 * LINE_WIDTH);
+ cairo_set_line_width (cr, LINE_WIDTH);
+ draw_three_shapes (cr);
+
+ cairo_translate (cr, 0, SIZE + 2 * PAD);
+
+ cairo_save (cr);
+ {
+ cairo_set_dash (cr, dash, sizeof(dash)/sizeof(dash[0]), - 2 * LINE_WIDTH);
+ cairo_set_line_width (cr, LINE_WIDTH);
+ cairo_scale (cr, 1, 2);
+ draw_three_shapes (cr);
+ }
+ cairo_restore (cr);
+
+ cairo_translate (cr, 0, 2 * (SIZE + PAD));
+
+ cairo_save (cr);
+ {
+ cairo_scale (cr, 1, 2);
+ cairo_set_dash (cr, dash, sizeof(dash)/sizeof(dash[0]), - 2 * LINE_WIDTH);
+ cairo_set_line_width (cr, LINE_WIDTH);
+ draw_three_shapes (cr);
+ }
+ cairo_restore (cr);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test, draw);
+}
diff-tree 0755a619a101b89f5c5439f12e0544ab5ecac997 (from b1231e2ef349af1c0b130880603a924ff67b2967)
Author: Carl Worth <cworth at cworth.org>
Date: Tue May 23 10:54:54 2006 -0700
SVG: Fix for line-width-scale
Use the same approach as the PDF backend: emit the pen matrix as the
SVG transform for the stroke, and compensate by first transforming all path
coordinates by the ctm_inverse.
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 8a0fd97..94e0abc 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -463,6 +463,7 @@ typedef struct
{
cairo_svg_document_t *document;
xmlBufferPtr path;
+ cairo_matrix_t *ctm_inverse;
} svg_path_info_t;
static cairo_status_t
@@ -471,12 +472,17 @@ _cairo_svg_path_move_to (void *closure,
svg_path_info_t *info = closure;
xmlBufferPtr path = info->path;
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
+ double x = _cairo_fixed_to_double (point->x);
+ double y = _cairo_fixed_to_double (point->y);
+
+ if (info->ctm_inverse)
+ cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
xmlBufferCat (path, CC2XML ("M "));
- _cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (point->x));
+ _cairo_dtostr (buffer, sizeof buffer, x);
xmlBufferCat (path, CC2XML (buffer));
xmlBufferCat (path, CC2XML (" "));
- _cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (point->y));
+ _cairo_dtostr (buffer, sizeof buffer, y);
xmlBufferCat (path, CC2XML (buffer));
xmlBufferCat (path, CC2XML (" "));
@@ -489,13 +495,18 @@ _cairo_svg_path_line_to (void *closure,
svg_path_info_t *info = closure;
xmlBufferPtr path = info->path;
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
+ double x = _cairo_fixed_to_double (point->x);
+ double y = _cairo_fixed_to_double (point->y);
+
+ if (info->ctm_inverse)
+ cairo_matrix_transform_point (info->ctm_inverse, &x, &y);
xmlBufferCat (path, CC2XML ("L "));
- _cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (point->x));
+ _cairo_dtostr (buffer, sizeof buffer, x);
xmlBufferCat (path, CC2XML (buffer));
xmlBufferCat (path, CC2XML (" "));
- _cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (point->y));
+ _cairo_dtostr (buffer, sizeof buffer, y);
xmlBufferCat (path, CC2XML (buffer));
xmlBufferCat (path, CC2XML (" "));
@@ -511,24 +522,36 @@ _cairo_svg_path_curve_to (void
svg_path_info_t *info = closure;
xmlBufferPtr path = info->path;
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
+ double bx = _cairo_fixed_to_double (b->x);
+ double by = _cairo_fixed_to_double (b->y);
+ double cx = _cairo_fixed_to_double (c->x);
+ double cy = _cairo_fixed_to_double (c->y);
+ double dx = _cairo_fixed_to_double (d->x);
+ double dy = _cairo_fixed_to_double (d->y);
+
+ if (info->ctm_inverse) {
+ cairo_matrix_transform_point (info->ctm_inverse, &bx, &by);
+ cairo_matrix_transform_point (info->ctm_inverse, &cx, &cy);
+ cairo_matrix_transform_point (info->ctm_inverse, &dx, &dy);
+ }
xmlBufferCat (path, CC2XML ("C "));
- _cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (b->x));
+ _cairo_dtostr (buffer, sizeof buffer, bx);
xmlBufferCat (path, CC2XML (buffer));
xmlBufferCat (path, CC2XML (" "));
- _cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (b->y));
+ _cairo_dtostr (buffer, sizeof buffer, by);
xmlBufferCat (path, CC2XML (buffer));
xmlBufferCat (path, CC2XML (" "));
- _cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (c->x));
+ _cairo_dtostr (buffer, sizeof buffer, cx);
xmlBufferCat (path, CC2XML (buffer));
xmlBufferCat (path, CC2XML (" "));
- _cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (c->y));
+ _cairo_dtostr (buffer, sizeof buffer, cy);
xmlBufferCat (path, CC2XML (buffer));
xmlBufferCat (path, CC2XML (" "));
- _cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (d->x));
+ _cairo_dtostr (buffer, sizeof buffer, dx);
xmlBufferCat (path, CC2XML (buffer));
xmlBufferCat (path, CC2XML (" "));
- _cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (d->y));
+ _cairo_dtostr (buffer, sizeof buffer, dy);
xmlBufferCat (path, CC2XML (buffer));
xmlBufferCat (path, CC2XML (" "));
@@ -579,6 +602,7 @@ _cairo_svg_document_emit_glyph (cairo_sv
info.document = document;
info.path = xmlBufferCreate ();
+ info.ctm_inverse = NULL;
status = _cairo_path_fixed_interpret (scaled_glyph->path,
CAIRO_DIRECTION_FORWARD,
@@ -1324,6 +1348,7 @@ _cairo_svg_surface_fill (void *abstrac
info.document = document;
info.path = xmlBufferCreate ();
+ info.ctm_inverse = NULL;
style = xmlBufferCreate ();
emit_pattern (surface, source, style, 0);
@@ -1525,7 +1550,6 @@ _cairo_svg_surface_stroke (void *abstr
xmlBufferPtr style;
xmlNodePtr child;
svg_path_info_t info;
- double rx, ry;
unsigned int i;
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
@@ -1536,14 +1560,12 @@ _cairo_svg_surface_stroke (void *abstr
info.document = document;
info.path = xmlBufferCreate ();
-
- rx = ry = stroke_style->line_width;
- cairo_matrix_transform_distance (ctm, &rx, &ry);
+ info.ctm_inverse = ctm_inverse;
style = xmlBufferCreate ();
emit_pattern (surface, source, style, 1);
xmlBufferCat (style, CC2XML ("fill: none; stroke-width: "));
- _cairo_dtostr (buffer, sizeof buffer, sqrt ((rx * rx + ry * ry) / 2.0));
+ _cairo_dtostr (buffer, sizeof buffer, stroke_style->line_width);
xmlBufferCat (style, C2XML (buffer));
xmlBufferCat (style, CC2XML (";"));
@@ -1576,18 +1598,13 @@ _cairo_svg_surface_stroke (void *abstr
for (i = 0; i < stroke_style->num_dashes; i++) {
if (i != 0)
xmlBufferCat (style, CC2XML (","));
- /* FIXME: Is is really what we want ? */
- rx = ry = stroke_style->dash[i];
- cairo_matrix_transform_distance (ctm, &rx, &ry);
- _cairo_dtostr (buffer, sizeof buffer, sqrt ((rx * rx + ry * ry) / 2.0));
+ _cairo_dtostr (buffer, sizeof buffer, stroke_style->dash[i]);
xmlBufferCat (style, C2XML (buffer));
}
xmlBufferCat (style, CC2XML (";"));
if (stroke_style->dash_offset != 0.0) {
xmlBufferCat (style, CC2XML (" stroke-dashoffset: "));
- rx = ry = stroke_style->dash_offset;
- cairo_matrix_transform_distance (ctm, &rx, &ry);
- _cairo_dtostr (buffer, sizeof buffer, sqrt ((rx * rx + ry * ry) / 2.0));
+ _cairo_dtostr (buffer, sizeof buffer, stroke_style->dash_offset);
xmlBufferCat (style, C2XML (buffer));
xmlBufferCat (style, CC2XML (";"));
}
@@ -1607,6 +1624,7 @@ _cairo_svg_surface_stroke (void *abstr
&info);
child = xmlNewChild (surface->xml_node, NULL, CC2XML ("path"), NULL);
+ emit_transform (child, "transform", ctm);
xmlSetProp (child, CC2XML ("d"), xmlBufferContent (info.path));
xmlSetProp (child, CC2XML ("style"), xmlBufferContent (style));
emit_operator (child, surface, op);
@@ -1718,6 +1736,7 @@ _cairo_svg_surface_intersect_clip_path (
if (path != NULL) {
info.document = document;
info.path = xmlBufferCreate ();
+ info.ctm_inverse = NULL;
group = xmlNewChild (surface->xml_node, NULL, CC2XML ("g"), NULL);
clip = xmlNewChild (document->xml_node_defs, NULL, CC2XML ("clipPath"), NULL);
diff-tree b1231e2ef349af1c0b130880603a924ff67b2967 (from 0a1ec91977ef05f04e2cc52895fd98a903f1c8eb)
Author: Carl Worth <cworth at cworth.org>
Date: Tue May 23 10:45:18 2006 -0700
Codify 1.0 behavior of cairo_set_line_width as a feature, not a bug.
Clarify the documentation of cairo_set_line_width to indicate that the
value will be interpreted within the user space at the time of the
stroke.
Also adjust the comments in test/line-width-scale as well as the
reference images for that test to match.
diff --git a/src/cairo.c b/src/cairo.c
index 8ec603a..cf87464 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -802,16 +802,28 @@ cairo_set_fill_rule (cairo_t *cr, cairo_
/**
* cairo_set_line_width:
* @cr: a #cairo_t
- * @width: a line width, as a user-space value
+ * @width: a line width
*
* Sets the current line width within the cairo context. The line
- * width specifies the diameter of a pen that is circular in
- * user space.
+ * width value specifies the diameter of a pen that is circular in
+ * user space, (though device-space pen may be an ellipse in general
+ * due to scaling/shear/rotation of the CTM).
+ *
+ * Note: When the description above refers to user space and CTM it
+ * refers to the user space and CTM in effect at the time of the
+ * stroking operation, not the user space and CTM in effect at the
+ * time of the call to cairo_set_line_width(). The simplest usage
+ * makes both of these spaces identical. That is, if there is no
+ * change to the CTM between a call to cairo_set_line_with() and the
+ * stroking operation, then one can just pass user-space values to
+ * cairo_set_line_width() and ignore this note.
*
* As with the other stroke parameters, the current line width is
* examined by cairo_stroke(), cairo_stroke_extents(), and
* cairo_stroke_to_path(), but does not have any effect during path
* construction.
+ *
+ * The default line width value is 2.0.
**/
void
cairo_set_line_width (cairo_t *cr, double width)
@@ -2591,9 +2603,10 @@ cairo_get_fill_rule (cairo_t *cr)
* cairo_get_line_width:
* @cr: a cairo context
*
- * Gets the current line width, as set by cairo_set_line_width().
- *
- * Return value: the current line width, in user-space units.
+ * Return value: the current line width value exactly as set by
+ * cairo_set_line_width(). Note that the value is unchanged even if
+ * the CTM has changed between the calls to cairo_set_line_width() and
+ * cairo_get_line_width().
**/
double
cairo_get_line_width (cairo_t *cr)
diff --git a/test/line-width-scale-ps-argb32-ref.png b/test/line-width-scale-ps-argb32-ref.png
index ab4d552..2f01fc7 100644
Binary files a/test/line-width-scale-ps-argb32-ref.png and b/test/line-width-scale-ps-argb32-ref.png differ
diff --git a/test/line-width-scale-ref.png b/test/line-width-scale-ref.png
index 9f19759..c40bce3 100644
Binary files a/test/line-width-scale-ref.png and b/test/line-width-scale-ref.png differ
diff --git a/test/line-width-scale.c b/test/line-width-scale.c
index ec79a64..c733262 100644
--- a/test/line-width-scale.c
+++ b/test/line-width-scale.c
@@ -26,7 +26,7 @@
#include "cairo-test.h"
/* This test exercises the various interactions between
- * cairo_set_line_width and cairo_scale. Specifically it show how
+ * cairo_set_line_width and cairo_scale. Specifically it shows how
* separate transformations can affect the pen for stroking compared
* to the path itself.
*
@@ -35,11 +35,14 @@
*
* http://antigrain.com/tips/line_alignment/conv_order.gif
*
- * It also uncovered a bug in cairo that cairo_set_line_width was not
- * transforing the width according the the current CTM, but instead
- * delaying that transformation until the time of cairo_stroke. See:
- *
- * http://article.gmane.org/gmane.comp.graphics.agg/2518
+ * It also uncovered some behavior in cairo that I found surprising.
+ * Namely, cairo_set_line_width was not transforming the width
+ * according the the current CTM, but instead delaying that
+ * transformation until the time of cairo_stroke.
+ *
+ * This delayed behavior was released in cairo 1.0 so we're going to
+ * document this as the way cairo_set_line_width works rather than
+ * considering this a bug.
*/
#define LINE_WIDTH 13
@@ -106,12 +109,12 @@ scale_path_and_line_width (cairo_t *cr)
cairo_restore (cr);
}
-/* This one's the bug.
- *
- * If we set the line width before scaling, then the path should be
- * scaled but the line width should not.
+/* This is the case that was surprising.
*
- * With the bug, the line_width is also being scaled here.
+ * Setting the line width before scaling doesn't change anything. The
+ * line width will be interpreted under the CTM in effect at the time
+ * of cairo_stroke, so the line width will be scaled as well as the
+ * path here.
*/
static void
set_line_width_then_scale_and_stroke (cairo_t *cr)
@@ -122,10 +125,9 @@ set_line_width_then_scale_and_stroke (ca
cairo_stroke (cr);
}
-/* This is used to verify what should be the results of
- * set_line_width_then_scale_and_stroke (once the bug is fixed).
+/* Here then is the way to achieve the alternate result.
*
- * It uses save/restore pairs to isolate the scaling of the path and
+ * This uses save/restore pairs to isolate the scaling of the path and
* line_width and ensures that the path is scaled while the line width
* is not.
*/
More information about the cairo-commit
mailing list