[cairo-commit] Branch '1.8' - 3 commits - AUTHORS perf/cairo-perf-diff src/cairo-gstate.c src/cairo-xcb-surface.c

Chris Wilson ickle at kemper.freedesktop.org
Sun Dec 14 03:15:03 PST 2008


 AUTHORS                 |    1 
 perf/cairo-perf-diff    |    2 
 src/cairo-gstate.c      |  223 +++++++++++++++++++++++++++++++++++++-----------
 src/cairo-xcb-surface.c |    8 +
 4 files changed, 184 insertions(+), 50 deletions(-)

New commits:
commit 79bd32a6ccb1a882ddd2b1585ab155f568bf5ec7
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Sat Dec 6 13:32:37 2008 +0200

    [perf-diff] Fix cairo-perf-diff for git 1.6
    
    Since git 1.6 the plumbing commands aren't installed in the user's
    path by default.  This patch fixes cairo-perf-diff to find the
    git-sh-setup command from git's lib dir.
    (cherry picked from commit 0c0f4862c52d68776024f125b003ade455044b27)

diff --git a/perf/cairo-perf-diff b/perf/cairo-perf-diff
index 50cd1f2..718cdc5 100755
--- a/perf/cairo-perf-diff
+++ b/perf/cairo-perf-diff
@@ -89,7 +89,7 @@ fi
 
 git_setup() {
     SUBDIRECTORY_OK='Yes'
-    . git-sh-setup
+    . "$(git --exec-path)/git-sh-setup"
     CAIRO_DIR=`dirname $GIT_DIR`
     if [ "$CAIRO_DIR" = "." ]; then
 	CAIRO_DIR=`pwd`
commit 97b5240beeb9206f4dbda6ffce33b51aa16eec2f
Author: Julien Danjou <julien at danjou.info>
Date:   Tue Nov 18 10:01:49 2008 +0100

    [xcb] check for render extension presence
    
    Otherwise this may leads to an invalid memory access to r.
    
    Fixes: Bug 18588 - XCB backend fails with missing render.
    https://bugs.freedesktop.org/show_bug.cgi?id=18588
    
    Signed-off-by: Julien Danjou <julien at danjou.info>
    Signed-off-by: Chris Wilson <chris at chris-wilson.co.uk>
    (cherry picked from commit 834f1d7b7097dcc3a32f6c65d21e87fd272d924a)

diff --git a/AUTHORS b/AUTHORS
index 488f4c0..289fecb 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -16,6 +16,7 @@ Steve Chaplin <stevech1097 at yahoo.com.au> Bug fixes for PNG reading
 Tomasz Cholewo <cholewo at ieee-cis.org> Bug fixes
 Manu Cornet <manu at manucornet.net> SVG build fix
 Frederic Crozat <fcrozat at mandriva.com> Fix test suite for OPD platforms (IA64 or PPC64)
+Julien Danjou <julien at danjou.info> XCB fixes
 Radek Doulík <rodo at novell.com> Bug report and test case
 John Ehresman <jpe at wingide.com> Build fixes for win32
 John Ellson <ellson at research.att.com> First font/glyph extents functions
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index 9b7eb4b..c63e851 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -1732,7 +1732,8 @@ _cairo_xcb_surface_create_internal (xcb_connection_t	     *dpy,
 				    int			      depth)
 {
     cairo_xcb_surface_t *surface;
-    const xcb_render_query_version_reply_t *r;
+    const xcb_query_extension_reply_t *er;
+    const xcb_render_query_version_reply_t *r = NULL;
 
     surface = malloc (sizeof (cairo_xcb_surface_t));
     if (surface == NULL)
@@ -1764,7 +1765,10 @@ _cairo_xcb_surface_create_internal (xcb_connection_t	     *dpy,
 	;
     }
 
-    r = xcb_render_util_query_version(dpy);
+    er = xcb_get_extension_data(dpy, &xcb_render_id);
+    if(er && er->present) {
+	r = xcb_render_util_query_version(dpy);
+    }
     if (r) {
 	surface->render_major = r->major_version;
 	surface->render_minor = r->minor_version;
commit 6fed98c0d3b0708ad5171654179a482fa7d88805
Author: Chris Wilson <chris at chris-wilson.co.uk>
Date:   Fri Dec 5 21:14:45 2008 +0000

    [gstate] Remove culled glyphs from clusters.
    
    Sascha Steinbiss reported a bug where the PDF backend was reading beyond
    the end of the glyph array:
    http://lists.cairographics.org/archives/cairo/2008-December/015976.html.
    
    It transpires that in the early glyph culling in the gstate we were
    not updating the clusters to skip culled glyphs.

diff --git a/src/cairo-gstate.c b/src/cairo-gstate.c
index fe8d279..28a9538 100644
--- a/src/cairo-gstate.c
+++ b/src/cairo-gstate.c
@@ -64,8 +64,12 @@ static cairo_status_t
 _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
                                            const cairo_glyph_t *glyphs,
                                            int                  num_glyphs,
+					   const cairo_text_cluster_t	*clusters,
+					   int			 num_clusters,
+					   cairo_text_cluster_flags_t cluster_flags,
                                            cairo_glyph_t       *transformed_glyphs,
-					   int		       *num_transformed_glyphs);
+					   int			*num_transformed_glyphs,
+					   cairo_text_cluster_t *transformed_clusters);
 
 cairo_status_t
 _cairo_gstate_init (cairo_gstate_t  *gstate,
@@ -1581,10 +1585,12 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 				int			    num_clusters,
 				cairo_text_cluster_flags_t  cluster_flags)
 {
-    cairo_status_t status;
     cairo_pattern_union_t source_pattern;
-    cairo_glyph_t *transformed_glyphs;
     cairo_glyph_t stack_transformed_glyphs[CAIRO_STACK_ARRAY_LENGTH (cairo_glyph_t)];
+    cairo_glyph_t *transformed_glyphs;
+    cairo_text_cluster_t stack_transformed_clusters[CAIRO_STACK_ARRAY_LENGTH (cairo_text_cluster_t)];
+    cairo_text_cluster_t *transformed_clusters;
+    cairo_status_t status;
 
     if (gstate->source->status)
 	return gstate->source->status;
@@ -1597,18 +1603,37 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
     if (status)
 	return status;
 
-    if (num_glyphs <= ARRAY_LENGTH (stack_transformed_glyphs)) {
-	transformed_glyphs = stack_transformed_glyphs;
-    } else {
+    transformed_glyphs = stack_transformed_glyphs;
+    transformed_clusters = stack_transformed_clusters;
+
+    if (num_glyphs > ARRAY_LENGTH (stack_transformed_glyphs)) {
 	transformed_glyphs = cairo_glyph_allocate (num_glyphs);
-	if (transformed_glyphs == NULL)
-	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	if (transformed_glyphs == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto CLEANUP_GLYPHS;
+	}
+    }
+
+    /* Just in case */
+    if (!clusters)
+	num_clusters = 0;
+
+    if (num_clusters > ARRAY_LENGTH (stack_transformed_clusters)) {
+	transformed_clusters = cairo_text_cluster_allocate (num_clusters);
+	if (transformed_clusters == NULL) {
+	    status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
+	    goto CLEANUP_GLYPHS;
+	}
     }
 
     status = _cairo_gstate_transform_glyphs_to_backend (gstate,
 							glyphs, num_glyphs,
+							clusters,
+							num_clusters,
+							cluster_flags,
 							transformed_glyphs,
-							&num_glyphs);
+							&num_glyphs,
+							transformed_clusters);
 
     if (status || num_glyphs == 0)
 	goto CLEANUP_GLYPHS;
@@ -1617,10 +1642,6 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
     if (status)
 	goto CLEANUP_GLYPHS;
 
-    /* Just in case */
-    if (!clusters)
-	num_clusters = 0;
-
     /* For really huge font sizes, we can just do path;fill instead of
      * show_glyphs, as show_glyphs would put excess pressure on the cache,
      * and moreover, not all components below us correctly handle huge font
@@ -1638,7 +1659,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 						  &source_pattern.base,
 						  utf8, utf8_len,
 						  transformed_glyphs, num_glyphs,
-						  clusters, num_clusters,
+						  transformed_clusters, num_clusters,
 						  cluster_flags,
 						  gstate->scaled_font);
     } else {
@@ -1667,6 +1688,8 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t		   *gstate,
 CLEANUP_GLYPHS:
     if (transformed_glyphs != stack_transformed_glyphs)
       cairo_glyph_free (transformed_glyphs);
+    if (transformed_clusters != stack_transformed_clusters)
+      cairo_text_cluster_free (transformed_clusters);
 
     return status;
 }
@@ -1694,8 +1717,9 @@ _cairo_gstate_glyph_path (cairo_gstate_t      *gstate,
 
     status = _cairo_gstate_transform_glyphs_to_backend (gstate,
 							glyphs, num_glyphs,
+							NULL, 0, 0,
 							transformed_glyphs,
-							NULL);
+							NULL, NULL);
     if (status)
 	goto CLEANUP_GLYPHS;
 
@@ -1744,13 +1768,17 @@ _cairo_gstate_get_antialias (cairo_gstate_t *gstate)
  * cull/drop glyphs that will not be visible.
  **/
 static cairo_status_t
-_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
-                                           const cairo_glyph_t *glyphs,
-                                           int                  num_glyphs,
-                                           cairo_glyph_t       *transformed_glyphs,
-					   int		       *num_transformed_glyphs)
-{
-    int i, j;
+_cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t	*gstate,
+                                           const cairo_glyph_t	*glyphs,
+                                           int			 num_glyphs,
+					   const cairo_text_cluster_t	*clusters,
+					   int			 num_clusters,
+					   cairo_text_cluster_flags_t cluster_flags,
+                                           cairo_glyph_t	*transformed_glyphs,
+					   int			*num_transformed_glyphs,
+					   cairo_text_cluster_t *transformed_clusters)
+{
+    int i, j, k;
     cairo_matrix_t *ctm = &gstate->ctm;
     cairo_matrix_t *font_matrix = &gstate->font_matrix;
     cairo_matrix_t *device_transform = &gstate->target->device_transform;
@@ -1796,22 +1824,52 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
 
 #define KEEP_GLYPH(glyph) (x1 <= glyph.x && glyph.x <= x2 && y1 <= glyph.y && glyph.y <= y2)
 
+    j = 0;
     if (_cairo_matrix_is_identity (ctm) &&
         _cairo_matrix_is_identity (device_transform) &&
 	font_matrix->x0 == 0 && font_matrix->y0 == 0)
     {
-	if (!drop)
-	    memcpy (transformed_glyphs, glyphs, num_glyphs * sizeof (cairo_glyph_t));
-	else {
-	    for (j = 0, i = 0; i < num_glyphs; i++)
-	    {
+	if (! drop) {
+	    memcpy (transformed_glyphs, glyphs,
+		    num_glyphs * sizeof (cairo_glyph_t));
+	} else if (num_clusters == 0) {
+	    for (i = 0; i < num_glyphs; i++) {
 		transformed_glyphs[j].index = glyphs[i].index;
 		transformed_glyphs[j].x = glyphs[i].x;
 		transformed_glyphs[j].y = glyphs[i].y;
 		if (KEEP_GLYPH (transformed_glyphs[j]))
 		    j++;
 	    }
-	    *num_transformed_glyphs = j;
+	} else {
+	    const cairo_glyph_t *cur_glyph;
+
+	    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
+		cur_glyph = glyphs + num_glyphs - 1;
+	    else
+		cur_glyph = glyphs;
+
+	    for (i = 0; i < num_clusters; i++) {
+		cairo_bool_t cluster_visible = FALSE;
+
+		for (k = 0; k < clusters[i].num_glyphs; k++) {
+		    transformed_glyphs[j+k].index = cur_glyph->index;
+		    transformed_glyphs[j+k].x = cur_glyph->x;
+		    transformed_glyphs[j+k].y = cur_glyph->y;
+		    if (KEEP_GLYPH (transformed_glyphs[j+k]))
+			cluster_visible = TRUE;
+
+		    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
+			cur_glyph--;
+		    else
+			cur_glyph++;
+		}
+
+		transformed_clusters[i] = clusters[i];
+		if (cluster_visible)
+		    j += k;
+		else
+		    transformed_clusters[i].num_glyphs = 0;
+	    }
 	}
     }
     else if (_cairo_matrix_is_translation (ctm) &&
@@ -1820,15 +1878,45 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
         double tx = font_matrix->x0 + ctm->x0 + device_transform->x0;
         double ty = font_matrix->y0 + ctm->y0 + device_transform->y0;
 
-        for (j = 0, i = 0; i < num_glyphs; i++)
-        {
-            transformed_glyphs[j].index = glyphs[i].index;
-            transformed_glyphs[j].x = glyphs[i].x + tx;
-            transformed_glyphs[j].y = glyphs[i].y + ty;
-	    if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
-		j++;
-        }
-	*num_transformed_glyphs = j;
+	if (! drop || num_clusters == 0) {
+	    for (i = 0; i < num_glyphs; i++) {
+		transformed_glyphs[j].index = glyphs[i].index;
+		transformed_glyphs[j].x = glyphs[i].x + tx;
+		transformed_glyphs[j].y = glyphs[i].y + ty;
+		if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
+		    j++;
+	    }
+	} else {
+	    const cairo_glyph_t *cur_glyph;
+
+	    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
+		cur_glyph = glyphs + num_glyphs - 1;
+	    else
+		cur_glyph = glyphs;
+
+	    for (i = 0; i < num_clusters; i++) {
+		cairo_bool_t cluster_visible = FALSE;
+
+		for (k = 0; k < clusters[i].num_glyphs; k++) {
+		    transformed_glyphs[j+k].index = cur_glyph->index;
+		    transformed_glyphs[j+k].x = cur_glyph->x + tx;
+		    transformed_glyphs[j+k].y = cur_glyph->y + ty;
+		    if (KEEP_GLYPH (transformed_glyphs[j+k]))
+			cluster_visible = TRUE;
+
+		    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
+			cur_glyph--;
+		    else
+			cur_glyph++;
+		}
+
+		transformed_clusters[i] = clusters[i];
+		if (cluster_visible)
+		    j += k;
+		else
+		    transformed_clusters[i].num_glyphs = 0;
+	    }
+	}
     }
     else
     {
@@ -1842,16 +1930,57 @@ _cairo_gstate_transform_glyphs_to_backend (cairo_gstate_t      *gstate,
         cairo_matrix_multiply (&aggregate_transform,
                                &aggregate_transform, device_transform);
 
-        for (j = 0, i = 0; i < num_glyphs; i++)
-        {
-            transformed_glyphs[j] = glyphs[i];
-            cairo_matrix_transform_point (&aggregate_transform,
-                                          &transformed_glyphs[j].x,
-                                          &transformed_glyphs[j].y);
-	    if (!drop || KEEP_GLYPH (transformed_glyphs[j]))
-		j++;
-        }
-	*num_transformed_glyphs = j;
+	if (! drop || num_clusters == 0) {
+	    for (i = 0; i < num_glyphs; i++) {
+		transformed_glyphs[j] = glyphs[i];
+		cairo_matrix_transform_point (&aggregate_transform,
+					      &transformed_glyphs[j].x,
+					      &transformed_glyphs[j].y);
+		if (! drop || KEEP_GLYPH (transformed_glyphs[j]))
+		    j++;
+	    }
+	} else {
+	    const cairo_glyph_t *cur_glyph;
+
+	    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
+		cur_glyph = glyphs + num_glyphs - 1;
+	    else
+		cur_glyph = glyphs;
+
+	    for (i = 0; i < num_clusters; i++) {
+		cairo_bool_t cluster_visible = FALSE;
+		for (k = 0; k < clusters[i].num_glyphs; k++) {
+		    transformed_glyphs[j+k] = *cur_glyph;
+		    cairo_matrix_transform_point (&aggregate_transform,
+						  &transformed_glyphs[j+k].x,
+						  &transformed_glyphs[j+k].y);
+		    if (KEEP_GLYPH (transformed_glyphs[j+k]))
+			cluster_visible = TRUE;
+
+		    if (cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD)
+			cur_glyph--;
+		    else
+			cur_glyph++;
+		}
+
+		transformed_clusters[i] = clusters[i];
+		if (cluster_visible)
+		    j += k;
+		else
+		    transformed_clusters[i].num_glyphs = 0;
+	    }
+	}
+    }
+    *num_transformed_glyphs = j;
+
+    if (num_clusters != 0 && cluster_flags & CAIRO_TEXT_CLUSTER_FLAG_BACKWARD) {
+	for (i = 0; i < --j; i++) {
+	    cairo_glyph_t tmp;
+
+	    tmp = transformed_glyphs[i];
+	    transformed_glyphs[i] = transformed_glyphs[j];
+	    transformed_glyphs[j] = tmp;
+	}
     }
 
     return CAIRO_STATUS_SUCCESS;


More information about the cairo-commit mailing list