[cairo-commit] 3 commits - src/cairo-analysis-surface.c src/cairo-directfb-surface.c src/cairoint.h src/cairo-meta-surface.c src/cairo-paginated-surface.c src/cairo-ps-surface.c src/cairo-quartz-surface.c src/cairo-scaled-font.c src/cairo-surface.c src/cairo-svg-surface.c src/cairo-win32-font.c src/cairo-win32-printing-surface.c src/cairo-win32-surface.c src/cairo-xcb-surface.c src/cairo-xlib-surface.c src/test-meta-surface.c src/test-paginated-surface.c

Behdad Esfahbod behdad at kemper.freedesktop.org
Fri May 23 17:11:44 PDT 2008


 src/cairo-analysis-surface.c       |   10 +++---
 src/cairo-directfb-surface.c       |    3 +
 src/cairo-meta-surface.c           |    3 +
 src/cairo-paginated-surface.c      |    3 +
 src/cairo-ps-surface.c             |    3 +
 src/cairo-quartz-surface.c         |    3 +
 src/cairo-scaled-font.c            |    7 +++-
 src/cairo-surface.c                |   17 +++++++++--
 src/cairo-svg-surface.c            |    3 +
 src/cairo-win32-font.c             |    3 +
 src/cairo-win32-printing-surface.c |    3 +
 src/cairo-win32-surface.c          |    3 +
 src/cairo-xcb-surface.c            |    3 +
 src/cairo-xlib-surface.c           |   57 ++++++++++++++++++++++---------------
 src/cairoint.h                     |    6 ++-
 src/test-meta-surface.c            |    3 +
 src/test-paginated-surface.c       |    3 +
 17 files changed, 90 insertions(+), 43 deletions(-)

New commits:
commit db1b18232b6854d14a1ee45a31bc2508ef36bc1a
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 23 19:04:13 2008 -0400

    [cairo-xlib] Fix max-request size calculations
    
    First, XMaxRequestSize returns number of 4-byte words.  So multiply by 4 is
    needed in all uses.  Next, XRenderAddGlyphs uses BIG-REQUEST extension if
    available, so when checking for glyph size overflow, we should use
    XExtendedMaxRequestSize() first.
    
    Also use the right format when calculating glyph size.
    
    These changes combined, push the biggest font size that can be uploaded to the
    server from under 200 to about 5000.
    
    See bug #4339 for history.

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index d14497c..28f2aba 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2940,20 +2940,6 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
 	already_had_glyph_surface = TRUE;
     }
 
