[cairo-commit] Branch '1.4' - 2 commits - src/cairo-ft-font.c src/cairo-xlib-surface.c

Carl Worth cworth at kemper.freedesktop.org
Fri Jan 11 12:42:32 PST 2008


 src/cairo-ft-font.c      |   24 ------
 src/cairo-xlib-surface.c |  179 +++++++++++++++++++++++++++++++++++------------
 2 files changed, 136 insertions(+), 67 deletions(-)

New commits:
commit 69549125feb24118ad35403a4be647f8bb692e86
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Dec 17 01:14:27 2007 -0500

    [cairo-xlib] Support scale fonts with glyphs of multiple formats (#13479)
    
    We maintain three Xrender glyphsets per scaled font, one for each of A1, A8,
    and ARGB32.  This is required to correctly support fonts with bitmaps for
    some glyphs but not all.
    (cherry picked from commit 805b668260c47e6d3d854361fcc53f12bd2a57e1)

diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c
index e76bc92..298617f 100644
--- a/src/cairo-xlib-surface.c
+++ b/src/cairo-xlib-surface.c
@@ -1076,6 +1076,7 @@ _cairo_xlib_surface_set_attributes (cairo_xlib_surface_t	    *surface,
 	break;
     case CAIRO_EXTEND_REFLECT:
     case CAIRO_EXTEND_PAD:
+    default:
 	status = CAIRO_INT_STATUS_UNSUPPORTED;
     }
     if (status)
@@ -2428,11 +2429,22 @@ cairo_xlib_surface_get_height (cairo_surface_t *abstract_surface)
     return surface->height;
 }
 
-typedef struct _cairo_xlib_surface_font_private {
-    Display		*dpy;
+enum {
+  GLYPHSET_INDEX_ARGB32,
+  GLYPHSET_INDEX_A8,
+  GLYPHSET_INDEX_A1,
+  NUM_GLYPHSETS
+};
+
+typedef struct _cairo_xlib_font_glyphset_info {
     GlyphSet		glyphset;
     cairo_format_t	format;
     XRenderPictFormat	*xrender_format;
+} cairo_xlib_font_glyphset_info_t;
+
+typedef struct _cairo_xlib_surface_font_private {
+    Display		*dpy;
+    cairo_xlib_font_glyphset_info_t glyphset_info[NUM_GLYPHSETS];
 } cairo_xlib_surface_font_private_t;
 
 static void
@@ -2450,17 +2462,23 @@ _cairo_xlib_surface_remove_scaled_font (Display *dpy,
     CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
 
     if (font_private != NULL) {
-	XRenderFreeGlyphSet (font_private->dpy, font_private->glyphset);
+	int i;
+	for (i = 0; i < NUM_GLYPHSETS; i++) {
+	    cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i];
+	    if (glyphset_info->glyphset) {
+		XRenderFreeGlyphSet (font_private->dpy, glyphset_info->glyphset);
+	    }
+	}
 	free (font_private);
     }
 }
 
 static cairo_status_t
 _cairo_xlib_surface_font_init (Display		    *dpy,
-			       cairo_scaled_font_t  *scaled_font,
-			       cairo_format_t	     format)
+			       cairo_scaled_font_t  *scaled_font)
 {
     cairo_xlib_surface_font_private_t	*font_private;
+    int i;
 
     font_private = malloc (sizeof (cairo_xlib_surface_font_private_t));
     if (!font_private)
@@ -2475,9 +2493,18 @@ _cairo_xlib_surface_font_init (Display		    *dpy,
 
 
     font_private->dpy = dpy;
-    font_private->format = format;
-    font_private->xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT(dpy, format);
-    font_private->glyphset = XRenderCreateGlyphSet (dpy, font_private->xrender_format);
+    for (i = 0; i < NUM_GLYPHSETS; i++) {
+	cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i];
+	switch (i) {
+	    case GLYPHSET_INDEX_ARGB32: glyphset_info->format = CAIRO_FORMAT_ARGB32; break;
+	    case GLYPHSET_INDEX_A8:     glyphset_info->format = CAIRO_FORMAT_A8;     break;
+	    case GLYPHSET_INDEX_A1:     glyphset_info->format = CAIRO_FORMAT_A1;     break;
+	    default:                    ASSERT_NOT_REACHED;                          break;
+	}
+	glyphset_info->xrender_format = NULL;
+	glyphset_info->glyphset = None;
+    }
+
     scaled_font->surface_private = font_private;
     scaled_font->surface_backend = &cairo_xlib_surface_backend;
 
@@ -2496,10 +2523,19 @@ _cairo_xlib_surface_scaled_font_fini (cairo_scaled_font_t *scaled_font)
 
 	display = _cairo_xlib_display_get (font_private->dpy);
 	if (display != NULL) {
-	    cairo_status_t status = _cairo_xlib_display_queue_resource (display,
-					                XRenderFreeGlyphSet,
-					                font_private->glyphset);
-	    (void) status; /* XXX cannot propagate failure */
+	    int i;
+
+	    for (i = 0; i < NUM_GLYPHSETS; i++) {
+		cairo_xlib_font_glyphset_info_t *glyphset_info = &font_private->glyphset_info[i];
+		if (glyphset_info->glyphset) {
+		    cairo_status_t status;
+		    status = _cairo_xlib_display_queue_resource (display,
+								 XRenderFreeGlyphSet,
+								 glyphset_info->glyphset);
+		    (void) status; /* XXX cannot propagate failure */
+		}
+	    }
+
 	    _cairo_xlib_display_destroy (display);
 	}
 
@@ -2518,6 +2554,19 @@ static void _cairo_xlib_render_free_glyphs (Display *dpy, struct _cairo_xlib_ren
 	               &arg->glyph_index, 1);
 }
 
