[cairo-commit] 7 commits - boilerplate/cairo-boilerplate-xcb.c src/cairo.h src/cairoint.h src/cairo-path-fixed-private.h src/cairo-pattern.c src/cairo-pdf-surface.c src/cairo-ps-surface.c src/cairo-surface.c src/cairo-tee-surface.c src/cairo-xml-surface.c util/cairo-fdr util/cairo-sphinx

Chris Wilson ickle at kemper.freedesktop.org
Tue Sep 1 12:29:04 PDT 2009


 boilerplate/cairo-boilerplate-xcb.c |   13 ++
 src/cairo-path-fixed-private.h      |    4 
 src/cairo-pattern.c                 |    9 --
 src/cairo-pdf-surface.c             |   68 +++++++++++++--
 src/cairo-ps-surface.c              |  122 ++++++++++++++++++++-------
 src/cairo-surface.c                 |  162 ++++++++++++++++++++++++++++++++++++
 src/cairo-tee-surface.c             |   51 ++++++++++-
 src/cairo-xml-surface.c             |    8 -
 src/cairo.h                         |    8 +
 src/cairoint.h                      |   50 ++++++++++-
 util/cairo-fdr/fdr.c                |    2 
 util/cairo-sphinx/fdr.c             |    2 
 12 files changed, 439 insertions(+), 60 deletions(-)

New commits:
commit 6ddab64025eacd5000fa295c86c0fddc469bdc5f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 1 20:25:53 2009 +0100

    [ps] Clip meta-surface to desired extents.
    
    Ensure that the meta surface does not extend beyond the operation by
    forcing a clip to the extents of the operation.
    
    Fixes test/device-offset and test/device-offset-positive

diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 49d962b..26bba17 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -2317,9 +2317,11 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t  *surface,
     if (cairo_surface_get_content (meta_surface) == CAIRO_CONTENT_COLOR) {
 	surface->content = CAIRO_CONTENT_COLOR;
 	_cairo_output_stream_printf (surface->stream,
-				     "  0 g 0 0 %f %f rectfill\n",
-				     surface->width,
-				     surface->height);
+				     "  0 g %d %d %d %d rectfill\n",
+				     surface->page_bbox.x,
+				     surface->page_bbox.y,
+				     surface->page_bbox.width,
+				     surface->page_bbox.height);
     }
 
     status = _cairo_meta_surface_replay_region (meta_surface, &surface->base,
@@ -2527,6 +2529,35 @@ _cairo_ps_surface_release_surface (cairo_ps_surface_t      *surface,
     surface->image = NULL;
 }
 
+static void
+_path_fixed_init_rectangle (cairo_path_fixed_t *path,
+			    cairo_rectangle_int_t *rect)
+{
+    cairo_status_t status;
+
+    _cairo_path_fixed_init (path);
+
+    status = _cairo_path_fixed_move_to (path,
+					_cairo_fixed_from_int (rect->x),
+					_cairo_fixed_from_int (rect->y));
+    assert (status == CAIRO_STATUS_SUCCESS);
+    status = _cairo_path_fixed_rel_line_to (path,
+					    _cairo_fixed_from_int (rect->width),
+					    _cairo_fixed_from_int (0));
+    assert (status == CAIRO_STATUS_SUCCESS);
+    status = _cairo_path_fixed_rel_line_to (path,
+					    _cairo_fixed_from_int (0),
+					    _cairo_fixed_from_int (rect->height));
+    assert (status == CAIRO_STATUS_SUCCESS);
+    status = _cairo_path_fixed_rel_line_to (path,
+					    _cairo_fixed_from_int (-rect->width),
+					    _cairo_fixed_from_int (0));
+    assert (status == CAIRO_STATUS_SUCCESS);
+
+    status = _cairo_path_fixed_close_path (path);
+    assert (status == CAIRO_STATUS_SUCCESS);
+}
+
 static cairo_status_t
 _cairo_ps_surface_paint_surface (cairo_ps_surface_t      *surface,
 				 cairo_surface_pattern_t *pattern,
@@ -2536,6 +2567,7 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t      *surface,
     cairo_status_t status;
     int width, height;
     cairo_matrix_t cairo_p2d, ps_p2d;
+    cairo_path_fixed_t path;
     int origin_x = 0;
     int origin_y = 0;
 
@@ -2547,6 +2579,14 @@ _cairo_ps_surface_paint_surface (cairo_ps_surface_t      *surface,
     if (unlikely (status))
 	return status;
 
+    _path_fixed_init_rectangle (&path, extents);
+    status = _cairo_pdf_operators_clip (&surface->pdf_operators,
+					&path,
+					CAIRO_FILL_RULE_WINDING);
+    _cairo_path_fixed_fini (&path);
+    if (unlikely (status))
+	return status;
+
     cairo_p2d = pattern->base.matrix;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_FALLBACK) {
commit 665f5829541703b29e33f80bebf579a17f47a892
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 1 18:24:42 2009 +0100

    [ps/pdf] Trim patterns to operation extents
    
    If we have to rasterise a pattern for use by PS/PDF (for example, to
    satisfy CAIRO_EXTENT_PAD) then only generate an image large enough to
    cover the operation extents. We ensure tight coverage by computing the
    extents afresh - we could do this lazily in the future, but we can not
    rely on the bounds as computed by the analysis surface as for native
    operations they may not be tight.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 7601687..ac78f58 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1162,7 +1162,7 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t	*surface,
 static cairo_status_t
 _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t		*surface,
 				    const cairo_pattern_t	*pattern,
-				    cairo_clip_t		*clip,
+				    const cairo_rectangle_int_t	*extents,
 				    cairo_pdf_resource_t	*pattern_res,
 				    cairo_pdf_resource_t	*gstate_res)
 {
@@ -1221,8 +1221,8 @@ _cairo_pdf_surface_add_pdf_pattern (cairo_pdf_surface_t		*surface,
 
     pdf_pattern.width = surface->width;
     pdf_pattern.height = surface->height;
-    if (clip != NULL) {
-	pdf_pattern.extents = clip->path->extents;
+    if (extents != NULL) {
+	pdf_pattern.extents = *extents;
     } else {
 	pdf_pattern.extents.x = 0;
 	pdf_pattern.extents.y = 0;
@@ -5315,6 +5315,7 @@ _cairo_pdf_surface_paint (void			*abstract_surface,
     cairo_status_t status;
     cairo_pdf_smask_group_t *group;
     cairo_pdf_resource_t pattern_res, gstate_res;
+    cairo_rectangle_int_t extents;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
 	return _cairo_pdf_surface_analyze_operation (surface, op, source);
@@ -5347,9 +5348,15 @@ _cairo_pdf_surface_paint (void			*abstract_surface,
 	return _cairo_output_stream_get_status (surface->output);
     }
 
+    status = _cairo_surface_paint_extents (&surface->base,
+					   op, source, clip,
+					   &extents);
+    if (unlikely (status))
+	return status;
+
     pattern_res.id = 0;
     gstate_res.id = 0;
-    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, clip,
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &extents,
 						 &pattern_res, &gstate_res);
     if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
 	return CAIRO_STATUS_SUCCESS;
@@ -5512,6 +5519,7 @@ _cairo_pdf_surface_stroke (void			*abstract_surface,
     cairo_status_t status;
     cairo_pdf_smask_group_t *group;
     cairo_pdf_resource_t pattern_res, gstate_res;
+    cairo_rectangle_int_t extents;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return _cairo_pdf_surface_analyze_operation (surface, op, source);
@@ -5522,9 +5530,17 @@ _cairo_pdf_surface_stroke (void			*abstract_surface,
     if (unlikely (status))
 	return status;
 
+    status = _cairo_surface_stroke_extents (&surface->base,
+					    op, source, path,
+					    style, ctm, ctm_inverse,
+					    tolerance, antialias,
+					    clip, &extents);
+    if (unlikely (status))
+	return status;
+
     pattern_res.id = 0;
     gstate_res.id = 0;
-    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, clip,
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &extents,
 						 &pattern_res, &gstate_res);
     if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
 	return CAIRO_STATUS_SUCCESS;
@@ -5613,6 +5629,7 @@ _cairo_pdf_surface_fill (void			*abstract_surface,
     cairo_status_t status;
     cairo_pdf_smask_group_t *group;
     cairo_pdf_resource_t pattern_res, gstate_res;
+    cairo_rectangle_int_t extents;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE) {
 	return _cairo_pdf_surface_analyze_operation (surface, op, source);
@@ -5651,9 +5668,16 @@ _cairo_pdf_surface_fill (void			*abstract_surface,
 	return _cairo_output_stream_get_status (surface->output);
     }
 
+    status = _cairo_surface_fill_extents (&surface->base,
+					  op, source, path, fill_rule,
+					  tolerance, antialias,
+					  clip, &extents);
+    if (unlikely (status))
+	return status;
+
     pattern_res.id = 0;
     gstate_res.id = 0;
-    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, clip,
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &extents,
 						 &pattern_res, &gstate_res);
     if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
 	return CAIRO_STATUS_SUCCESS;
@@ -5740,6 +5764,7 @@ _cairo_pdf_surface_fill_stroke (void		     *abstract_surface,
     cairo_pdf_surface_t *surface = abstract_surface;
     cairo_status_t status;
     cairo_pdf_resource_t fill_pattern_res, stroke_pattern_res, gstate_res;
+    cairo_rectangle_int_t extents;
 
     /* During analysis we return unsupported and let the _fill and
      * _stroke functions that are on the fallback path do the analysis
@@ -5771,10 +5796,18 @@ _cairo_pdf_surface_fill_stroke (void		     *abstract_surface,
     if (unlikely (status))
 	return status;
 
+    status = _cairo_surface_fill_extents (&surface->base,
+					  fill_op, fill_source, path, fill_rule,
+					  fill_tolerance, fill_antialias,
+					  clip, &extents);
+    if (unlikely (status))
+	return status;
+
+
     fill_pattern_res.id = 0;
     gstate_res.id = 0;
     status = _cairo_pdf_surface_add_pdf_pattern (surface, fill_source,
-						 clip,
+						 &extents,
 						 &fill_pattern_res,
 						 &gstate_res);
     if (unlikely (status))
@@ -5782,11 +5815,19 @@ _cairo_pdf_surface_fill_stroke (void		     *abstract_surface,
 
     assert (gstate_res.id == 0);
 
+    status = _cairo_surface_stroke_extents (&surface->base,
+					    stroke_op, stroke_source, path,
+					    stroke_style, stroke_ctm, stroke_ctm_inverse,
+					    stroke_tolerance, stroke_antialias,
+					    clip, &extents);
+    if (unlikely (status))
+	return status;
+
     stroke_pattern_res.id = 0;
     gstate_res.id = 0;
     status = _cairo_pdf_surface_add_pdf_pattern (surface,
 						 stroke_source,
-						 clip,
+						 &extents,
 						 &stroke_pattern_res,
 						 &gstate_res);
     if (unlikely (status))
@@ -5846,6 +5887,7 @@ _cairo_pdf_surface_show_text_glyphs (void			*abstract_surface,
     cairo_status_t status;
     cairo_pdf_smask_group_t *group;
     cairo_pdf_resource_t pattern_res, gstate_res;
+    cairo_rectangle_int_t extents;
 
     if (surface->paginated_mode == CAIRO_PAGINATED_MODE_ANALYZE)
 	return _cairo_pdf_surface_analyze_operation (surface, op, source);
@@ -5856,9 +5898,16 @@ _cairo_pdf_surface_show_text_glyphs (void			*abstract_surface,
     if (unlikely (status))
 	return status;
 
+    status = _cairo_surface_glyphs_extents (&surface->base, op, source,
+					    glyphs, num_glyphs,
+					    scaled_font,
+					    clip, &extents);
+    if (unlikely (status))
+	return status;
+
     pattern_res.id = 0;
     gstate_res.id = 0;
-    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, clip,
+    status = _cairo_pdf_surface_add_pdf_pattern (surface, source, &extents,
 						 &pattern_res, &gstate_res);
     if (unlikely (status == CAIRO_INT_STATUS_NOTHING_TO_DO))
 	return CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 6f1bcfc..49d962b 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -2277,12 +2277,14 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t  *surface,
     double old_width, old_height;
     cairo_matrix_t old_cairo_to_ps;
     cairo_content_t old_content;
+    cairo_rectangle_int_t old_page_bbox;
     cairo_box_t bbox;
     cairo_status_t status;
 
     old_content = surface->content;
     old_width = surface->width;
     old_height = surface->height;
+    old_page_bbox = surface->page_bbox;
     old_cairo_to_ps = surface->cairo_to_ps;
 
     status =
@@ -2292,9 +2294,18 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t  *surface,
     if (unlikely (status))
 	return status;
 
-    /* XXX is this still necessary? */
+#if DEBUG_PS
+    _cairo_output_stream_printf (surface->stream,
+				 "%% _cairo_ps_surface_emit_meta_surface (%f, %f), (%f, %f)\n",
+				 _cairo_fixed_to_double (bbox.p1.x),
+				 _cairo_fixed_to_double (bbox.p1.y),
+				 _cairo_fixed_to_double (bbox.p2.x),
+				 _cairo_fixed_to_double (bbox.p2.y));
+#endif
+
     surface->width = _cairo_fixed_to_double (bbox.p2.x - bbox.p1.x);
     surface->height = _cairo_fixed_to_double (bbox.p2.y - bbox.p1.y);
+    _cairo_box_round_to_rectangle (&bbox, &surface->page_bbox);
 
     surface->current_pattern_is_solid_color = FALSE;
     _cairo_pdf_operators_reset (&surface->pdf_operators);
@@ -2325,6 +2336,7 @@ _cairo_ps_surface_emit_meta_surface (cairo_ps_surface_t  *surface,
     surface->content = old_content;
     surface->width = old_width;
     surface->height = old_height;
+    surface->page_bbox = old_page_bbox;
     surface->current_pattern_is_solid_color = FALSE;
     _cairo_pdf_operators_reset (&surface->pdf_operators);
     surface->cairo_to_ps = old_cairo_to_ps;
@@ -3235,21 +3247,6 @@ _cairo_ps_surface_get_font_options (void                  *abstract_surface,
     cairo_font_options_set_antialias (options, CAIRO_ANTIALIAS_GRAY);
 }
 
-static cairo_bool_t
-_rectangle_intersect_clip (cairo_rectangle_int_t *extents, cairo_clip_t *clip)
-{
-    const cairo_rectangle_int_t *clip_extents;
-
-    clip_extents = NULL;
-    if (clip != NULL)
-	clip_extents = _cairo_clip_get_extents (clip);
-
-    if (clip_extents != NULL)
-	return _cairo_rectangle_intersect (extents, clip_extents);
-
-    return TRUE;
-}
-
 static cairo_int_status_t
 _cairo_ps_surface_paint (void			*abstract_surface,
 			 cairo_operator_t	 op,
@@ -3271,8 +3268,13 @@ _cairo_ps_surface_paint (void			*abstract_surface,
 				 "%% _cairo_ps_surface_paint\n");
 #endif
 
-    extents = surface->page_bbox;
-    if (! _rectangle_intersect_clip (&extents, clip))
+    status = _cairo_surface_paint_extents (&surface->base,
+					   op, source, clip,
+					   &extents);
+    if (unlikely (status))
+	return status;
+
+    if (! _cairo_rectangle_intersect (&extents, &surface->page_bbox))
 	return CAIRO_STATUS_SUCCESS;
 
     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
@@ -3333,8 +3335,16 @@ _cairo_ps_surface_stroke (void			*abstract_surface,
 				 "%% _cairo_ps_surface_stroke\n");
 #endif
 
-    extents = surface->page_bbox;
-    if (! _rectangle_intersect_clip (&extents, clip))
+    status = _cairo_surface_stroke_extents (&surface->base,
+					    op, source,
+					    path, style,
+					    ctm, ctm_inverse,
+					    tolerance, antialias,
+					    clip, &extents);
+    if (unlikely (status))
+	return status;
+
+    if (! _cairo_rectangle_intersect (&extents, &surface->page_bbox))
 	return CAIRO_STATUS_SUCCESS;
 
     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
@@ -3379,14 +3389,21 @@ _cairo_ps_surface_fill (void		*abstract_surface,
 				 "%% _cairo_ps_surface_fill\n");
 #endif
 
-    extents = surface->page_bbox;
-    if (! _rectangle_intersect_clip (&extents, clip))
-	return CAIRO_STATUS_SUCCESS;
-
     status = _cairo_pdf_operators_flush (&surface->pdf_operators);
     if (unlikely (status))
 	return status;
 
+    status = _cairo_surface_fill_extents (&surface->base,
+					  op, source,
+					  path, fill_rule,
+					  tolerance, antialias,
+					  clip, &extents);
+    if (unlikely (status))
+	return status;
+
+    if (! _cairo_rectangle_intersect (&extents, &surface->page_bbox))
+	return CAIRO_STATUS_SUCCESS;
+
     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
     if (unlikely (status))
 	return status;
@@ -3454,8 +3471,15 @@ _cairo_ps_surface_show_glyphs (void		     *abstract_surface,
     if (num_glyphs <= 0)
         return CAIRO_STATUS_SUCCESS;
 
-    extents = surface->page_bbox;
-    if (! _rectangle_intersect_clip (&extents, clip))
+    status = _cairo_surface_glyphs_extents (&surface->base,
+					    op, source,
+					    glyphs, num_glyphs,
+					    scaled_font,
+					    clip, &extents);
+    if (unlikely (status))
+	return status;
+
+    if (! _cairo_rectangle_intersect (&extents, &surface->page_bbox))
 	return CAIRO_STATUS_SUCCESS;
 
     status = _cairo_surface_clipper_set_clip (&surface->clipper, clip);
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index 46abf25..6dab8e2 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -2841,6 +2841,168 @@ _cairo_surface_set_resolution (cairo_surface_t *surface,
     surface->y_resolution = y_res;
 }
 
+/* Generic methods for determining operation extents. */
+
+static void
+_rectangle_intersect_clip (cairo_rectangle_int_t *extents, cairo_clip_t *clip)
+{
+    const cairo_rectangle_int_t *clip_extents;
+    cairo_bool_t is_empty;
+
+    clip_extents = NULL;
+    if (clip != NULL)
+	clip_extents = _cairo_clip_get_extents (clip);
+
+    if (clip_extents != NULL)
+	is_empty = _cairo_rectangle_intersect (extents, clip_extents);
+}
+
+static void
+_cairo_surface_operation_extents (cairo_surface_t *surface,
+				  cairo_operator_t op,
+				  const cairo_pattern_t *source,
+				  cairo_clip_t *clip,
+				  cairo_rectangle_int_t *extents)
+{
+    cairo_bool_t is_empty;
+
+    is_empty = _cairo_surface_get_extents (surface, extents);
+
+    if (_cairo_operator_bounded_by_source (op)) {
+	cairo_rectangle_int_t source_extents;
+
+	_cairo_pattern_get_extents (source, &source_extents);
+	is_empty = _cairo_rectangle_intersect (extents, &source_extents);
+    }
+
+    _rectangle_intersect_clip (extents, clip);
+}
+
+cairo_status_t
+_cairo_surface_paint_extents (cairo_surface_t *surface,
+			      cairo_operator_t		op,
+			      const cairo_pattern_t	*source,
+			      cairo_clip_t		*clip,
+			      cairo_rectangle_int_t	*extents)
+{
+    _cairo_surface_operation_extents (surface, op, source, clip, extents);
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_surface_mask_extents (cairo_surface_t *surface,
+			     cairo_operator_t		 op,
+			     const cairo_pattern_t	*source,
+			     const cairo_pattern_t	*mask,
+			     cairo_clip_t		*clip,
+			     cairo_rectangle_int_t	*extents)
+{
+    cairo_bool_t is_empty;
+
+    _cairo_surface_operation_extents (surface, op, source, clip, extents);
+
+    if (_cairo_operator_bounded_by_mask (op)) {
+	cairo_rectangle_int_t mask_extents;
+
+	_cairo_pattern_get_extents (mask, &mask_extents);
+	is_empty = _cairo_rectangle_intersect (extents, &mask_extents);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_surface_stroke_extents (cairo_surface_t *surface,
+			       cairo_operator_t op,
+			       const cairo_pattern_t *source,
+			       cairo_path_fixed_t	*path,
+			       cairo_stroke_style_t *style,
+			       const cairo_matrix_t *ctm,
+			       const cairo_matrix_t *ctm_inverse,
+			       double tolerance,
+			       cairo_antialias_t	 antialias,
+			       cairo_clip_t *clip,
+			       cairo_rectangle_int_t *extents)
+{
+    cairo_status_t status;
+    cairo_bool_t is_empty;
+
+    _cairo_surface_operation_extents (surface, op, source, clip, extents);
+
+    if (_cairo_operator_bounded_by_mask (op)) {
+	cairo_rectangle_int_t mask_extents;
+
+	status = _cairo_path_fixed_stroke_extents (path, style,
+						   ctm, ctm_inverse,
+						   tolerance,
+						   &mask_extents);
+	if (unlikely (status))
+	    return status;
+
+	is_empty = _cairo_rectangle_intersect (extents, &mask_extents);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_surface_fill_extents (cairo_surface_t		*surface,
+			     cairo_operator_t		 op,
+			     const cairo_pattern_t	*source,
+			     cairo_path_fixed_t		*path,
+			     cairo_fill_rule_t		 fill_rule,
+			     double			 tolerance,
+			     cairo_antialias_t		 antialias,
+			     cairo_clip_t		*clip,
+			     cairo_rectangle_int_t	*extents)
+{
+    cairo_bool_t is_empty;
+
+    _cairo_surface_operation_extents (surface, op, source, clip, extents);
+
+    if (_cairo_operator_bounded_by_mask (op)) {
+	cairo_rectangle_int_t mask_extents;
+
+	_cairo_path_fixed_fill_extents (path, fill_rule, tolerance,
+					&mask_extents);
+	is_empty = _cairo_rectangle_intersect (extents, &mask_extents);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
+cairo_status_t
+_cairo_surface_glyphs_extents (cairo_surface_t *surface,
+			       cairo_operator_t	   op,
+			       const cairo_pattern_t *source,
+			       cairo_glyph_t	  *glyphs,
+			       int		   num_glyphs,
+			       cairo_scaled_font_t  *scaled_font,
+			       cairo_clip_t         *clip,
+			       cairo_rectangle_int_t *extents)
+{
+    cairo_status_t	     status;
+    cairo_bool_t             is_empty;
+
+    _cairo_surface_operation_extents (surface, op, source, clip, extents);
+
+    if (_cairo_operator_bounded_by_mask (op)) {
+	cairo_rectangle_int_t glyph_extents;
+
+	status = _cairo_scaled_font_glyph_device_extents (scaled_font,
+							  glyphs,
+							  num_glyphs,
+							  &glyph_extents,
+							  NULL);
+	if (unlikely (status))
+	    return status;
+
+	is_empty = _cairo_rectangle_intersect (extents, &glyph_extents);
+    }
+
+    return CAIRO_STATUS_SUCCESS;
+}
+
 cairo_surface_t *
 _cairo_surface_create_in_error (cairo_status_t status)
 {
diff --git a/src/cairoint.h b/src/cairoint.h
index d0e3409..f6a4559 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -1950,6 +1950,55 @@ _cairo_surface_show_text_glyphs (cairo_surface_t	    *surface,
 				 cairo_clip_t		    *clip);
 
 cairo_private cairo_status_t
+_cairo_surface_paint_extents (cairo_surface_t *surface,
+			      cairo_operator_t		op,
+			      const cairo_pattern_t	*source,
+			      cairo_clip_t		*clip,
+			      cairo_rectangle_int_t	*extents);
+
+cairo_private cairo_status_t
+_cairo_surface_mask_extents (cairo_surface_t *surface,
+			     cairo_operator_t		 op,
+			     const cairo_pattern_t	*source,
+			     const cairo_pattern_t	*mask,
+			     cairo_clip_t		*clip,
+			     cairo_rectangle_int_t	*extents);
+
+cairo_private cairo_status_t
+_cairo_surface_stroke_extents (cairo_surface_t *surface,
+			       cairo_operator_t op,
+			       const cairo_pattern_t *source,
+			       cairo_path_fixed_t	*path,
+			       cairo_stroke_style_t *style,
+			       const cairo_matrix_t *ctm,
+			       const cairo_matrix_t *ctm_inverse,
+			       double tolerance,
+			       cairo_antialias_t	 antialias,
+			       cairo_clip_t *clip,
+			       cairo_rectangle_int_t *extents);
+
+cairo_private cairo_status_t
+_cairo_surface_fill_extents (cairo_surface_t		*surface,
+			     cairo_operator_t		 op,
+			     const cairo_pattern_t	*source,
+			     cairo_path_fixed_t		*path,
+			     cairo_fill_rule_t		 fill_rule,
+			     double			 tolerance,
+			     cairo_antialias_t		 antialias,
+			     cairo_clip_t		*clip,
+			     cairo_rectangle_int_t	*extents);
+
+cairo_private cairo_status_t
+_cairo_surface_glyphs_extents (cairo_surface_t *surface,
+			       cairo_operator_t	   op,
+			       const cairo_pattern_t *source,
+			       cairo_glyph_t	  *glyphs,
+			       int		   num_glyphs,
+			       cairo_scaled_font_t  *scaled_font,
+			       cairo_clip_t         *clip,
+			       cairo_rectangle_int_t *extents);
+
+cairo_private cairo_status_t
 _cairo_surface_composite_trapezoids (cairo_operator_t	op,
 				     const cairo_pattern_t *pattern,
 				     cairo_surface_t	*dst,
commit c4c7db96750337076b953a4938afc7b5f16815fc
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 1 14:59:36 2009 +0100

    [boilerplate] Use xlib as fallback reference for xcb
    
    And exercise RGB code-paths.

diff --git a/boilerplate/cairo-boilerplate-xcb.c b/boilerplate/cairo-boilerplate-xcb.c
index 0653d8c..e8996fa 100644
--- a/boilerplate/cairo-boilerplate-xcb.c
+++ b/boilerplate/cairo-boilerplate-xcb.c
@@ -117,7 +117,7 @@ static const cairo_boilerplate_target_t targets[] = {
     /* Acceleration architectures may make the results differ by a
      * bit, so we set the error tolerance to 1. */
     {
-	"xcb", "xcb", NULL, NULL,
+	"xcb", "xlib", NULL, NULL,
 	CAIRO_SURFACE_TYPE_XCB, CAIRO_CONTENT_COLOR_ALPHA, 1,
 	"cairo_xcb_surface_create_with_xrender_format",
 	_cairo_boilerplate_xcb_create_surface,
@@ -127,5 +127,16 @@ static const cairo_boilerplate_target_t targets[] = {
 	_cairo_boilerplate_xcb_cleanup,
 	_cairo_boilerplate_xcb_synchronize
     },
+    {
+	"xcb", "xlib", NULL, NULL,
+	CAIRO_SURFACE_TYPE_XCB, CAIRO_CONTENT_COLOR, 1,
+	"cairo_xcb_surface_create_with_xrender_format",
+	_cairo_boilerplate_xcb_create_surface,
+	NULL, NULL,
+	_cairo_boilerplate_get_image_surface,
+	cairo_surface_write_to_png,
+	_cairo_boilerplate_xcb_cleanup,
+	_cairo_boilerplate_xcb_synchronize
+    },
 };
 CAIRO_BOILERPLATE (xcb, targets)
commit e7a118d3f82f2cbefb4a1529cc90f76ed7371ecc
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 1 14:31:38 2009 +0100

    [path] Standalone header-compilation
    
    Hmm, TRUE/FALSE apparently weren't defined before use. Odd.

diff --git a/src/cairo-path-fixed-private.h b/src/cairo-path-fixed-private.h
index ce35c9e..08b7a06 100644
--- a/src/cairo-path-fixed-private.h
+++ b/src/cairo-path-fixed-private.h
@@ -139,10 +139,10 @@ static inline cairo_bool_t
 _cairo_path_fixed_is_rectilinear_fill (const cairo_path_fixed_t *path)
 {
     if (! path->is_rectilinear)
-	return FALSE;
+	return 0;
 
     if (! path->has_current_point)
-	return TRUE;
+	return 1;
 
     /* check whether the implicit close preserves the rectilinear property */
     return path->current_point.x == path->last_move_point.x ||
commit 4f880deeabc36842b3b4b0d7ad16383db708cd42
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 1 14:24:59 2009 +0100

    Compiler warnings
    
    Add an impossible default condition to avoid a compiler warning. And tweak
    the code to avoid mismatching signed/unsigned comparisons.

diff --git a/src/cairo-pdf-surface.c b/src/cairo-pdf-surface.c
index 6fa6133..7601687 100644
--- a/src/cairo-pdf-surface.c
+++ b/src/cairo-pdf-surface.c
@@ -1099,6 +1099,7 @@ _cairo_pdf_surface_add_source_surface (cairo_pdf_surface_t	*surface,
     cairo_bool_t interpolate;
 
     switch (filter) {
+    default:
     case CAIRO_FILTER_GOOD:
     case CAIRO_FILTER_BEST:
     case CAIRO_FILTER_BILINEAR:
diff --git a/src/cairo-xml-surface.c b/src/cairo-xml-surface.c
index ec4d3fd..61e8f61 100644
--- a/src/cairo-xml-surface.c
+++ b/src/cairo-xml-surface.c
@@ -266,7 +266,7 @@ _cairo_xml_printf (cairo_xml_t *xml, const char *fmt, ...)
     char indent[80];
     int len;
 
-    len = MIN (xml->indent, sizeof (indent));
+    len = MIN (xml->indent, ARRAY_LENGTH (indent));
     memset (indent, ' ', len);
     _cairo_output_stream_write (xml->stream, indent, len);
 
@@ -283,7 +283,7 @@ _cairo_xml_printf_start (cairo_xml_t *xml, const char *fmt, ...)
     char indent[80];
     int len;
 
-    len = MIN (xml->indent, sizeof (indent));
+    len = MIN (xml->indent, ARRAY_LENGTH (indent));
     memset (indent, ' ', len);
     _cairo_output_stream_write (xml->stream, indent, len);
 
@@ -535,7 +535,7 @@ static void
 _cairo_xml_emit_gradient (cairo_xml_t *xml,
 			  const cairo_gradient_pattern_t *gradient)
 {
-    int i;
+    unsigned int i;
 
     for (i = 0; i < gradient->n_stops; i++) {
 	_cairo_xml_printf (xml,
@@ -784,7 +784,7 @@ _cairo_xml_surface_stroke (void				*abstract_surface,
 	return status;
 
     if (style->num_dashes) {
-	int i;
+	unsigned int i;
 
 	_cairo_xml_printf_start (xml, "<dash offset='%f'>",
 				 style->dash_offset);
commit 1bcc3a3fa00445667adc47d4852237271c7eec0f
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 1 14:24:06 2009 +0100

    [tee] Rename 'append' to 'add' and add symmetric 'remove'

diff --git a/src/cairo-tee-surface.c b/src/cairo-tee-surface.c
index 0a7842f..56f3cc2 100644
--- a/src/cairo-tee-surface.c
+++ b/src/cairo-tee-surface.c
@@ -51,7 +51,7 @@ typedef struct _cairo_tee_surface {
 } cairo_tee_surface_t;
 
 slim_hidden_proto (cairo_tee_surface_create);
-slim_hidden_proto (cairo_tee_surface_append);
+slim_hidden_proto (cairo_tee_surface_add);
 
 static cairo_surface_t *
 _cairo_tee_surface_create_similar (void			*abstract_surface,
@@ -80,7 +80,7 @@ _cairo_tee_surface_create_similar (void			*abstract_surface,
 	similar = _cairo_surface_wrapper_create_similar (&slaves[n],
 							 content,
 							 width, height);
-	cairo_tee_surface_append (surface, similar);
+	cairo_tee_surface_add (surface, similar);
 	cairo_surface_destroy (similar);
     }
 
@@ -457,8 +457,8 @@ cairo_tee_surface_create (cairo_surface_t *master)
 slim_hidden_def (cairo_tee_surface_create);
 
 void
-cairo_tee_surface_append (cairo_surface_t *abstract_surface,
-			  cairo_surface_t *target)
+cairo_tee_surface_add (cairo_surface_t *abstract_surface,
+		       cairo_surface_t *target)
 {
     cairo_tee_surface_t *surface;
     cairo_surface_wrapper_t slave;
@@ -487,7 +487,48 @@ cairo_tee_surface_append (cairo_surface_t *abstract_surface,
 	status = _cairo_surface_set_error (&surface->base, status);
     }
 }
-slim_hidden_def (cairo_tee_surface_append);
+slim_hidden_def (cairo_tee_surface_add);
+
+void
+cairo_tee_surface_remove (cairo_surface_t *abstract_surface,
+			  cairo_surface_t *target)
+{
+    cairo_tee_surface_t *surface;
+    cairo_surface_wrapper_t *slaves;
+    int n, num_slaves;
+    cairo_status_t status;
+
+    if (abstract_surface->backend != &cairo_tee_surface_backend) {
+	status = _cairo_surface_set_error (abstract_surface,
+					   _cairo_error (CAIRO_STATUS_SURFACE_TYPE_MISMATCH));
+	return;
+    }
+
+    surface = (cairo_tee_surface_t *) abstract_surface;
+    if (target == surface->master.target) {
+	status = _cairo_surface_set_error (abstract_surface,
+					   _cairo_error (CAIRO_STATUS_INVALID_INDEX));
+	return;
+    }
+
+    num_slaves = _cairo_array_num_elements (&surface->slaves);
+    slaves = _cairo_array_index (&surface->slaves, 0);
+    for (n = 0; n < num_slaves; n++) {
+	if (slaves[n].target == target)
+	    break;
+    }
+
+    if (n == num_slaves) {
+	status = _cairo_surface_set_error (abstract_surface,
+					   _cairo_error (CAIRO_STATUS_INVALID_INDEX));
+	return;
+    }
+
+    _cairo_surface_wrapper_fini (&slaves[n]);
+    for (n++; n < num_slaves; n++)
+	slaves[n-1] = slaves[n];
+    surface->slaves.num_elements--; /* XXX: cairo_array_remove()? */
+}
 
 cairo_surface_t *
 cairo_tee_surface_index (cairo_surface_t *abstract_surface,
diff --git a/src/cairo.h b/src/cairo.h
index a046a47..3b5eb36 100644
--- a/src/cairo.h
+++ b/src/cairo.h
@@ -2199,11 +2199,15 @@ cairo_public cairo_surface_t *
 cairo_tee_surface_create (cairo_surface_t *master);
 
 cairo_public void
-cairo_tee_surface_append (cairo_surface_t *surface,
+cairo_tee_surface_add (cairo_surface_t *surface,
+		       cairo_surface_t *target);
+
+cairo_public void
+cairo_tee_surface_remove (cairo_surface_t *surface,
 			  cairo_surface_t *target);
 
 cairo_public cairo_surface_t *
-cairo_tee_surface_index (cairo_surface_t *abstract_surface,
+cairo_tee_surface_index (cairo_surface_t *surface,
 			 int index);
 
 /* Pattern creation functions */
diff --git a/util/cairo-fdr/fdr.c b/util/cairo-fdr/fdr.c
index 4675473..9890024 100644
--- a/util/cairo-fdr/fdr.c
+++ b/util/cairo-fdr/fdr.c
@@ -164,7 +164,7 @@ cairo_create (cairo_surface_t *surface)
 
 	tee = DLCALL (cairo_tee_surface_create, surface);
 	record = DLCALL (cairo_meta_surface_create, content, &extents);
-	DLCALL (cairo_tee_surface_append, tee, record);
+	DLCALL (cairo_tee_surface_add, tee, record);
 
 	DLCALL (cairo_surface_set_user_data, surface,
 		&fdr_key, tee, fdr_surface_destroy);
diff --git a/util/cairo-sphinx/fdr.c b/util/cairo-sphinx/fdr.c
index 993baba..9c66608 100644
--- a/util/cairo-sphinx/fdr.c
+++ b/util/cairo-sphinx/fdr.c
@@ -136,7 +136,7 @@ cairo_create (cairo_surface_t *surface)
 	tee = DLCALL (cairo_tee_surface_create, surface);
 	script = DLCALL (cairo_script_surface_create,
 			 fdr_context, content, extents.width, extents.height);
-	DLCALL (cairo_tee_surface_append, tee, script);
+	DLCALL (cairo_tee_surface_add, tee, script);
 
 	DLCALL (cairo_surface_set_user_data, surface,
 		&fdr_key, tee, fdr_surface_destroy);
commit af82670dd3bfdb661de5a01a6856ec01bdf80040
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Tue Sep 1 13:31:52 2009 +0100

    [pattern] Remove unused hidden symbol for cairo_pattern_status()

diff --git a/src/cairo-pattern.c b/src/cairo-pattern.c
index 149cdc7..727b80e 100644
--- a/src/cairo-pattern.c
+++ b/src/cairo-pattern.c
@@ -486,7 +486,7 @@ _freed_pattern_get (freed_pool_t *pool)
 	i = 0;
 
     pattern = _atomic_fetch (&pool->pool[i]);
-    if (pattern != NULL) {
+    if (likely (pattern != NULL)) {
 	pool->top = i;
 	return pattern;
     }
@@ -511,8 +511,8 @@ _freed_pattern_put (freed_pool_t *pool,
 {
     int i = pool->top;
 
-    if (i < ARRAY_LENGTH (pool->pool) &&
-	_atomic_store (&pool->pool[i], pattern))
+    if (likely (i < ARRAY_LENGTH (pool->pool) &&
+		_atomic_store (&pool->pool[i], pattern)))
     {
 	pool->top = i + 1;
 	return;
@@ -549,7 +549,7 @@ cairo_pattern_t *
 _cairo_pattern_create_solid (const cairo_color_t *color,
 			     cairo_content_t	  content)
 {
-    cairo_solid_pattern_t *pattern = NULL;
+    cairo_solid_pattern_t *pattern;
 
     pattern =
 	_freed_pattern_get (&freed_pattern_pool[CAIRO_PATTERN_TYPE_SOLID]);
@@ -870,7 +870,6 @@ cairo_pattern_status (cairo_pattern_t *pattern)
 {
     return pattern->status;
 }
-slim_hidden_def (cairo_pattern_status);
 
 /**
  * cairo_pattern_destroy:
diff --git a/src/cairoint.h b/src/cairoint.h
index 7d2812b..d0e3409 100644
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -2668,7 +2668,6 @@ slim_hidden_proto (cairo_pattern_destroy);
 slim_hidden_proto (cairo_pattern_get_extend);
 slim_hidden_proto_no_warn (cairo_pattern_reference);
 slim_hidden_proto (cairo_pattern_set_matrix);
-slim_hidden_proto (cairo_pattern_status);
 slim_hidden_proto (cairo_pop_group);
 slim_hidden_proto (cairo_push_group_with_content);
 slim_hidden_proto (cairo_rel_line_to);


More information about the cairo-commit mailing list