-    /* XXX XRenderAddGlyph does not handle a glyph surface larger than the
-     * maximum XRequest size.
-     */
-    {
-	/* pessimistic length estimation in case we need to change formats */
-	int len = 4 * glyph_surface->width * glyph_surface->height;
-	int max_request_size = XMaxRequestSize (dpy)  -
-	                       sz_xRenderAddGlyphsReq -
-	                       sz_xGlyphInfo          -
-			       4;
-	if (len >= max_request_size)
-	    return CAIRO_INT_STATUS_UNSUPPORTED;
-    }
-
     if (scaled_font->surface_private == NULL) {
 	status = _cairo_xlib_surface_font_init (dpy, scaled_font);
 	if (status)
@@ -2963,6 +2949,17 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
     glyphset_info = _cairo_xlib_scaled_font_get_glyphset_info_for_format (scaled_font,
 									  glyph_surface->format);
 
+    /* XRenderAddGlyph does not handle a glyph surface larger than the extended maximum XRequest size.  */
+    {
+	int len = cairo_format_stride_for_width (glyphset_info->format, glyph_surface->width) * glyph_surface->height;
+	int max_request_size = (XExtendedMaxRequestSize (dpy) ? XExtendedMaxRequestSize (dpy) : XMaxRequestSize (dpy)) * 4 -
+	                       sz_xRenderAddGlyphsReq -
+	                       sz_xGlyphInfo          -
+			       8;
+	if (len >= max_request_size)
+	    return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+
     /* check to see if we have a pending XRenderFreeGlyph for this glyph */
     if (glyphset_info->pending_free_glyphs != NULL) {
 	cairo_xlib_font_glyphset_free_glyphs_t *to_free;
@@ -3304,7 +3301,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
     int num_elts = 0;
     int num_out_glyphs = 0;
 
-    int max_request_size = XMaxRequestSize (dst->dpy)
+    int max_request_size = XMaxRequestSize (dst->dpy) * 4
 			 - MAX (sz_xRenderCompositeGlyphs8Req,
 				MAX(sz_xRenderCompositeGlyphs16Req,
 				    sz_xRenderCompositeGlyphs32Req));
commit cf473f4a75ca0d3c815222287d7c144e72de5add
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 23 19:57:48 2008 -0400

    [cairo-xlib] Fix show_glyphs when failing to upload a glyph
    
    Originally reported here:
    http://lists.cairographics.org/archives/cairo/2008-May/014032.html
    and analyized later in the thread.
    
    Change (font and surface) backend show_glyphs() API to take a
    int *remaining_glyphs argument.  It's used to communicate to the caller,
    by way of setting remaining_glyphs and returning INT_STATUS_UNSUPPORTED,
    that some of the glyphs were shown but not the others.  The xlib backend
    now correctly uses this to handle failure to upload a glyph to the server.
    So the large-font test passes now.
    
    An alternative approach could be to add some public value for glyphs
    indices that are not shown.  -1 perhaps (the xlib backend already uses
    that value internally).  Then instead of remaining_glyphs, a backend
    could simply set glyph indices of glyphs shown to that -1 value.

diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c
index ad1ca3c..c19de4b 100644
--- a/src/cairo-analysis-surface.c
+++ b/src/cairo-analysis-surface.c
@@ -556,7 +556,8 @@ _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 				     cairo_pattern_t	  *source,
 				     cairo_glyph_t	  *glyphs,
 				     int		   num_glyphs,
-				     cairo_scaled_font_t  *scaled_font)
+				     cairo_scaled_font_t  *scaled_font,
+				     int                  *remaining_glyphs)
 {
     cairo_analysis_surface_t *surface = abstract_surface;
     cairo_status_t	     status, backend_status;
@@ -566,9 +567,10 @@ _cairo_analysis_surface_show_glyphs (void		  *abstract_surface,
 	backend_status = CAIRO_INT_STATUS_UNSUPPORTED;
     else
 	backend_status = (*surface->target->backend->show_glyphs) (surface->target, op,
-							   source,
-							   glyphs, num_glyphs,
-							   scaled_font);
+								   source,
+								   glyphs, num_glyphs,
+								   scaled_font,
+								   remaining_glyphs);
 
     if (backend_status == CAIRO_INT_STATUS_ANALYZE_META_SURFACE_PATTERN)
 	backend_status = _cairo_analysis_surface_analyze_meta_surface_pattern (surface,
diff --git a/src/cairo-directfb-surface.c b/src/cairo-directfb-surface.c
index f20bf2b..7483048 100644
--- a/src/cairo-directfb-surface.c
+++ b/src/cairo-directfb-surface.c
@@ -1606,7 +1606,8 @@ _cairo_directfb_surface_show_glyphs (void                *abstract_dst,
                                      cairo_pattern_t     *pattern,
                                      cairo_glyph_t       *glyphs,
                                      int                  num_glyphs,
-                                     cairo_scaled_font_t *scaled_font)
+                                     cairo_scaled_font_t *scaled_font,
+				     int		 *remaining_glyphs)
 {
     cairo_directfb_surface_t    *dst = abstract_dst;
     cairo_directfb_font_cache_t *cache;
diff --git a/src/cairo-meta-surface.c b/src/cairo-meta-surface.c
index 6abb29a..a7674cd 100644
--- a/src/cairo-meta-surface.c
+++ b/src/cairo-meta-surface.c
@@ -432,7 +432,8 @@ _cairo_meta_surface_show_glyphs (void			*abstract_surface,
 				 cairo_pattern_t	*source,
 				 cairo_glyph_t		*glyphs,
 				 int			 num_glyphs,
-				 cairo_scaled_font_t	*scaled_font)
+				 cairo_scaled_font_t	*scaled_font,
+				 int			*remaining_glyphs)
 {
     cairo_status_t status;
     cairo_meta_surface_t *meta = abstract_surface;
diff --git a/src/cairo-paginated-surface.c b/src/cairo-paginated-surface.c
index 4c47749..dc622ed 100644
--- a/src/cairo-paginated-surface.c
+++ b/src/cairo-paginated-surface.c
@@ -601,7 +601,8 @@ _cairo_paginated_surface_show_glyphs (void			*abstract_surface,
 				      cairo_pattern_t		*source,
 				      cairo_glyph_t		*glyphs,
 				      int			 num_glyphs,
-				      cairo_scaled_font_t	*scaled_font)
+				      cairo_scaled_font_t	*scaled_font,
+				      int			*remaining_glyphs)
 {
     cairo_paginated_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
diff --git a/src/cairo-ps-surface.c b/src/cairo-ps-surface.c
index 2c07b47..589607e 100644
--- a/src/cairo-ps-surface.c
+++ b/src/cairo-ps-surface.c
@@ -3077,7 +3077,8 @@ _cairo_ps_surface_show_glyphs (void		     *abstract_surface,
 			       cairo_pattern_t	     *source,
 			       cairo_glyph_t         *glyphs,
 			       int		      num_glyphs,
-			       cairo_scaled_font_t   *scaled_font)
+			       cairo_scaled_font_t   *scaled_font,
+			       int		     *remaining_glyphs)
 {
     cairo_ps_surface_t *surface = abstract_surface;
     cairo_status_t status;
diff --git a/src/cairo-quartz-surface.c b/src/cairo-quartz-surface.c
index 7d90fba..75fb13f 100644
--- a/src/cairo-quartz-surface.c
+++ b/src/cairo-quartz-surface.c
@@ -1875,7 +1875,8 @@ _cairo_quartz_surface_show_glyphs (void *abstract_surface,
 				   cairo_pattern_t *source,
 				   cairo_glyph_t *glyphs,
 				   int num_glyphs,
-				   cairo_scaled_font_t *scaled_font)
+				   cairo_scaled_font_t *scaled_font,
+				   int *remaining_glyphs)
 {
     CGAffineTransform textTransform, ctm;
 #define STATIC_BUF_SIZE 64
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c
index 8cfc44a..b4c1ad3 100644
--- a/src/cairo-scaled-font.c
+++ b/src/cairo-scaled-font.c
@@ -1280,13 +1280,18 @@ _cairo_scaled_font_show_glyphs (cairo_scaled_font_t    *scaled_font,
 	return CAIRO_STATUS_SUCCESS;
 
     if (scaled_font->backend->show_glyphs != NULL) {
+	int remaining_glyphs = num_glyphs;
 	status = scaled_font->backend->show_glyphs (scaled_font,
 						    op, pattern,
 						    surface,
 						    source_x, source_y,
 						    dest_x, dest_y,
 						    width, height,
-						    glyphs, num_glyphs);
+						    glyphs, num_glyphs, &remaining_glyphs);
+	glyphs += num_glyphs - remaining_glyphs;
+	num_glyphs = remaining_glyphs;
+	if (remaining_glyphs == 0)
+	    status = CAIRO_STATUS_SUCCESS;
 	if (status != CAIRO_INT_STATUS_UNSUPPORTED)
 	    return _cairo_scaled_font_set_error (scaled_font, status);
     }
diff --git a/src/cairo-surface.c b/src/cairo-surface.c
index ba39b9b..7ded02d 100644
--- a/src/cairo-surface.c
+++ b/src/cairo-surface.c
@@ -2111,6 +2111,12 @@ _cairo_surface_get_extents (cairo_surface_t         *surface,
  * avoid copying the array again and again, and edit it in-place.
  * Backends are in fact free to use the array as a generic buffer as they
  * see fit.
+ *
+ * When they do return UNSUPPORTED, they may adjust remaining_glyphs to notify
+ * that they have successfully rendered some of the glyphs (from the beginning
+ * of the array), but not all.  If they don't touch remaining_glyphs, it
+ * defaults to all glyphs.
+ *
  * See commits 5a9642c5746fd677aed35ce620ce90b1029b1a0c and
  * 1781e6018c17909311295a9cc74b70500c6b4d0a for the rationale.
  */
@@ -2167,10 +2173,17 @@ _cairo_surface_show_glyphs (cairo_surface_t	*surface,
 
     status = CAIRO_INT_STATUS_UNSUPPORTED;
 
-    if (surface->backend->show_glyphs)
+    if (surface->backend->show_glyphs) {
+	int remaining_glyphs = num_glyphs;
 	status = surface->backend->show_glyphs (surface, op, dev_source,
 						glyphs, num_glyphs,
-                                                dev_scaled_font);
+                                                dev_scaled_font,
+						&remaining_glyphs);
+	glyphs += num_glyphs - remaining_glyphs;
+	num_glyphs = remaining_glyphs;
+	if (remaining_glyphs == 0)
+	    status = CAIRO_STATUS_SUCCESS;
+    }
 
     if (status == CAIRO_INT_STATUS_UNSUPPORTED)
 	status = _cairo_surface_fallback_show_glyphs (surface, op, dev_source,
diff --git a/src/cairo-svg-surface.c b/src/cairo-svg-surface.c
index 6a06783..e5e691b 100644
--- a/src/cairo-svg-surface.c
+++ b/src/cairo-svg-surface.c
@@ -2142,7 +2142,8 @@ _cairo_svg_surface_show_glyphs (void			*abstract_surface,
 				cairo_pattern_t		*pattern,
 				cairo_glyph_t		*glyphs,
 				int			 num_glyphs,
-				cairo_scaled_font_t	*scaled_font)
+				cairo_scaled_font_t	*scaled_font,
+				int			*remaining_glyphs)
 {
     cairo_svg_surface_t *surface = abstract_surface;
     cairo_svg_document_t *document = surface->document;
diff --git a/src/cairo-win32-font.c b/src/cairo-win32-font.c
index 919b6f8..74b072c 100644
--- a/src/cairo-win32-font.c
+++ b/src/cairo-win32-font.c
@@ -1320,7 +1320,8 @@ _cairo_win32_scaled_font_show_glyphs (void		       *abstract_font,
 				      unsigned int		width,
 				      unsigned int		height,
 				      cairo_glyph_t	       *glyphs,
-				      int                 	num_glyphs)
+				      int                 	num_glyphs,
+				      int		       *remaining_glyphs)
 {
     cairo_win32_scaled_font_t *scaled_font = abstract_font;
     cairo_win32_surface_t *surface = (cairo_win32_surface_t *)generic_surface;
diff --git a/src/cairo-win32-printing-surface.c b/src/cairo-win32-printing-surface.c
index 8fe5bc7..805fe64 100644
--- a/src/cairo-win32-printing-surface.c
+++ b/src/cairo-win32-printing-surface.c
@@ -1293,7 +1293,8 @@ _cairo_win32_printing_surface_show_glyphs (void                 *abstract_surfac
                                            cairo_pattern_t	*source,
                                            cairo_glyph_t        *glyphs,
                                            int			 num_glyphs,
-                                           cairo_scaled_font_t  *scaled_font)
+                                           cairo_scaled_font_t  *scaled_font,
+					   int			*remaining_glyphs)
 {
     cairo_win32_surface_t *surface = abstract_surface;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
diff --git a/src/cairo-win32-surface.c b/src/cairo-win32-surface.c
index d303af8..539f795 100644
--- a/src/cairo-win32-surface.c
+++ b/src/cairo-win32-surface.c
@@ -1556,7 +1556,8 @@ _cairo_win32_surface_show_glyphs (void			*surface,
 				  cairo_pattern_t	*source,
 				  cairo_glyph_t		*glyphs,
 				  int			 num_glyphs,
-				  cairo_scaled_font_t	*scaled_font)
+				  cairo_scaled_font_t	*scaled_font,
+				  int			*remaining_glyphs)
 {
 #if CAIRO_HAS_WIN32_FONT
     cairo_win32_surface_t *dst = surface;
diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c
index f7ae9d1..a3eac9e 100644
--- a/src/cairo-xcb-surface.c
+++ b/src/cairo-xcb-surface.c
@@ -2310,7 +2310,8 @@ _cairo_xcb_surface_show_glyphs (void                *abstract_dst,
 				 cairo_pattern_t     *src_pattern,
 				 cairo_glyph_t       *glyphs,
 				 int		      num_glyphs,
-				 cairo_scaled_font_t *scaled_font)
+				 cairo_scaled_font_t *scaled_font,
+				 int		     *remaining_glyphs)
 {
     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_xcb_surface_t *dst = abstract_dst;
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index b9641aa..d14497c 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -80,7 +80,8 @@ _cairo_xlib_surface_show_glyphs (void                *abstract_dst,
 				 cairo_pattern_t     *src_pattern,
 				 cairo_glyph_t       *glyphs,
 				 int		      num_glyphs,
-				 cairo_scaled_font_t *scaled_font);
+				 cairo_scaled_font_t *scaled_font,
+				 int		     *remaining_glyphs);
 
 /*
  * Instead of taking two round trips for each blending request,
@@ -3289,7 +3290,8 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
 				 cairo_scaled_font_t *scaled_font,
 				 cairo_operator_t op,
 				 cairo_xlib_surface_t *src,
-				 cairo_surface_attributes_t *attributes)
+				 cairo_surface_attributes_t *attributes,
+				 int *remaining_glyphs)
 {
     int i;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
@@ -3351,8 +3353,22 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
 	    status = _cairo_xlib_surface_add_glyph (dst->dpy,
 		                                    scaled_font,
 						    &scaled_glyph);
-	    if (status)
+	    if (status) {
+	        if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
+		    /* Glyph image too big to send to server.  Flush what we
+		     * got and let fallback code handle the rest.
+		     */
+		    if (num_elts)
+			status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, i,
+									scaled_font, op, src, attributes,
+									num_elts, width, glyphset_info);
+		    *remaining_glyphs = num_glyphs - i;
+
+		    if (status == CAIRO_STATUS_SUCCESS)
+			status = CAIRO_INT_STATUS_UNSUPPORTED;
+		}
 		return status;
+	    }
 	}
 
 	this_glyphset_info = _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph);