+static cairo_xlib_font_glyphset_info_t *
+_cairo_xlib_scaled_glyph_get_glyphset_info (cairo_scaled_glyph_t            *scaled_glyph)
+{
+  return scaled_glyph->surface_private;
+}
+
+static void
+_cairo_xlib_scaled_glyph_set_glyphset_info (cairo_scaled_glyph_t            *scaled_glyph,
+					    cairo_xlib_font_glyphset_info_t *glyphset_info)
+{
+  scaled_glyph->surface_private = glyphset_info;
+}
+
 static void
 _cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
 				       cairo_scaled_font_t  *scaled_font)
@@ -2530,7 +2579,7 @@ _cairo_xlib_surface_scaled_glyph_fini (cairo_scaled_glyph_t *scaled_glyph,
 	    struct _cairo_xlib_render_free_glyphs *arg = malloc (sizeof (*arg));
 	    if (arg != NULL) {
 		cairo_status_t status;
-		arg->glyphset = font_private->glyphset;
+		arg->glyphset = _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph)->glyphset;
 		arg->glyph_index = _cairo_scaled_glyph_index (scaled_glyph);
 		status = _cairo_xlib_display_queue_work (display,
 			(cairo_xlib_notify_func) _cairo_xlib_render_free_glyphs,
@@ -2556,6 +2605,32 @@ _native_byte_order_lsb (void)
     return *((char *) &x) == 1;
 }
 
+static cairo_xlib_font_glyphset_info_t *
+_cairo_xlib_scaled_font_get_glyphset_info_for_format (cairo_scaled_font_t *scaled_font,
+						      cairo_format_t       format)
+{
+    cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
+    cairo_xlib_font_glyphset_info_t *glyphset_info;
+    int glyphset_index;
+
+    switch (format) {
+    default:
+    case CAIRO_FORMAT_RGB24:
+    case CAIRO_FORMAT_ARGB32: glyphset_index = GLYPHSET_INDEX_ARGB32; break;
+    case CAIRO_FORMAT_A8:     glyphset_index = GLYPHSET_INDEX_A8;     break;
+    case CAIRO_FORMAT_A1:     glyphset_index = GLYPHSET_INDEX_A1;     break;
+    }
+
+    glyphset_info = &font_private->glyphset_info[glyphset_index];
+
+    if (glyphset_info->glyphset == None) {
+	glyphset_info->xrender_format = _CAIRO_FORMAT_TO_XRENDER_FORMAT(font_private->dpy, glyphset_info->format);
+	glyphset_info->glyphset = XRenderCreateGlyphSet (font_private->dpy, glyphset_info->xrender_format);
+    }
+
+    return glyphset_info;
+}
+
 static cairo_status_t
 _cairo_xlib_surface_add_glyph (Display *dpy,
 			       cairo_scaled_font_t   *scaled_font,
@@ -2569,6 +2644,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
     cairo_scaled_glyph_t *scaled_glyph = *pscaled_glyph;
     cairo_image_surface_t *glyph_surface = scaled_glyph->surface;
     cairo_bool_t already_had_glyph_surface;
+    cairo_xlib_font_glyphset_info_t *glyphset_info;
 
     if (!glyph_surface) {
 
@@ -2588,13 +2664,15 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
     }
 
     if (scaled_font->surface_private == NULL) {
-	status = _cairo_xlib_surface_font_init (dpy, scaled_font,
-						glyph_surface->format);
+	status = _cairo_xlib_surface_font_init (dpy, scaled_font);
 	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);
+
     /* If the glyph surface has zero height or width, we create
      * a clear 1x1 surface, to avoid various X server bugs.
      */
@@ -2602,7 +2680,7 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
 	cairo_t *cr;
 	cairo_surface_t *tmp_surface;
 
-	tmp_surface = cairo_image_surface_create (font_private->format, 1, 1);
+	tmp_surface = cairo_image_surface_create (glyphset_info->format, 1, 1);
 	cr = cairo_create (tmp_surface);
 	cairo_set_operator (cr, CAIRO_OPERATOR_CLEAR);
 	cairo_paint (cr);
@@ -2624,11 +2702,11 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
      * create a temporary surface for the glyph image with the font's
      * format.
      */
-    if (glyph_surface->format != font_private->format) {
+    if (glyph_surface->format != glyphset_info->format) {
 	cairo_t *cr;
 	cairo_surface_t *tmp_surface;
 
-	tmp_surface = cairo_image_surface_create (font_private->format,
+	tmp_surface = cairo_image_surface_create (glyphset_info->format,
 						  glyph_surface->width,
 						  glyph_surface->height);
 	tmp_surface->device_transform = glyph_surface->base.device_transform;
@@ -2760,11 +2838,13 @@ _cairo_xlib_surface_add_glyph (Display *dpy,
 
     glyph_index = _cairo_scaled_glyph_index (scaled_glyph);
 
-    XRenderAddGlyphs (dpy, font_private->glyphset,
+    XRenderAddGlyphs (dpy, glyphset_info->glyphset,
 		      &glyph_index, &(glyph_info), 1,
 		      (char *) data,
 		      glyph_surface->stride * glyph_surface->height);
 
+    _cairo_xlib_scaled_glyph_set_glyphset_info (scaled_glyph, glyphset_info);
+
     if (data != glyph_surface->data)
 	free (data);
 
@@ -2814,6 +2894,9 @@ typedef struct {
   } p;
 } cairo_xlib_glyph_t;
 
+/* compile-time assert that cairo_xlib_glyph_t is the same size as cairo_glyph_t */
+typedef int cairo_xlib_glyph_t_size_assertion [sizeof (cairo_xlib_glyph_t) == sizeof (cairo_glyph_t) ? 1 : -1];
+
 #define GLYPH_INDEX_SKIP ((unsigned long) -1)
 #define STACK_ELTS_LEN ((int) (CAIRO_STACK_BUFFER_SIZE / sizeof (XGlyphElt8)))
 
@@ -2821,12 +2904,14 @@ static cairo_status_t
 _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
 				       cairo_xlib_glyph_t *glyphs,
 				       int num_glyphs,
-				       int width,
-				       int num_elts,
 				       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,
+				       /* info for this chunk */
+				       int num_elts,
+				       int width,
+				       cairo_xlib_font_glyphset_info_t *glyphset_info)
 {
     /* Which XRenderCompositeText function to use */
     cairo_xrender_composite_text_func_t composite_text_func;
@@ -2846,8 +2931,6 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
     int n; /* Num output glyphs in current element */
     int j; /* Num output glyphs so far */
 
-    cairo_xlib_surface_font_private_t *font_private = scaled_font->surface_private;
-
     switch (width) {
     case 1:
 	/* don't cast the 8-variant, to catch possible mismatches */
@@ -2892,7 +2975,7 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
 	    n = 0;
 	  }
 	  elts[nelt].chars = char8 + size * j;
-	  elts[nelt].glyphset = font_private->glyphset;
+	  elts[nelt].glyphset = glyphset_info->glyphset;
 	  elts[nelt].xOff = glyphs[i].p.i.x;
 	  elts[nelt].yOff = glyphs[i].p.i.y;
       }
@@ -2918,7 +3001,7 @@ _cairo_xlib_surface_emit_glyphs_chunk (cairo_xlib_surface_t *dst,
 			 _render_operator (op),
 			 src->src_picture,
 			 dst->dst_picture,
-			 font_private->xrender_format,
+			 glyphset_info->xrender_format,
 			 attributes->x_offset + elts[0].xOff,
 			 attributes->y_offset + elts[0].yOff,
 			 elts[0].xOff, elts[0].yOff,
@@ -2945,6 +3028,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
     cairo_status_t status = CAIRO_STATUS_SUCCESS;
     cairo_scaled_glyph_t *scaled_glyph;
     cairo_fixed_t x = 0, y = 0;
+    cairo_xlib_font_glyphset_info_t *glyphset_info = NULL, *this_glyphset_info;
 
     unsigned long max_index = 0;
     int width = 1;
@@ -2995,6 +3079,19 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
 	    continue;
 	}
 
+	/* Send unsent glyphs to the server */
+	if (scaled_glyph->surface_private == NULL) {
+	    status = _cairo_xlib_surface_add_glyph (dst->dpy,
+		                                    scaled_font,
+						    &scaled_glyph);
+	    if (status)
+		return status;
+	}
+
+	this_glyphset_info = _cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph);
+	if (!glyphset_info)
+	    glyphset_info = this_glyphset_info;
+
 	old_width = width;
 
 	/* Update max glyph index */
@@ -3010,11 +3107,17 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
 
 	/* If we will pass the max request size by adding this glyph,
 	 * flush current glyphs.  Note that we account for a
-	 * possible element being added below. */
-	if (request_size + width > max_request_size - sz_xGlyphElt) {
+	 * possible element being added below.
+	 *
+	 * Also flush if changing glyphsets, as Xrender limits one mask
+	 * format per request, so we can either break up, or use a
+	 * wide-enough mask format.  We do the former.
+	 */
+	if (request_size + width > max_request_size - sz_xGlyphElt ||
+	    (this_glyphset_info != glyphset_info)) {
 	    status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, i,
-							    old_width, num_elts,
-							    scaled_font, op, src, attributes);
+							    scaled_font, op, src, attributes,
+							    num_elts, old_width, glyphset_info);
 	    if (status != CAIRO_STATUS_SUCCESS)
 		return status;
 
@@ -3027,7 +3130,7 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
 	    num_elts = 0;
 	    num_out_glyphs = 0;
 	    x = y = 0;
-
+	    glyphset_info = this_glyphset_info;
 	}
 
 	/* Convert absolute glyph position to relative-to-current-point
@@ -3042,16 +3145,6 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
 	    request_size += sz_xGlyphElt;
 	}
 
-	/* Send unsent glyphs to the server */
-	if (scaled_glyph->surface_private == NULL) {
-	    status = _cairo_xlib_surface_add_glyph (dst->dpy,
-		                                    scaled_font,
-						    &scaled_glyph);
-	    if (status)
-		return status;
-	    scaled_glyph->surface_private = (void *) 1;
-	}
-
 	/* adjust current-position */
 	x = this_x + scaled_glyph->x_advance;
 	y = this_y + scaled_glyph->y_advance;
@@ -3062,8 +3155,8 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_surface_t *dst,
 
     if (num_elts)
 	status = _cairo_xlib_surface_emit_glyphs_chunk (dst, glyphs, num_glyphs,
-							width, num_elts,
-							scaled_font, op, src, attributes);
+							scaled_font, op, src, attributes,
+							num_elts, width, glyphset_info);
 
     return status;
 }
commit 8776061068fba967dbafb43fac3af7df90464cb8
Author: Behdad Esfahbod <behdad at behdad.org>
Date:   Mon Dec 17 01:19:53 2007 -0500

    [cairo-ft] Revert "Force non-AA text when using a bitmap strike with only scaling transform." (#13479)
    
    The reasoning for that commit was that fonts with bitmap strikes should be
    rendered with antialiasing off for those (hopefully) few glyphs that don't
    have a bitmap.
    
    However, it turns out, there are fonts that have some, but very few, bitmaps,
    and this changed forces non-AA rendering on them.  We now support multiple
    glyph formats per font in the Xlib backend, so backing this out to let every
    glyph render as is.  Fontconfig rules can be used to force AA off on a per-font
    basis.
    
    This reverts commit 06af5c2891b89da28581c30afcde06c5442884db.
    (cherry picked from commit 83963d2a9ec445e23cfbe692b877177a9d9d135e)

diff --git a/src/cairo-ft-font.c b/src/cairo-ft-font.c
index 804ecc2..914dc0b 100644
--- a/src/cairo-ft-font.c
+++ b/src/cairo-ft-font.c
@@ -1512,30 +1512,6 @@ _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t	 *unscaled,
 	return NULL;
     }
 
-    /*
-     * Force non-AA drawing when using a bitmap strike that
-     * won't be resampled due to non-scaling transform
-     */
-    if (!unscaled->have_shape &&
-	(scaled_font->ft_options.load_flags & FT_LOAD_NO_BITMAP) == 0 &&
-	scaled_font->ft_options.base.antialias != CAIRO_ANTIALIAS_NONE &&
-	(face->face_flags & FT_FACE_FLAG_FIXED_SIZES))
-    {
-	int		i;
-	FT_Size_Metrics	*size_metrics = &face->size->metrics;
-
-	for (i = 0; i < face->num_fixed_sizes; i++)
-	{
-	    FT_Bitmap_Size  *bitmap_size = &face->available_sizes[i];
-
-	    if (bitmap_size->x_ppem == size_metrics->x_ppem * 64 &&
-		bitmap_size->y_ppem == size_metrics->y_ppem * 64)
-	    {
-		scaled_font->ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
-		break;
-	    }
-	}
-    }
 
     metrics = &face->size->metrics;
 


More information about the cairo-commit mailing list