[cairo-commit] 4 commits - .gitignore src/cairo.c src/cairo.h
src/cairoint.h src/cairo-path.c src/cairo-path-stroke.c
src/cairo-pdf-surface.c src/cairo-ps-surface.c
src/cairo-svg-surface.c test/.gitignore test/Makefile.am
test/new-sub-path.c test/new-sub-path-ps-argb32-ref.png
test/new-sub-path-ref.png test/new-sub-path-rgb24-ref.png
Carl Worth
cworth at kemper.freedesktop.org
Tue Apr 18 15:24:45 PDT 2006
.gitignore | 1
src/cairo-path-stroke.c | 24 ++--------
src/cairo-path.c | 40 +++++++++++++-----
src/cairo-pdf-surface.c | 48 +++++----------------
src/cairo-ps-surface.c | 78 +++++++++--------------------------
src/cairo-svg-surface.c | 17 -------
src/cairo.c | 64 +++++++++++++++++++++++++----
src/cairo.h | 3 +
src/cairoint.h | 3 +
test/.gitignore | 1
test/Makefile.am | 4 +
test/new-sub-path-ps-argb32-ref.png |binary
test/new-sub-path-ref.png |binary
test/new-sub-path-rgb24-ref.png |binary
test/new-sub-path.c | 79 ++++++++++++++++++++++++++++++++++++
15 files changed, 217 insertions(+), 145 deletions(-)
New commits:
diff-tree eadb26a1c13da1af292f0262e108878133cbadf0 (from 448e904b2a64769aa9cfd8ea011c2b5fb6ec883b)
Author: Carl Worth <cworth at cworth.org>
Date: Tue Apr 18 15:19:36 2006 -0700
Add new PS-specific reference image for new-sub-path.
diff --git a/test/new-sub-path-ps-argb32-ref.png b/test/new-sub-path-ps-argb32-ref.png
new file mode 100644
index 0000000..23b7e75
Binary files /dev/null and b/test/new-sub-path-ps-argb32-ref.png differ
diff-tree 448e904b2a64769aa9cfd8ea011c2b5fb6ec883b (from parents)
Merge: cb778760cb87e727a701603bcea3a2cdc063d785 ffab2592fc5d0ccd498aff2f4e645eefe351b61b
Author: Carl Worth <cworth at cworth.org>
Date: Tue Apr 18 15:18:31 2006 -0700
Merge branch 'cairo' into new-sub-path
Conflicts:
src/cairo-path-stroke.c
src/cairo-pdf-surface.c
src/cairo-ps-surface.c
diff --cc src/cairo-path-stroke.c
index e817099,d6044a3..7ca6ab8
@@@ -620,7 -636,11 +633,8 @@@
cairo_stroke_face_t start, end;
cairo_point_t *p1 = &stroker->current_point;
cairo_point_t *p2 = point;
+ cairo_slope_t slope;
- if (!stroker->has_current_point)
- return _cairo_stroker_move_to (stroker, point);
-
if (p1->x == p2->x && p1->y == p2->y) {
/* XXX: Need to rethink how this case should be handled, (both
here and in cairo_stroker_add_sub_edge and in _compute_face). The
@@@ -667,6 -689,20 +683,17 @@@
cairo_stroke_face_t sub_start, sub_end;
cairo_point_t *p1 = &stroker->current_point;
cairo_point_t *p2 = point;
+ cairo_slope_t slope;
+
- if (!stroker->has_current_point)
- return _cairo_stroker_move_to (stroker, point);
-
+ if (p1->x == p2->x && p1->y == p2->y) {
+ /* XXX: Need to rethink how this case should be handled, (both
+ here and in cairo_stroker_add_sub_edge and in _compute_face). The
+ key behavior is that degenerate paths should draw as much
+ as possible. */
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ _cairo_slope_init (&slope, p1, p2);
dx = _cairo_fixed_to_double (p2->x - p1->x);
dy = _cairo_fixed_to_double (p2->y - p1->y);
diff --cc src/cairo-pdf-surface.c
index 0c024a2,836b3ae..68c0271
@@@ -2086,3 -2037,233 +2017,229 @@@
return CAIRO_STATUS_SUCCESS;
}
+
+ static cairo_bool_t
+ _surface_pattern_supported (const cairo_surface_pattern_t *pattern)
+ {
+ if (pattern->surface->backend->acquire_source_image != NULL)
+ return TRUE;
+
+ return FALSE;
+ }
+
+ static cairo_bool_t
+ _pattern_supported (const cairo_pattern_t *pattern)
+ {
+ if (pattern->type == CAIRO_PATTERN_TYPE_SOLID)
+ return TRUE;
+
+ if (pattern->type == CAIRO_PATTERN_TYPE_SURFACE)
+ return _surface_pattern_supported ((const cairo_surface_pattern_t *) pattern);
+
+ return FALSE;
+ }
+
+ static cairo_int_status_t
+ _operation_supported (cairo_pdf_surface_t *surface,
+ cairo_operator_t op,
+ const cairo_pattern_t *pattern)
+ {
+ if (! _pattern_supported (pattern))
+ return FALSE;
+
+ if (_cairo_operator_always_opaque (op))
+ return TRUE;
+
+ if (_cairo_operator_always_translucent (op))
+ return FALSE;
+
+ return _cairo_pattern_is_opaque (pattern);
+ }
+
+ static cairo_int_status_t
+ _analyze_operation (cairo_pdf_surface_t *surface,
+ cairo_operator_t op,
+ const cairo_pattern_t *pattern)
+ {
+ if (_operation_supported (surface, op, pattern))
+ return CAIRO_STATUS_SUCCESS;
+ else
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ static cairo_int_status_t
+ _cairo_pdf_surface_paint (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source)
+ {
+ cairo_pdf_surface_t *surface = abstract_surface;
+
+ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ /* One would think that since we analyzed this away as unsupported
+ * that it would never be called after analyzing. But in fact,
+ * paint is called to paint the actual fallback surface. So we
+ * must not ASSERT_NOT_REACHED as we do for the other drawing
+ * operations. */
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ static cairo_int_status_t
+ _cairo_pdf_surface_mask (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_pattern_t *mask)
+ {
+ cairo_pdf_surface_t *surface = abstract_surface;
+
+ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ ASSERT_NOT_REACHED;
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ static cairo_int_status_t
+ _cairo_pdf_surface_stroke (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_path_fixed_t *path,
+ cairo_stroke_style_t *style,
+ cairo_matrix_t *ctm,
+ cairo_matrix_t *ctm_inverse,
+ double tolerance,
+ cairo_antialias_t antialias)
+ {
+ cairo_pdf_surface_t *surface = abstract_surface;
+
+ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ ASSERT_NOT_REACHED;
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ static cairo_int_status_t
+ _cairo_pdf_surface_fill (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_path_fixed_t *path,
+ cairo_fill_rule_t fill_rule,
+ double tolerance,
+ cairo_antialias_t antialias)
+ {
+ cairo_pdf_surface_t *surface = abstract_surface;
+ cairo_pdf_document_t *document = surface->document;
+ const char *pdf_operator;
+ cairo_status_t status;
- pdf_path_info_t info;
+
+ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ return _analyze_operation (surface, op, source);
+
+ assert (_operation_supported (surface, op, source));
+
+ status = emit_pattern (surface, source);
+ if (status)
+ return status;
+
+ /* After emitting the pattern the current stream should belong to
+ * this surface, so no need to _cairo_pdf_surface_ensure_stream()
+ */
+ assert (document->current_stream != NULL &&
+ document->current_stream == surface->current_stream);
+
- info.output_stream = document->output_stream;
- info.has_current_point = FALSE;
-
+ 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,
- &info);
++ document->output_stream);
+
+ switch (fill_rule) {
+ case CAIRO_FILL_RULE_WINDING:
+ pdf_operator = "f";
+ break;
+ case CAIRO_FILL_RULE_EVEN_ODD:
+ pdf_operator = "f*";
+ break;
+ default:
+ ASSERT_NOT_REACHED;
+ }
+
+ _cairo_output_stream_printf (document->output_stream,
+ "%s\r\n",
+ pdf_operator);
+
+ return status;
+ }
+
+ static cairo_int_status_t
+ _cairo_pdf_surface_show_glyphs (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ const cairo_glyph_t *glyphs,
+ int num_glyphs,
+ cairo_scaled_font_t *scaled_font)
+ {
+ cairo_pdf_surface_t *surface = abstract_surface;
+
+ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+
+ ASSERT_NOT_REACHED;
+
+ return CAIRO_INT_STATUS_UNSUPPORTED;
+ }
+
+ static void
+ _cairo_pdf_surface_set_paginated_mode (void *abstract_surface,
+ cairo_paginated_mode_t paginated_mode)
+ {
+ cairo_pdf_surface_t *surface = abstract_surface;
+
+ surface->paginated_mode = paginated_mode;
+ }
+
+ static const cairo_surface_backend_t cairo_pdf_surface_backend = {
+ CAIRO_SURFACE_TYPE_PDF,
+ _cairo_pdf_surface_create_similar,
+ _cairo_pdf_surface_finish,
+ NULL, /* acquire_source_image */
+ NULL, /* release_source_image */
+ NULL, /* acquire_dest_image */
+ NULL, /* release_dest_image */
+ NULL, /* clone_similar */
+ _cairo_pdf_surface_composite,
+ _cairo_pdf_surface_fill_rectangles,
+ _cairo_pdf_surface_composite_trapezoids,
+ _cairo_pdf_surface_copy_page,
+ _cairo_pdf_surface_show_page,
+ NULL, /* set_clip_region */
+ _cairo_pdf_surface_intersect_clip_path,
+ _cairo_pdf_surface_get_extents,
+ _cairo_pdf_surface_old_show_glyphs,
+ _cairo_pdf_surface_get_font_options,
+ NULL, /* flush */
+ NULL, /* mark_dirty_rectangle */
+ NULL, /* scaled_font_fini */
+ NULL, /* scaled_glyph_fini */
+
+ /* Here are the drawing functions */
+
+ _cairo_pdf_surface_paint,
+ _cairo_pdf_surface_mask,
+ _cairo_pdf_surface_stroke,
+ _cairo_pdf_surface_fill,
+ _cairo_pdf_surface_show_glyphs,
+ NULL, /* snapshot */
+ };
+
+ static const cairo_paginated_surface_backend_t cairo_pdf_surface_paginated_backend = {
+ NULL, /* start_page */
+ _cairo_pdf_surface_set_paginated_mode
+ };
diff --cc src/cairo-ps-surface.c
index 37053e9,19a835b..29b6882
@@@ -78,10 -107,79 +107,62 @@@
#define PS_SURFACE_DPI_DEFAULT 300.0
- #if DONE_ADDING_FONTS_SUPPORT_BACK_AFTER_SWITCHING_TO_PAGINATED
- static cairo_int_status_t
- _cairo_ps_surface_write_font_subsets (cairo_ps_surface_t *surface);
- #endif
-typedef struct
-{
- cairo_output_stream_t *output_stream;
- cairo_bool_t has_current_point;
-} cairo_ps_surface_path_info_t;
-
+ static cairo_status_t
+ _cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point)
+ {
- cairo_ps_surface_path_info_t *info = closure;
++ cairo_output_stream_t *output_stream = closure;
+
- _cairo_output_stream_printf (info->output_stream,
- "%f %f M ",
++ _cairo_output_stream_printf (output_stream,
++ "%f %f moveto ",
+ _cairo_fixed_to_double (point->x),
+ _cairo_fixed_to_double (point->y));
- info->has_current_point = TRUE;
+
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ static cairo_status_t
+ _cairo_ps_surface_path_line_to (void *closure, cairo_point_t *point)
+ {
- cairo_ps_surface_path_info_t *info = closure;
- const char *ps_operator;
++ cairo_output_stream_t *output_stream = closure;
+
- if (info->has_current_point)
- ps_operator = "L";
- else
- ps_operator = "M";
-
- _cairo_output_stream_printf (info->output_stream,
- "%f %f %s ",
++ _cairo_output_stream_printf (output_stream,
++ "%f %f lineto ",
+ _cairo_fixed_to_double (point->x),
- _cairo_fixed_to_double (point->y),
- ps_operator);
- info->has_current_point = TRUE;
++ _cairo_fixed_to_double (point->y));
+
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ static cairo_status_t
+ _cairo_ps_surface_path_curve_to (void *closure,
- cairo_point_t *b,
- cairo_point_t *c,
- cairo_point_t *d)
++ cairo_point_t *b,
++ cairo_point_t *c,
++ cairo_point_t *d)
+ {
- cairo_ps_surface_path_info_t *info = closure;
++ cairo_output_stream_t *output_stream = closure;
+
- _cairo_output_stream_printf (info->output_stream,
- "%f %f %f %f %f %f C ",
++ _cairo_output_stream_printf (output_stream,
++ "%f %f %f %f %f %f curveto ",
+ _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_ps_surface_path_close_path (void *closure)
+ {
- cairo_ps_surface_path_info_t *info = closure;
++ cairo_output_stream_t *output_stream = closure;
+
- if (info->has_current_point)
- _cairo_output_stream_printf (info->output_stream,
- "P\n");
- info->has_current_point = FALSE;
++ _cairo_output_stream_printf (output_stream,
++ "closepath\n");
+
+ return CAIRO_STATUS_SUCCESS;
+ }
static void
_cairo_ps_surface_emit_header (cairo_ps_surface_t *surface)
@@@ -101,13 -200,325 +183,321 @@@
surface->width,
surface->height);
- /* The "/FlateDecode filter" currently used is a feature of
- * LanguageLevel 3 */
- _cairo_output_stream_printf (surface->stream,
- "%%%%DocumentData: Binary\n"
- "%%%%LanguageLevel: 3\n"
+ _cairo_output_stream_printf (surface->final_stream,
+ "%%%%DocumentData: Clean7Bit\n"
+ "%%%%LanguageLevel: 2\n"
"%%%%Orientation: Portrait\n"
"%%%%EndComments\n");
+
+ _cairo_output_stream_printf (surface->final_stream,
+ "%%%%BeginProlog\n"
+ "/C{curveto}bind def\n"
+ "/F{fill}bind def\n"
+ "/G{setgray}bind def\n"
+ "/L{lineto}bind def\n"
+ "/M{moveto}bind def\n"
+ "/P{closepath}bind def\n"
+ "/R{setrgbcolor}bind def\n"
+ "/S{show}bind def\n"
+ "%%%%EndProlog\n");
+ }
+
+ static cairo_bool_t
+ _cairo_ps_glyph_equal (const void *key_a, const void *key_b)
+ {
+ const cairo_ps_glyph_t *ps_glyph_a = key_a;
+ const cairo_ps_glyph_t *ps_glyph_b = key_b;
+
+ return ps_glyph_a->base.hash == ps_glyph_b->base.hash;
+ }
+
+ static void
+ _cairo_ps_glyph_key_init (cairo_ps_glyph_t *ps_glyph,
+ unsigned long index)
+ {
+ ps_glyph->base.hash = index;
+ }
+
+ static cairo_ps_glyph_t *
+ _cairo_ps_glyph_create (cairo_ps_font_t *ps_font,
+ unsigned long index)
+ {
+ cairo_ps_glyph_t *ps_glyph = malloc (sizeof (cairo_ps_glyph_t));
+
+ if (!ps_glyph)
+ return NULL;
+ _cairo_ps_glyph_key_init (ps_glyph, index);
+ ps_glyph->output_glyph = ps_font->max_glyph++;
+ return ps_glyph;
+ }
+
+ static void
+ _cairo_ps_glyph_destroy (cairo_ps_glyph_t *ps_glyph)
+ {
+ free (ps_glyph);
+ }
+
+ static cairo_status_t
+ _cairo_ps_glyph_find (cairo_ps_font_t *font,
+ cairo_scaled_font_t *scaled_font,
+ unsigned long index,
+ cairo_ps_glyph_t **result)
+ {
+ cairo_ps_glyph_t key;
+ cairo_ps_glyph_t *ps_glyph;
+ cairo_status_t status;
+
+ _cairo_ps_glyph_key_init (&key, index);
+ if (!_cairo_hash_table_lookup (font->glyphs,
+ &key.base,
+ (cairo_hash_entry_t **) &ps_glyph)) {
+ ps_glyph = _cairo_ps_glyph_create (font, index);
+ if (!ps_glyph)
+ return CAIRO_STATUS_NO_MEMORY;
+ status = _cairo_hash_table_insert (font->glyphs, &ps_glyph->base);
+ if (status)
+ return status;
+ }
+ *result = ps_glyph;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ static cairo_bool_t
+ _cairo_ps_font_equal (const void *key_a, const void *key_b)
+ {
+ const cairo_ps_font_t *ps_font_a = key_a;
+ const cairo_ps_font_t *ps_font_b = key_b;
+
+ return ps_font_a->scaled_font == ps_font_b->scaled_font;
+ }
+
+ static void
+ _cairo_ps_font_key_init (cairo_ps_font_t *ps_font,
+ cairo_scaled_font_t *scaled_font)
+ {
+ ps_font->base.hash = (unsigned long) scaled_font;
+ ps_font->scaled_font = scaled_font;
+ }
+
+ static cairo_ps_font_t *
+ _cairo_ps_font_create (cairo_ps_surface_t *surface,
+ cairo_scaled_font_t *scaled_font)
+ {
+ cairo_ps_font_t *ps_font = malloc (sizeof (cairo_ps_font_t));
+ if (!ps_font)
+ return NULL;
+ _cairo_ps_font_key_init (ps_font, scaled_font);
+ ps_font->glyphs = _cairo_hash_table_create (_cairo_ps_glyph_equal);
+ if (!ps_font->glyphs) {
+ free (ps_font);
+ return NULL;
+ }
+ ps_font->max_glyph = 0;
+ ps_font->output_font = surface->max_font++;
+ cairo_scaled_font_reference (ps_font->scaled_font);
+ return ps_font;
+ }
+
+ static void
+ _cairo_ps_font_destroy_glyph (void *entry, void *closure)
+ {
+ cairo_ps_glyph_t *ps_glyph = entry;
+ cairo_ps_font_t *ps_font = closure;
+
+ _cairo_hash_table_remove (ps_font->glyphs, &ps_glyph->base);
+ _cairo_ps_glyph_destroy (ps_glyph);
+ }
+
+ static void
+ _cairo_ps_font_destroy (cairo_ps_font_t *ps_font)
+ {
+ _cairo_hash_table_foreach (ps_font->glyphs,
+ _cairo_ps_font_destroy_glyph,
+ ps_font);
+ _cairo_hash_table_destroy (ps_font->glyphs);
+ cairo_scaled_font_destroy (ps_font->scaled_font);
+ free (ps_font);
+ }
+
+ static void
+ _cairo_ps_surface_destroy_font (cairo_ps_surface_t *surface,
+ cairo_ps_font_t *ps_font)
+ {
+ _cairo_hash_table_remove (surface->fonts, &ps_font->base);
+ _cairo_ps_font_destroy (ps_font);
+ }
+
+ static cairo_status_t
+ _cairo_ps_font_find (cairo_ps_surface_t *surface,
+ cairo_scaled_font_t *scaled_font,
+ cairo_ps_font_t **result)
+ {
+ cairo_ps_font_t key;
+ cairo_ps_font_t *ps_font;
+ cairo_status_t status;
+
+ _cairo_ps_font_key_init (&key, scaled_font);
+ if (!_cairo_hash_table_lookup (surface->fonts, &key.base,
+ (cairo_hash_entry_t **) &ps_font))
+ {
+ ps_font = _cairo_ps_font_create (surface, scaled_font);
+ if (!ps_font)
+ return CAIRO_STATUS_NO_MEMORY;
+ status = _cairo_hash_table_insert (surface->fonts,
+ &ps_font->base);
+ if (status)
+ return status;
+ }
+ *result = ps_font;
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ typedef struct _cairo_ps_font_glyph_select {
+ cairo_ps_glyph_t **glyphs;
+ int subfont;
+ int numglyph;
+ } cairo_ps_font_glyph_select_t;
+
+ static void
+ _cairo_ps_font_select_glyphs (void *entry, void *closure)
+ {
+ cairo_ps_glyph_t *ps_glyph = entry;
+ cairo_ps_font_glyph_select_t *ps_glyph_select = closure;
+
+ if (ps_glyph->output_glyph >> 8 == ps_glyph_select->subfont) {
+ unsigned long sub_glyph = ps_glyph->output_glyph & 0xff;
+ ps_glyph_select->glyphs[sub_glyph] = ps_glyph;
+ if (sub_glyph >= ps_glyph_select->numglyph)
+ ps_glyph_select->numglyph = sub_glyph + 1;
+ }
+ }
+
+ static cairo_status_t
+ _cairo_ps_surface_emit_glyph (cairo_ps_surface_t *surface,
+ cairo_ps_font_t *ps_font,
+ cairo_ps_glyph_t *ps_glyph)
+ {
+ cairo_scaled_glyph_t *scaled_glyph;
+ cairo_status_t status;
- cairo_ps_surface_path_info_t info;
+
+ _cairo_output_stream_printf (surface->final_stream,
+ "\t\t{ %% %d\n", ps_glyph->output_glyph);
+ status = _cairo_scaled_glyph_lookup (ps_font->scaled_font,
+ ps_glyph->base.hash,
+ CAIRO_SCALED_GLYPH_INFO_METRICS|
+ CAIRO_SCALED_GLYPH_INFO_PATH,
+ &scaled_glyph);
+ /*
+ * If that fails, try again but ask for an image instead
+ */
+ if (status)
+ status = _cairo_scaled_glyph_lookup (ps_font->scaled_font,
+ ps_glyph->base.hash,
+ CAIRO_SCALED_GLYPH_INFO_METRICS|
+ CAIRO_SCALED_GLYPH_INFO_SURFACE,
+ &scaled_glyph);
+ if (status) {
+ _cairo_output_stream_printf (surface->final_stream, "\t\t}\n");
+ return status;
+ }
+ _cairo_output_stream_printf (surface->final_stream,
+ "%f %f %f %f 0 0 setcachedevice\n",
+ _cairo_fixed_to_double (scaled_glyph->bbox.p1.x),
+ -_cairo_fixed_to_double (scaled_glyph->bbox.p2.y),
+ _cairo_fixed_to_double (scaled_glyph->bbox.p2.x),
+ -_cairo_fixed_to_double (scaled_glyph->bbox.p1.y));
+
- info.output_stream = surface->final_stream;
- info.has_current_point = FALSE;
-
+ status = _cairo_path_fixed_interpret (scaled_glyph->path,
+ CAIRO_DIRECTION_FORWARD,
+ _cairo_ps_surface_path_move_to,
+ _cairo_ps_surface_path_line_to,
+ _cairo_ps_surface_path_curve_to,
+ _cairo_ps_surface_path_close_path,
- &info);
++ surface->final_stream);
+
+ _cairo_output_stream_printf (surface->final_stream,
+ "F\n");
+
+ _cairo_output_stream_printf (surface->final_stream,
+ "\t\t}\n");
+ return CAIRO_STATUS_SUCCESS;
+ }
+
+ static void
+ _cairo_ps_surface_emit_font (void *entry, void *closure)
+ {
+ cairo_ps_font_t *ps_font = entry;
+ cairo_ps_surface_t *surface = closure;
+ cairo_ps_font_glyph_select_t glyph_select;
+ cairo_ps_glyph_t *ps_glyphs[256], *ps_glyph;
+ int glyph, numglyph;
+ int subfont, nsubfont;
+
+ _cairo_output_stream_printf (surface->final_stream,
+ "%% _cairo_ps_surface_emit_font\n");
+ nsubfont = (ps_font->max_glyph >> 8) + 1;
+ for (subfont = 0; subfont < nsubfont; subfont++) {
+ _cairo_output_stream_printf (surface->final_stream,
+ "/CairoFont-%d-%d <<\n",
+ ps_font->output_font,
+ subfont);
+ memset (ps_glyphs, '\0', sizeof (ps_glyphs));
+ glyph_select.glyphs = ps_glyphs;
+ glyph_select.numglyph = 0;
+ glyph_select.subfont = subfont;
+ _cairo_hash_table_foreach (ps_font->glyphs,
+ _cairo_ps_font_select_glyphs,
+ &glyph_select);
+ _cairo_output_stream_printf (surface->final_stream,
+ "\t/FontType\t3\n"
+ "\t/FontMatrix\t[1 0 0 1 0 0]\n"
+ "\t/Encoding\t[0]\n"
+ "\t/FontBBox\t[0 0 10 10]\n"
+ "\t/Glyphs [\n");
+ numglyph = glyph_select.numglyph;
+ for (glyph = 0; glyph < numglyph; glyph++) {
+ ps_glyph = ps_glyphs[glyph];
+ if (ps_glyph) {
+ _cairo_ps_surface_emit_glyph (surface,
+ ps_font,
+ ps_glyph);
+ } else {
+ _cairo_output_stream_printf (surface->final_stream,
+ "\t\t{ } %% %d\n", glyph);
+ }
+ _cairo_ps_font_destroy_glyph (ps_glyph, ps_font);
+ }
+ _cairo_output_stream_printf (surface->final_stream,
+ "\t]\n"
+ "\t/BuildChar {\n"
+ "\t\texch /Glyphs get\n"
+ "\t\texch get exec\n"
+ "\t}\n"
+ ">> definefont pop\n");
+ }
+ _cairo_ps_surface_destroy_font (surface, ps_font);
+ }
+
+
+ static void
+ _cairo_ps_surface_emit_fonts (cairo_ps_surface_t *surface)
+ {
+ _cairo_hash_table_foreach (surface->fonts,
+ _cairo_ps_surface_emit_font,
+ surface);
+ _cairo_hash_table_destroy (surface->fonts);
+ surface->fonts = NULL;
+ }
+
+ static void
+ _cairo_ps_surface_emit_body (cairo_ps_surface_t *surface)
+ {
+ char buf[4096];
+ int n;
+
+ rewind (surface->tmpfile);
+ while ((n = fread (buf, 1, sizeof (buf), surface->tmpfile)) > 0)
+ _cairo_output_stream_write (surface->final_stream, buf, n);
}
static void
@@@ -1117,8 -1315,12 +1294,11 @@@
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
cairo_status_t status;
- cairo_ps_surface_path_info_t info;
const char *ps_operator;
+ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ return CAIRO_STATUS_SUCCESS;
+
_cairo_output_stream_printf (stream,
"%% _cairo_ps_surface_intersect_clip_path\n");
@@@ -1189,64 -1384,146 +1359,137 @@@
{
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
- cairo_font_subset_t *subset;
- int i, subset_index;
- cairo_ps_surface_path_info_t info;
- if (surface->fallback)
- return CAIRO_STATUS_SUCCESS;
+ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ return _analyze_operation (surface, op, source);
- if (surface->need_start_page)
- _cairo_ps_surface_start_page (surface);
+ /* XXX: It would be nice to be able to assert this condition
+ * here. But, we actually allow one 'cheat' that is used when
+ * painting the final image-based fallbacks. The final fallbacks
+ * do have alpha which we support by blending with white. This is
+ * possible only because there is nothing between the fallback
+ * images and the paper, nor is anything painted above. */
+ /*
+ assert (pattern_operation_supported (op, source));
+ */
+
+ _cairo_output_stream_printf (stream,
+ "%% _cairo_ps_surface_paint\n");
- /* XXX: Need to fix this to work with a general cairo_scaled_font_t. */
- if (! _cairo_scaled_font_is_ft (scaled_font))
- return CAIRO_INT_STATUS_UNSUPPORTED;
+ emit_pattern (surface, source);
- if (surface->fallback)
- return CAIRO_STATUS_SUCCESS;
- info.output_stream = stream;
- info.has_current_point = FALSE;
-
+ _cairo_output_stream_printf (stream, "0 0 M\n");
+ _cairo_output_stream_printf (stream, "%f 0 L\n", surface->width);
+ _cairo_output_stream_printf (stream, "%f %f L\n",
+ surface->width, surface->height);
+ _cairo_output_stream_printf (stream, "0 %f L\n", surface->height);
+ _cairo_output_stream_printf (stream, "P F\n");
+ return CAIRO_STATUS_SUCCESS;
+ }
- if (pattern_operation_needs_fallback (op, pattern))
- return _cairo_ps_surface_add_fallback_area (surface, dest_x, dest_y, width, height);
+ static int
+ _cairo_ps_line_cap (cairo_line_cap_t cap)
+ {
+ switch (cap) {
+ case CAIRO_LINE_CAP_BUTT:
+ return 0;
+ case CAIRO_LINE_CAP_ROUND:
+ return 1;
+ case CAIRO_LINE_CAP_SQUARE:
+ return 2;
+ default:
+ ASSERT_NOT_REACHED;
+ return 0;
+ }
+ }
- _cairo_output_stream_printf (stream,
- "%% _cairo_ps_surface_old_show_glyphs\n");
+ static int
+ _cairo_ps_line_join (cairo_line_join_t join)
+ {
+ switch (join) {
+ case CAIRO_LINE_JOIN_MITER:
+ return 0;
+ case CAIRO_LINE_JOIN_ROUND:
+ return 1;
+ case CAIRO_LINE_JOIN_BEVEL:
+ return 2;
+ default:
+ ASSERT_NOT_REACHED;
+ return 0;
+ }
+ }
- emit_pattern (surface, pattern);
+ static cairo_int_status_t
+ _cairo_ps_surface_stroke (void *abstract_surface,
+ cairo_operator_t op,
+ cairo_pattern_t *source,
+ cairo_path_fixed_t *path,
+ cairo_stroke_style_t *style,
+ cairo_matrix_t *ctm,
+ cairo_matrix_t *ctm_inverse,
+ double tolerance,
+ cairo_antialias_t antialias)
+ {
+ cairo_ps_surface_t *surface = abstract_surface;
+ cairo_output_stream_t *stream = surface->stream;
+ cairo_int_status_t status;
- cairo_ps_surface_path_info_t info;
- /* FIXME: Need to optimize this so we only do this sequence if the
- * font isn't already set. */
+ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ return _analyze_operation (surface, op, source);
- subset = _cairo_ps_surface_get_font (surface, scaled_font);
+ assert (operation_supported (surface, op, source));
+
_cairo_output_stream_printf (stream,
- "/f%d findfont\n"
- "[ %f %f %f %f 0 0 ] makefont\n"
- "setfont\n",
- subset->font_id,
- scaled_font->scale.xx,
- scaled_font->scale.yx,
- scaled_font->scale.xy,
- -scaled_font->scale.yy);
-
- /* FIXME: Need to optimize per glyph code. Should detect when
- * glyphs share the same baseline and when the spacing corresponds
- * to the glyph widths. */
+ "%% _cairo_ps_surface_stroke\n");
- for (i = 0; i < num_glyphs; i++) {
- subset_index = _cairo_font_subset_use_glyph (subset, glyphs[i].index);
- _cairo_output_stream_printf (stream,
- "%f %f moveto (\\%o) show\n",
- glyphs[i].x,
- glyphs[i].y,
- subset_index);
-
- }
+ emit_pattern (surface, source);
- return CAIRO_STATUS_SUCCESS;
-
- info.output_stream = stream;
- info.has_current_point = FALSE;
-
+ _cairo_output_stream_printf (stream,
+ "gsave\n");
+ status = _cairo_path_fixed_interpret (path,
+ CAIRO_DIRECTION_FORWARD,
+ _cairo_ps_surface_path_move_to,
+ _cairo_ps_surface_path_line_to,
+ _cairo_ps_surface_path_curve_to,
+ _cairo_ps_surface_path_close_path,
- &info);
++ stream);
+
+ /*
+ * Switch to user space to set line parameters
+ */
+ _cairo_output_stream_printf (stream,
+ "[%f %f %f %f 0 0] concat\n",
+ ctm->xx, ctm->yx, ctm->xy, ctm->yy);
+ /* line width */
+ _cairo_output_stream_printf (stream, "%f setlinewidth\n",
+ style->line_width);
+ /* line cap */
+ _cairo_output_stream_printf (stream, "%d setlinecap\n",
+ _cairo_ps_line_cap (style->line_cap));
+ /* line join */
+ _cairo_output_stream_printf (stream, "%d setlinejoin\n",
+ _cairo_ps_line_join (style->line_join));
+ /* dashes */
+ if (style->num_dashes) {
+ int d;
+ _cairo_output_stream_printf (stream, "[");
+ for (d = 0; d < style->num_dashes; d++)
+ _cairo_output_stream_printf (stream, " %f", style->dash[d]);
+ _cairo_output_stream_printf (stream, "] %f setdash\n",
+ style->dash_offset);
+ }
+ /* miter limit */
+ _cairo_output_stream_printf (stream, "%f setmiterlimit\n",
+ style->miter_limit);
+ _cairo_output_stream_printf (stream,
+ "stroke\n");
+ _cairo_output_stream_printf (stream,
+ "grestore\n");
+ return status;
}
- #endif
static cairo_int_status_t
- _cairo_ps_surface_fill (void *abstract_surface,
+ _cairo_ps_surface_fill (void *abstract_surface,
cairo_operator_t op,
cairo_pattern_t *source,
cairo_path_fixed_t *path,
@@@ -1257,17 -1534,14 +1500,13 @@@
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
cairo_int_status_t status;
- cairo_ps_surface_path_info_t info;
const char *ps_operator;
- if (pattern_operation_needs_fallback (op, source))
- return _cairo_ps_surface_add_fallback_area (surface,
- 0, 0,
- surface->width,
- surface->height);
-
- if (surface->need_start_page)
- _cairo_ps_surface_start_page (surface);
+ if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
+ return _analyze_operation (surface, op, source);
+ assert (operation_supported (surface, op, source));
+
_cairo_output_stream_printf (stream,
"%% _cairo_ps_surface_fill\n");
diff-tree cb778760cb87e727a701603bcea3a2cdc063d785 (from 1dc1b57b4eaa55b7a5cafe39f818f7c87352ea6d)
Author: Carl Worth <cworth at cworth.org>
Date: Thu Feb 23 22:07:13 2006 -0800
cairo_close_path: Document that there will be a current point after
cairo_close_path.
diff --git a/src/cairo.c b/src/cairo.c
index 6a94d0f..3319e2b 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -1417,7 +1417,8 @@ cairo_stroke_to_path (cairo_t *cr)
*
* Adds a line segment to the path from the current point to the
* beginning of the current subpath, (the most recent point passed to
- * cairo_move_to()), and closes this subpath.
+ * cairo_move_to()), and closes this subpath. After this call the
+ * current point will be at the joined endpoint of the subpath.
*
* The behavior of cairo_close_path() is distinct from simply calling
* cairo_line_to() with the equivalent coordinate in the case of
@@ -1425,7 +1426,8 @@ cairo_stroke_to_path (cairo_t *cr)
* the ends of the subpath. Instead, there is a line join connecting
* the final and initial segments of the subpath.
*
- * If there is no current point, this function will have no effect.
+ * If there is no current point before the call to cairo_close_path,
+ * this function will have no effect.
**/
void
cairo_close_path (cairo_t *cr)
diff-tree 1dc1b57b4eaa55b7a5cafe39f818f7c87352ea6d (from 0354956a09cf5a45feed256c1d880bbb9b7c7c42)
Author: Carl Worth <cworth at cworth.org>
Date: Thu Feb 23 22:01:07 2006 -0800
cairo_new_sub_path: Making cairo_arc easier to use and more.
This adds a new function which has as its only effect the elimination
of
the current point. This makes it much easier to use the various
cairo_arc calls when the initial line_to is not actually desired.
This function also unifies and generalizes the long-existing behavior
of cairo_line_to being treated as cairo_move_to when there is no
current point. With the addition of cairo_new_sub_path this becomes a
documented feature with similar behavior in cairo_curve_to as well.
diff --git a/.gitignore b/.gitignore
index aaa9f03..73e1e4e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -22,3 +22,4 @@ stamp-h
stamp-h1
stamp-h.in
*~
+*.orig
diff --git a/src/cairo-path-stroke.c b/src/cairo-path-stroke.c
index 96664ce..e817099 100644
--- a/src/cairo-path-stroke.c
+++ b/src/cairo-path-stroke.c
@@ -47,7 +47,6 @@ typedef struct cairo_stroker {
cairo_pen_t pen;
- cairo_bool_t has_current_point;
cairo_point_t current_point;
cairo_point_t first_point;
@@ -159,7 +158,6 @@ _cairo_stroker_init (cairo_stroker_t *s
stroke_style->line_width / 2.0,
tolerance, ctm);
- stroker->has_current_point = FALSE;
stroker->has_current_face = FALSE;
stroker->has_first_face = FALSE;
@@ -607,7 +605,6 @@ _cairo_stroker_move_to (void *closure, c
stroker->first_point = *point;
stroker->current_point = *point;
- stroker->has_current_point = 1;
stroker->has_first_face = 0;
stroker->has_current_face = 0;
@@ -624,9 +621,6 @@ _cairo_stroker_line_to (void *closure, c
cairo_point_t *p1 = &stroker->current_point;
cairo_point_t *p2 = point;
- if (!stroker->has_current_point)
- return _cairo_stroker_move_to (stroker, point);
-
if (p1->x == p2->x && p1->y == p2->y) {
/* XXX: Need to rethink how this case should be handled, (both
here and in cairo_stroker_add_sub_edge and in _compute_face). The
@@ -674,9 +668,6 @@ _cairo_stroker_line_to_dashed (void *clo
cairo_point_t *p1 = &stroker->current_point;
cairo_point_t *p2 = point;
- if (!stroker->has_current_point)
- return _cairo_stroker_move_to (stroker, point);
-
dx = _cairo_fixed_to_double (p2->x - p1->x);
dy = _cairo_fixed_to_double (p2->y - p1->y);
@@ -914,14 +905,12 @@ _cairo_stroker_close_path (void *closure
cairo_status_t status;
cairo_stroker_t *stroker = closure;
- if (stroker->has_current_point) {
- if (stroker->dashed)
- status = _cairo_stroker_line_to_dashed (stroker, &stroker->first_point);
- else
- status = _cairo_stroker_line_to (stroker, &stroker->first_point);
- if (status)
- return status;
- }
+ if (stroker->dashed)
+ status = _cairo_stroker_line_to_dashed (stroker, &stroker->first_point);
+ else
+ status = _cairo_stroker_line_to (stroker, &stroker->first_point);
+ if (status)
+ return status;
if (stroker->has_first_face && stroker->has_current_face) {
status = _cairo_stroker_join (stroker, &stroker->current_face, &stroker->first_face);
@@ -931,7 +920,6 @@ _cairo_stroker_close_path (void *closure
stroker->has_first_face = 0;
stroker->has_current_face = 0;
- stroker->has_current_point = 0;
return CAIRO_STATUS_SUCCESS;
}
diff --git a/src/cairo-path.c b/src/cairo-path.c
index 669e587..7358bee 100644
--- a/src/cairo-path.c
+++ b/src/cairo-path.c
@@ -87,7 +87,7 @@ _cairo_path_fixed_init (cairo_path_fixed
path->current_point.x = 0;
path->current_point.y = 0;
- path->has_current_point = 0;
+ path->has_current_point = FALSE;
path->last_move_point = path->current_point;
}
@@ -163,7 +163,7 @@ _cairo_path_fixed_fini (cairo_path_fixed
}
path->arg_buf_tail = NULL;
- path->has_current_point = 0;
+ path->has_current_point = FALSE;
}
void
@@ -189,12 +189,18 @@ _cairo_path_fixed_move_to (cairo_path_fi
return status;
path->current_point = point;
- path->has_current_point = 1;
+ path->has_current_point = TRUE;
path->last_move_point = path->current_point;
return CAIRO_STATUS_SUCCESS;
}
+void
+_cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path)
+{
+ path->has_current_point = FALSE;
+}
+
cairo_status_t
_cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
cairo_fixed_t dx,
@@ -202,7 +208,7 @@ _cairo_path_fixed_rel_move_to (cairo_pat
{
cairo_fixed_t x, y;
- if (!path->has_current_point)
+ if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
x = path->current_point.x + dx;
@@ -222,12 +228,16 @@ _cairo_path_fixed_line_to (cairo_path_fi
point.x = x;
point.y = y;
- status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
+ if (! path->has_current_point)
+ status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO, &point, 1);
+ else
+ status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_LINE_TO, &point, 1);
+
if (status)
return status;
path->current_point = point;
- path->has_current_point = 1;
+ path->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@@ -239,7 +249,7 @@ _cairo_path_fixed_rel_line_to (cairo_pat
{
cairo_fixed_t x, y;
- if (!path->has_current_point)
+ if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
x = path->current_point.x + dx;
@@ -261,12 +271,19 @@ _cairo_path_fixed_curve_to (cairo_path_f
point[1].x = x1; point[1].y = y1;
point[2].x = x2; point[2].y = y2;
+ if (! path->has_current_point) {
+ status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_MOVE_TO,
+ &point[0], 1);
+ if (status)
+ return status;
+ }
+
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CURVE_TO, point, 3);
if (status)
return status;
path->current_point = point[2];
- path->has_current_point = 1;
+ path->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@@ -281,7 +298,7 @@ _cairo_path_fixed_rel_curve_to (cairo_pa
cairo_fixed_t x1, y1;
cairo_fixed_t x2, y2;
- if (!path->has_current_point)
+ if (! path->has_current_point)
return CAIRO_STATUS_NO_CURRENT_POINT;
x0 = path->current_point.x + dx0;
@@ -304,13 +321,16 @@ _cairo_path_fixed_close_path (cairo_path
{
cairo_status_t status;
+ if (! path->has_current_point)
+ return CAIRO_STATUS_SUCCESS;
+
status = _cairo_path_fixed_add (path, CAIRO_PATH_OP_CLOSE_PATH, NULL, 0);
if (status)
return status;
path->current_point.x = path->last_move_point.x;
path->current_point.y = path->last_move_point.y;
- path->has_current_point = 1;
+ path->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index ee5c482..0c024a2 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1263,22 +1263,15 @@ intersect (cairo_line_t *line, cairo_fix
_cairo_fixed_to_double (line->p2.y - line->p1.y);
}
-typedef struct
-{
- cairo_output_stream_t *output_stream;
- cairo_bool_t has_current_point;
-} pdf_path_info_t;
-
static cairo_status_t
_cairo_pdf_path_move_to (void *closure, cairo_point_t *point)
{
- pdf_path_info_t *info = closure;
+ cairo_output_stream_t *output_stream = closure;
- _cairo_output_stream_printf (info->output_stream,
+ _cairo_output_stream_printf (output_stream,
"%f %f m ",
_cairo_fixed_to_double (point->x),
_cairo_fixed_to_double (point->y));
- info->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1286,20 +1279,12 @@ _cairo_pdf_path_move_to (void *closure,
static cairo_status_t
_cairo_pdf_path_line_to (void *closure, cairo_point_t *point)
{
- pdf_path_info_t *info = closure;
- const char *pdf_operator;
-
- if (info->has_current_point)
- pdf_operator = "l";
- else
- pdf_operator = "m";
+ cairo_output_stream_t *output_stream = closure;
- _cairo_output_stream_printf (info->output_stream,
- "%f %f %s ",
+ _cairo_output_stream_printf (output_stream,
+ "%f %f l ",
_cairo_fixed_to_double (point->x),
- _cairo_fixed_to_double (point->y),
- pdf_operator);
- info->has_current_point = TRUE;
+ _cairo_fixed_to_double (point->y));
return CAIRO_STATUS_SUCCESS;
}
@@ -1310,9 +1295,9 @@ _cairo_pdf_path_curve_to (void
cairo_point_t *c,
cairo_point_t *d)
{
- pdf_path_info_t *info = closure;
+ cairo_output_stream_t *output_stream = closure;
- _cairo_output_stream_printf (info->output_stream,
+ _cairo_output_stream_printf (output_stream,
"%f %f %f %f %f %f c ",
_cairo_fixed_to_double (b->x),
_cairo_fixed_to_double (b->y),
@@ -1327,11 +1312,10 @@ _cairo_pdf_path_curve_to (void
static cairo_status_t
_cairo_pdf_path_close_path (void *closure)
{
- pdf_path_info_t *info = closure;
+ cairo_output_stream_t *output_stream = closure;
- _cairo_output_stream_printf (info->output_stream,
+ _cairo_output_stream_printf (output_stream,
"h\r\n");
- info->has_current_point = FALSE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1349,7 +1333,6 @@ _cairo_pdf_surface_fill (void *abstrac
cairo_pdf_document_t *document = surface->document;
const char *pdf_operator;
cairo_status_t status;
- pdf_path_info_t info;
status = emit_pattern (surface, pattern);
if (status)
@@ -1360,16 +1343,13 @@ _cairo_pdf_surface_fill (void *abstrac
assert (document->current_stream != NULL &&
document->current_stream == surface->current_stream);
- info.output_stream = document->output_stream;
- info.has_current_point = FALSE;
-
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,
- &info);
+ document->output_stream);
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
@@ -1600,7 +1580,6 @@ _cairo_pdf_surface_intersect_clip_path (
cairo_pdf_document_t *document = surface->document;
cairo_output_stream_t *output = document->output_stream;
cairo_status_t status;
- pdf_path_info_t info;
const char *pdf_operator;
_cairo_pdf_surface_ensure_stream (surface);
@@ -1617,16 +1596,13 @@ _cairo_pdf_surface_intersect_clip_path (
surface->has_clip = TRUE;
}
- info.output_stream = document->output_stream;
- info.has_current_point = FALSE;
-
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,
- &info);
+ document->output_stream);
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 6cf8621..37053e9 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -1049,22 +1049,16 @@ _cairo_ps_surface_composite_trapezoids (
return CAIRO_STATUS_SUCCESS;
}
-typedef struct
-{
- cairo_output_stream_t *output_stream;
- cairo_bool_t has_current_point;
-} cairo_ps_surface_path_info_t;
static cairo_status_t
_cairo_ps_surface_path_move_to (void *closure, cairo_point_t *point)
{
- cairo_ps_surface_path_info_t *info = closure;
+ cairo_output_stream_t *output_stream = closure;
- _cairo_output_stream_printf (info->output_stream,
+ _cairo_output_stream_printf (output_stream,
"%f %f moveto ",
_cairo_fixed_to_double (point->x),
_cairo_fixed_to_double (point->y));
- info->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1072,33 +1066,25 @@ _cairo_ps_surface_path_move_to (void *cl
static cairo_status_t
_cairo_ps_surface_path_line_to (void *closure, cairo_point_t *point)
{
- cairo_ps_surface_path_info_t *info = closure;
- const char *ps_operator;
+ cairo_output_stream_t *output_stream = closure;
- if (info->has_current_point)
- ps_operator = "lineto";
- else
- ps_operator = "moveto";
-
- _cairo_output_stream_printf (info->output_stream,
- "%f %f %s ",
+ _cairo_output_stream_printf (output_stream,
+ "%f %f lineto ",
_cairo_fixed_to_double (point->x),
- _cairo_fixed_to_double (point->y),
- ps_operator);
- info->has_current_point = TRUE;
+ _cairo_fixed_to_double (point->y));
return CAIRO_STATUS_SUCCESS;
}
static cairo_status_t
_cairo_ps_surface_path_curve_to (void *closure,
- cairo_point_t *b,
- cairo_point_t *c,
- cairo_point_t *d)
+ cairo_point_t *b,
+ cairo_point_t *c,
+ cairo_point_t *d)
{
- cairo_ps_surface_path_info_t *info = closure;
+ cairo_output_stream_t *output_stream = closure;
- _cairo_output_stream_printf (info->output_stream,
+ _cairo_output_stream_printf (output_stream,
"%f %f %f %f %f %f curveto ",
_cairo_fixed_to_double (b->x),
_cairo_fixed_to_double (b->y),
@@ -1113,11 +1099,10 @@ _cairo_ps_surface_path_curve_to (void
static cairo_status_t
_cairo_ps_surface_path_close_path (void *closure)
{
- cairo_ps_surface_path_info_t *info = closure;
+ cairo_output_stream_t *output_stream = closure;
- _cairo_output_stream_printf (info->output_stream,
+ _cairo_output_stream_printf (output_stream,
"closepath\n");
- info->has_current_point = FALSE;
return CAIRO_STATUS_SUCCESS;
}
@@ -1132,7 +1117,6 @@ _cairo_ps_surface_intersect_clip_path (v
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
cairo_status_t status;
- cairo_ps_surface_path_info_t info;
const char *ps_operator;
_cairo_output_stream_printf (stream,
@@ -1143,16 +1127,13 @@ _cairo_ps_surface_intersect_clip_path (v
return CAIRO_STATUS_SUCCESS;
}
- info.output_stream = stream;
- info.has_current_point = FALSE;
-
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_ps_surface_path_move_to,
_cairo_ps_surface_path_line_to,
_cairo_ps_surface_path_curve_to,
_cairo_ps_surface_path_close_path,
- &info);
+ stream);
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
@@ -1276,7 +1257,6 @@ _cairo_ps_surface_fill (void *abstract
cairo_ps_surface_t *surface = abstract_surface;
cairo_output_stream_t *stream = surface->stream;
cairo_int_status_t status;
- cairo_ps_surface_path_info_t info;
const char *ps_operator;
if (pattern_operation_needs_fallback (op, source))
@@ -1293,16 +1273,13 @@ _cairo_ps_surface_fill (void *abstract
emit_pattern (surface, source);
- info.output_stream = stream;
- info.has_current_point = FALSE;
-
status = _cairo_path_fixed_interpret (path,
CAIRO_DIRECTION_FORWARD,
_cairo_ps_surface_path_move_to,
_cairo_ps_surface_path_line_to,
_cairo_ps_surface_path_curve_to,
_cairo_ps_surface_path_close_path,
- &info);
+ stream);
switch (fill_rule) {
case CAIRO_FILL_RULE_WINDING:
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 5a2c92f..9297005 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -783,7 +783,6 @@ emit_pattern (cairo_svg_surface_t *surfa
typedef struct
{
cairo_svg_document_t *document;
- cairo_bool_t has_current_point;
xmlBufferPtr path;
} svg_path_info_t;
@@ -801,7 +800,6 @@ _cairo_svg_path_move_to (void *closure,
_cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (point->y));
xmlBufferCat (path, CC2XML (buffer));
xmlBufferCat (path, CC2XML (" "));
- info->has_current_point = TRUE;
return CAIRO_STATUS_SUCCESS;
}
@@ -813,10 +811,7 @@ _cairo_svg_path_line_to (void *closure,
xmlBufferPtr path = info->path;
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
- if (info->has_current_point)
- xmlBufferCat (path, CC2XML ("L "));
- else
- xmlBufferCat (path, CC2XML ("M "));
+ xmlBufferCat (path, CC2XML ("L "));
_cairo_dtostr (buffer, sizeof buffer, _cairo_fixed_to_double (point->x));
xmlBufferCat (path, CC2XML (buffer));
@@ -825,8 +820,6 @@ _cairo_svg_path_line_to (void *closure,
xmlBufferCat (path, CC2XML (buffer));
xmlBufferCat (path, CC2XML (" "));
- info->has_current_point = TRUE;
-
return CAIRO_STATUS_SUCCESS;
}
@@ -868,10 +861,7 @@ _cairo_svg_path_close_path (void *closur
{
svg_path_info_t *info = closure;
- if (info->has_current_point)
- xmlBufferCat (info->path, CC2XML ("Z "));
-
- info->has_current_point = FALSE;
+ xmlBufferCat (info->path, CC2XML ("Z "));
return CAIRO_STATUS_SUCCESS;
}
@@ -893,7 +883,6 @@ _cairo_svg_surface_fill (void *abstrac
xmlBufferPtr style;
info.document = document;
- info.has_current_point = FALSE;
info.path = xmlBufferCreate ();
style = xmlBufferCreate ();
@@ -1035,7 +1024,6 @@ _cairo_svg_surface_stroke (void *abstr
char buffer[CAIRO_SVG_DTOSTR_BUFFER_LEN];
info.document = document;
- info.has_current_point = FALSE;
info.path = xmlBufferCreate ();
rx = ry = stroke_style->line_width;
@@ -1176,7 +1164,6 @@ _cairo_svg_surface_intersect_clip_path (
if (path != NULL) {
info.document = document;
- info.has_current_point = FALSE;
info.path = xmlBufferCreate ();
group = xmlNewChild (surface->xml_node, NULL, CC2XML ("g"), NULL);
diff --git a/src/cairo.c b/src/cairo.c
index 96cd504..6a94d0f 100644
--- a/src/cairo.c
+++ b/src/cairo.c
@@ -957,8 +957,8 @@ cairo_device_to_user_distance (cairo_t *
* cairo_new_path:
* @cr: a cairo context
*
- * Clears the current path. After this call there will be no current
- * point.
+ * Clears the current path. After this call there will be no path and
+ * no current point.
**/
void
cairo_new_path (cairo_t *cr)
@@ -976,8 +976,8 @@ slim_hidden_def(cairo_new_path);
* @x: the X coordinate of the new position
* @y: the Y coordinate of the new position
*
- * If the current subpath is not empty, begin a new subpath. After
- * this call the current point will be (@x, @y).
+ * Begin a new subpath. After this call the current point will be (@x,
+ * @y).
**/
void
cairo_move_to (cairo_t *cr, double x, double y)
@@ -998,6 +998,31 @@ cairo_move_to (cairo_t *cr, double x, do
slim_hidden_def(cairo_move_to);
/**
+ * cairo_new_sub_path:
+ * @cr: a cairo context
+ *
+ * Begin a new subpath. Note that the existing path is not
+ * affected. After this call there will be no current point.
+ *
+ * In many cases, this call is not needed since new subpaths are
+ * frequently started with cairo_move_to().
+ *
+ * A call to cairo_new_sub_path() is particularly useful when
+ * beginning a new subpath with one of the cairo_arc() calls. This
+ * makes things easier as it is no longer necessary to manually
+ * compute the arc's initial coordinates for a call to
+ * cairo_move_to().
+ **/
+void
+cairo_new_sub_path (cairo_t *cr)
+{
+ if (cr->status)
+ return;
+
+ _cairo_path_fixed_new_sub_path (&cr->path);
+}
+
+/**
* cairo_line_to:
* @cr: a cairo context
* @x: the X coordinate of the end of the new line
@@ -1006,6 +1031,9 @@ slim_hidden_def(cairo_move_to);
* Adds a line to the path from the current point to position (@x, @y)
* in user-space coordinates. After this call the current point
* will be (@x, @y).
+ *
+ * If there is no current point before the call to cairo_line_to()
+ * this function will behave as cairo_move_to (@cr, @x, @y).
**/
void
cairo_line_to (cairo_t *cr, double x, double y)
@@ -1038,6 +1066,10 @@ cairo_line_to (cairo_t *cr, double x, do
* position (@x3, @y3) in user-space coordinates, using (@x1, @y1) and
* (@x2, @y2) as the control points. After this call the current point
* will be (@x3, @y3).
+ *
+ * If there is no current point before the call to cairo_curve_to()
+ * this function will behave as if preceded by a call to
+ * cairo_move_to (@cr, @x1, @y1).
**/
void
cairo_curve_to (cairo_t *cr,
@@ -1208,11 +1240,15 @@ cairo_arc_to (cairo_t *cr,
* @dx: the X offset
* @dy: the Y offset
*
- * If the current subpath is not empty, begin a new subpath. After
- * this call the current point will offset by (@x, @y).
+ * Begin a new subpath. After this call the current point will offset
+ * by (@x, @y).
*
* Given a current point of (x, y), cairo_rel_move_to(@cr, @dx, @dy)
* is logically equivalent to cairo_move_to (@cr, x + @dx, y + @dy).
+ *
+ * It is an error to call this function with no current point. Doing
+ * so will cause @cr to shutdown with a status of
+ * CAIRO_STATUS_NO_CURRENT_POINT.
**/
void
cairo_rel_move_to (cairo_t *cr, double dx, double dy)
@@ -1244,6 +1280,10 @@ cairo_rel_move_to (cairo_t *cr, double d
*
* Given a current point of (x, y), cairo_rel_line_to(@cr, @dx, @dy)
* is logically equivalent to cairo_line_to (@cr, x + @dx, y + @dy).
+ *
+ * It is an error to call this function with no current point. Doing
+ * so will cause @cr to shutdown with a status of
+ * CAIRO_STATUS_NO_CURRENT_POINT.
**/
void
cairo_rel_line_to (cairo_t *cr, double dx, double dy)
@@ -1284,6 +1324,10 @@ slim_hidden_def(cairo_rel_line_to);
* @dy1, @dx2, @dy2, @dx3, @dy3) is logically equivalent to
* cairo_curve_to (@cr, x + @dx1, y + @dy1, x + @dx2, y + @dy2, x +
* @dx3, y + @dy3).
+ *
+ * It is an error to call this function with no current point. Doing
+ * so will cause @cr to shutdown with a status of
+ * CAIRO_STATUS_NO_CURRENT_POINT.
**/
void
cairo_rel_curve_to (cairo_t *cr,
@@ -1378,8 +1422,10 @@ cairo_stroke_to_path (cairo_t *cr)
* The behavior of cairo_close_path() is distinct from simply calling
* cairo_line_to() with the equivalent coordinate in the case of
* stroking. When a closed subpath is stroked, there are no caps on
- * the ends of the subpath. Instead, their is a line join connecting
+ * the ends of the subpath. Instead, there is a line join connecting
* the final and initial segments of the subpath.
+ *
+ * If there is no current point, this function will have no effect.
**/
void
cairo_close_path (cairo_t *cr)
diff --git a/src/cairo.h b/src/cairo.h
index fbb3620..6dd2742 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -436,6 +436,9 @@ cairo_public void
cairo_move_to (cairo_t *cr, double x, double y);
cairo_public void
+cairo_new_sub_path (cairo_t *cr);
+
+cairo_public void
cairo_line_to (cairo_t *cr, double x, double y);
cairo_public void
diff --git a/src/cairoint.h b/src/cairoint.h
index 88fccae..d51b994 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1394,6 +1394,9 @@ _cairo_path_fixed_move_to (cairo_path_fi
cairo_fixed_t x,
cairo_fixed_t y);
+cairo_private void
+_cairo_path_fixed_new_sub_path (cairo_path_fixed_t *path);
+
cairo_private cairo_status_t
_cairo_path_fixed_rel_move_to (cairo_path_fixed_t *path,
cairo_fixed_t dx,
diff --git a/test/.gitignore b/test/.gitignore
index 5173349..1a12122 100644
--- a/test/.gitignore
+++ b/test/.gitignore
@@ -37,6 +37,7 @@ move-to-show-surface
multi-page
multi-page.pdf
multi-page.ps
+new-sub-path
nil-surface
operator-clear
operator-source
diff --git a/test/Makefile.am b/test/Makefile.am
index 0da8b5a..0ea0624 100644
--- a/test/Makefile.am
+++ b/test/Makefile.am
@@ -29,6 +29,7 @@ mask \
mask-ctm \
mask-surface-ctm \
move-to-show-surface \
+new-sub-path \
nil-surface \
operator-clear \
operator-source \
@@ -143,6 +144,8 @@ mask-surface-ctm-ref.png \
mask-surface-ctm-rgb24-ref.png \
move-to-show-surface-ref.png \
move-to-show-surface-rgb24-ref.png \
+new-sub-path-ref.png \
+new-sub-path-rgb24-ref.png \
nil-surface-ref.png \
nil-surface-rgb24-ref.png \
operator-clear-ref.png \
@@ -311,6 +314,7 @@ mask_ctm_LDADD = $(LDADDS)
mask_surface_ctm_LDADD = $(LDADDS)
multi_page_LDADD = $(LDADDS)
move_to_show_surface_LDADD = $(LDADDS)
+new_sub_path_LDADD = $(LDADDS)
nil_surface_LDADD = $(LDADDS)
operator_clear_LDADD = $(LDADDS)
operator_source_LDADD = $(LDADDS)
diff --git a/test/new-sub-path-ref.png b/test/new-sub-path-ref.png
new file mode 100644
index 0000000..7319ab3
Binary files /dev/null and b/test/new-sub-path-ref.png differ
diff --git a/test/new-sub-path-rgb24-ref.png b/test/new-sub-path-rgb24-ref.png
new file mode 100644
index 0000000..8cbc731
Binary files /dev/null and b/test/new-sub-path-rgb24-ref.png differ
diff --git a/test/new-sub-path.c b/test/new-sub-path.c
new file mode 100644
index 0000000..90e0c73
--- /dev/null
+++ b/test/new-sub-path.c
@@ -0,0 +1,79 @@
+/*
+ * 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 SIZE 10
+
+cairo_test_t test = {
+ "new-sub-path",
+ "Test the cairo_new_sub_path call",
+ 8 * SIZE,
+ 3 * SIZE
+};
+
+static cairo_test_status_t
+draw (cairo_t *cr, int width, int height)
+{
+ cairo_set_source_rgb (cr, 0.0, 0.0, 1.0); /* blue */
+
+ /* Test cairo_new_sub_path followed by several different
+ * path-modification functions in turn...
+ */
+
+ /* ... cairo_move_to */
+ cairo_new_sub_path (cr);
+ cairo_move_to (cr, SIZE, SIZE);
+ cairo_line_to (cr, SIZE, 2 * SIZE);
+
+ /* ... cairo_line_to */
+ cairo_new_sub_path (cr);
+ cairo_line_to (cr, 2 * SIZE, 1.5 * SIZE);
+ cairo_line_to (cr, 3 * SIZE, 1.5 * SIZE);
+
+ /* ... cairo_curve_to */
+ cairo_new_sub_path (cr);
+ cairo_curve_to (cr,
+ 4.0 * SIZE, 1.5 * SIZE,
+ 4.5 * SIZE, 1.0 * SIZE,
+ 5.0 * SIZE, 1.5 * SIZE);
+
+ /* ... cairo_arc */
+ cairo_new_sub_path (cr);
+ cairo_arc (cr,
+ 6.5 * SIZE, 1.5 * SIZE,
+ 0.5 * SIZE,
+ 0.0, 2.0 * M_PI);
+
+ cairo_stroke (cr);
+
+ return CAIRO_TEST_SUCCESS;
+}
+
+int
+main (void)
+{
+ return cairo_test (&test, draw);
+}
More information about the cairo-commit
mailing list