@@ -3439,7 +3455,8 @@ _cairo_xlib_surface_show_glyphs (void                *abstract_dst,
 				 cairo_pattern_t     *src_pattern,
 				 cairo_glyph_t       *glyphs,
 				 int		      num_glyphs,
-				 cairo_scaled_font_t *scaled_font)
+				 cairo_scaled_font_t *scaled_font,
+				 int		     *remaining_glyphs)
 {
     cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_xlib_surface_t *dst = (cairo_xlib_surface_t*) abstract_dst;
@@ -3554,7 +3571,8 @@ _cairo_xlib_surface_show_glyphs (void                *abstract_dst,
 					      scaled_font,
 					      op,
 					      src,
-					      &attributes);
+					      &attributes,
+					      remaining_glyphs);
 
   BAIL1:
     if (src)
diff --git a/src/cairoint.h b/src/cairoint.h
index 8716bd4..bf85e64 100755
--- a/src/cairoint.h
+++ b/src/cairoint.h
@@ -425,7 +425,8 @@ struct _cairo_scaled_font_backend {
 			 unsigned int		 width,
 			 unsigned int		 height,
 			 cairo_glyph_t		*glyphs,
-			 int			 num_glyphs);
+			 int			 num_glyphs,
+			 int			*remaining_glyphs);
 
     cairo_warn cairo_int_status_t
     (*load_truetype_table)(void		        *scaled_font,
@@ -710,7 +711,8 @@ struct _cairo_surface_backend {
 				 cairo_pattern_t	*source,
 				 cairo_glyph_t		*glyphs,
 				 int			 num_glyphs,
-				 cairo_scaled_font_t	*scaled_font);
+				 cairo_scaled_font_t	*scaled_font,
+				 int			*remaining_glyphs);
 
     cairo_surface_t *
     (*snapshot)			(void			*surface);
diff --git a/src/test-meta-surface.c b/src/test-meta-surface.c
index e56efcc..a6f8b97 100644
--- a/src/test-meta-surface.c
+++ b/src/test-meta-surface.c
@@ -261,7 +261,8 @@ _test_meta_surface_show_glyphs (void			*abstract_surface,
 				cairo_pattern_t		*source,
 				cairo_glyph_t		*glyphs,
 				int			 num_glyphs,
-				cairo_scaled_font_t	*scaled_font)
+				cairo_scaled_font_t	*scaled_font,
+				int			*remaining_glyphs)
 {
     test_meta_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
diff --git a/src/test-paginated-surface.c b/src/test-paginated-surface.c
index f7cc4db..6b85a13 100644
--- a/src/test-paginated-surface.c
+++ b/src/test-paginated-surface.c
@@ -238,7 +238,8 @@ _test_paginated_surface_show_glyphs (void			*abstract_surface,
 				     cairo_pattern_t		*source,
 				     cairo_glyph_t		*glyphs,
 				     int			 num_glyphs,
-				     cairo_scaled_font_t	*scaled_font)
+				     cairo_scaled_font_t	*scaled_font,
+				     int			*remaining_glyphs)
 {
     test_paginated_surface_t *surface = abstract_surface;
     cairo_int_status_t status;
commit e66e198ab04f2e19093aad4ed9f9c24e2756b8a7
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Fri May 23 17:11:43 2008 -0400

    [cairo-xlib] Remove unused variable

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index fef51f1..b9641aa 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -2916,7 +2916,6 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
     unsigned long glyph_index;
     unsigned char *data;
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
-    cairo_xlib_surface_font_private_t *font_private;
     cairo_scaled_glyph_t *scaled_glyph = *pscaled_glyph;
     cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
     cairo_bool_t already_had_glyph_surface;
@@ -2959,7 +2958,6 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
 	if (status)
 	    return status;
     }
-    font_private = scaled_font->surface_private;
 
     glyphset_info = _cairo_xlib_scaled_font_get_glyphset_info_for_format (scaled_font,
 									  glyph_surface->format);


More information about the cairo-commit mailing list