[cairo-commit] 2 commits - src/cairo-atsui-font.c

Brian Ewins brianewins at kemper.freedesktop.org
Mon Jan 8 14:58:53 PST 2007


 src/cairo-atsui-font.c |  186 ++++++++++++++++++++++++++++++++++++++++---------
 1 files changed, 153 insertions(+), 33 deletions(-)

New commits:
diff-tree 504cbdae37232d65f5c1f8913e55ac63397ad4f0 (from 77171cb8e23704db3eeddfe92cc4e0e83d02b36b)
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Thu Jan 4 03:12:53 2007 +0000

    [ATSUI] [2/2] Implement CAIRO_SCALED_GLYPH_INFO_SURFACE support.(#9467)
    
    All non-quartz surfaces need to fall back to using glyph surfaces,
    in order to clip correctly. This second patch implements glyph
    surface support, correcting the unclipped text seen in the clip-operator
    test.

diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index c9305c5..b359b2e 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -676,9 +676,118 @@ _cairo_atsui_scaled_font_init_glyph_path
 
 static cairo_status_t
 _cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
-					  cairo_scaled_glyph_t *scaled_glyph)
+					     cairo_scaled_glyph_t *scaled_glyph)
 {
-    return CAIRO_INT_STATUS_UNSUPPORTED;
+    OSStatus err;
+    CGContextRef drawingContext;
+    cairo_image_surface_t *surface;
+    cairo_format_t format;
+
+    ATSFontRef atsFont;
+    CGFontRef cgFont;
+    cairo_scaled_font_t base = scaled_font->base;
+    cairo_font_extents_t extents = base.extents;
+
+    GlyphID theGlyph = _cairo_scaled_glyph_index (scaled_glyph);
+    ATSGlyphScreenMetrics metricsH;
+    double left, bottom, width, height;
+    double xscale, yscale;
+    CGRect bbox;
+    CGAffineTransform transform;
+
+
+    /* Compute a box to contain the glyph mask. The vertical
+     * sizes come from the font extents; extra pixels are 
+     * added to account for fractional sizes.
+     */
+    height = extents.ascent + extents.descent + 2.0;
+    bottom = -extents.descent - 1.0;
+
+    /* Horizontal sizes come from the glyph typographic metrics.
+     * It is possible that this might result in clipped text
+     * in fonts where the typographic bounds don't cover the ink.
+     * The width is recalculated, since metricsH.width is rounded.
+     */
+    err = ATSUGlyphGetScreenMetrics (scaled_font->style,
+				     1, &theGlyph, 0, false, 
+				     false, &metricsH);    
+    left = metricsH.sideBearing.x - 1.0;
+    width = metricsH.deviceAdvance.x 
+	- metricsH.sideBearing.x 
+	+ metricsH.otherSideBearing.x + 2.0;
+
+    /* The xy and yx components are negated because the y-axis
+     * is flipped into the cairo system then flipped back, ie:
+     * [1  0][xx yx][1  0]
+     * [0 -1][xy yy][0 -1]
+     */
+    transform = CGAffineTransformMake (base.scale.xx, 
+				      -base.scale.yx, 
+				      -base.scale.xy, 
+				      base.scale.yy, 
+				      0., 0.);
+    _cairo_matrix_compute_scale_factors (&base.scale, 
+					&xscale, &yscale, 1);
+    transform = CGAffineTransformScale (transform, 1.0/xscale, 1.0/yscale);
+
+    /* Rotate the bounding box. This computes the smallest CGRect
+     * that would contain the bounding box after rotation.
+     */
+    bbox = CGRectApplyAffineTransform (CGRectMake (left, bottom, 
+						   width, height), transform);
+    /* Compute the smallest CGRect with  integer coordinates
+     * that contains the bounding box.
+     */
+    bbox = CGRectIntegral (bbox);
+
+    left = CGRectGetMinX (bbox);
+    bottom = CGRectGetMinY (bbox);
+
+    /* XXX should we select format based on antialiasing flags, as ft does? */
+    format = CAIRO_FORMAT_A8;
+
+    /* create the glyph mask surface */
+    surface = (cairo_image_surface_t *)cairo_image_surface_create (format, bbox.size.width, bbox.size.height);
+    if (!surface)
+	return CAIRO_STATUS_NO_MEMORY;
+
+    drawingContext = CGBitmapContextCreateWithCairoImageSurface (surface);
+    if (!drawingContext) {
+	cairo_surface_destroy ((cairo_surface_t *)surface);
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+    }
+    
+    atsFont = FMGetATSFontRefFromFont (scaled_font->fontID);
+    cgFont = CGFontCreateWithPlatformFont (&atsFont);
+
+    CGContextSetFont (drawingContext, cgFont);
+
+    if (base.options.antialias ==  CAIRO_ANTIALIAS_NONE) {
+    	CGContextSetShouldAntialias (drawingContext, false);
+    }
+
+    /* solid white */
+    CGContextSetRGBFillColor (drawingContext, 1.0, 1.0, 1.0, 1.0);
+
+    CGContextSetFontSize (drawingContext, 1.0);
+    CGContextTranslateCTM (drawingContext, -left, -bottom);
+    CGContextScaleCTM (drawingContext, xscale, yscale);
+    CGContextSetTextMatrix (drawingContext, transform);
+    CGContextShowGlyphsAtPoint (drawingContext, 0, 0,  
+				&theGlyph, 1);
+
+    CGContextRelease (drawingContext);
+
+    /* correct for difference between cairo and quartz 
+     * coordinate systems.
+     */
+    cairo_surface_set_device_offset ((cairo_surface_t *)surface, left, 
+				    -bbox.size.height - bottom);
+    _cairo_scaled_glyph_set_surface (scaled_glyph,
+				     &base,
+				     surface);
+
+    return CAIRO_STATUS_SUCCESS;
 }
 
 static cairo_int_status_t
diff-tree 77171cb8e23704db3eeddfe92cc4e0e83d02b36b (from 116ae23fc64a8477a116bd6f3b60c7b5404af1c5)
Author: Brian Ewins <Brian.Ewins at gmail.com>
Date:   Thu Jan 4 02:16:47 2007 +0000

    [ATSUI] [1/2] Implement CAIRO_SCALED_GLYPH_INFO_SURFACE support.(#9467)
    
    All non-quartz surfaces need to fall back to using glyph surfaces,
    in order to clip correctly. The bug being fixed is visible in the
    clip-operator test. This first patch takes out direct rendering support 
    for non-quartz surfaces, causing all image tests to fail.

diff --git a/src/cairo-atsui-font.c b/src/cairo-atsui-font.c
index 4144ce6..c9305c5 100644
--- a/src/cairo-atsui-font.c
+++ b/src/cairo-atsui-font.c
@@ -674,6 +674,13 @@ _cairo_atsui_scaled_font_init_glyph_path
     return CAIRO_STATUS_SUCCESS;
 }
 
+static cairo_status_t
+_cairo_atsui_scaled_font_init_glyph_surface (cairo_atsui_font_t *scaled_font,
+					  cairo_scaled_glyph_t *scaled_glyph)
+{
+    return CAIRO_INT_STATUS_UNSUPPORTED;
+}
+
 static cairo_int_status_t
 _cairo_atsui_font_scaled_glyph_init (void			*abstract_font,
 				     cairo_scaled_glyph_t	*scaled_glyph,
@@ -694,6 +701,12 @@ _cairo_atsui_font_scaled_glyph_init (voi
 	    return status;
     }
 
+    if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
+	status = _cairo_atsui_scaled_font_init_glyph_surface (scaled_font, scaled_glyph);
+	if (status)
+	    return status;
+    }
+
     return CAIRO_STATUS_SUCCESS;
 }
 
@@ -777,14 +790,17 @@ _cairo_atsui_font_old_show_glyphs (void	
     void *extra = NULL;
     cairo_bool_t can_draw_directly;
     cairo_rectangle_int16_t rect;
+    cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface;
 
     ATSFontRef atsFont;
     CGFontRef cgFont;
     CGAffineTransform textTransform;
 
+    if (!_cairo_surface_is_quartz (generic_surface))
+	return CAIRO_INT_STATUS_UNSUPPORTED;
+
     /* Check if we can draw directly to the destination surface */
-    can_draw_directly = _cairo_surface_is_quartz (generic_surface) &&
-	_cairo_pattern_is_opaque_solid (pattern) &&
+    can_draw_directly = _cairo_pattern_is_opaque_solid (pattern) &&
 	op == CAIRO_OPERATOR_OVER;
 
     if (!can_draw_directly) {
@@ -837,38 +853,33 @@ _cairo_atsui_font_old_show_glyphs (void	
 	CGContextSetRGBFillColor(drawingContext, 0.0f, 0.0f, 0.0f, 0.0f);
     }
 
-    if (_cairo_surface_is_quartz (generic_surface)) {
-	cairo_quartz_surface_t *surface = (cairo_quartz_surface_t *)generic_surface;
-	if (surface->clip_region) {
-	    pixman_box16_t *boxes = pixman_region_rects (surface->clip_region);
-	    int num_boxes = pixman_region_num_rects (surface->clip_region);
-	    CGRect stack_rects[10];
-	    CGRect *rects;
-	    int i;
-
-	    /* XXX: Return-value of malloc needs to be checked for
-	     * NULL. Can someone fix this who is more familiar with
-	     * the cleanup needed in this function?
-	     */
-	    if (num_boxes > 10)
-		rects = malloc (sizeof (CGRect) * num_boxes);
-	    else
-		rects = stack_rects;
-
-	    for (i = 0; i < num_boxes; i++) {
-		rects[i].origin.x = boxes[i].x1;
-		rects[i].origin.y = boxes[i].y1;
-		rects[i].size.width = boxes[i].x2 - boxes[i].x1;
-		rects[i].size.height = boxes[i].y2 - boxes[i].y1;
-	    }
-
-	    CGContextClipToRects (drawingContext, rects, num_boxes);
-
-	    if (rects != stack_rects)
-		free(rects);
+    if (surface->clip_region) {
+	pixman_box16_t *boxes = pixman_region_rects (surface->clip_region);
+	int num_boxes = pixman_region_num_rects (surface->clip_region);
+	CGRect stack_rects[10];
+	CGRect *rects;
+	int i;
+	
+	/* XXX: Return-value of malloc needs to be checked for
+	 * NULL. Can someone fix this who is more familiar with
+	 * the cleanup needed in this function?
+	 */
+	if (num_boxes > 10)
+	    rects = malloc (sizeof (CGRect) * num_boxes);
+	else
+	    rects = stack_rects;
+	
+	for (i = 0; i < num_boxes; i++) {
+	    rects[i].origin.x = boxes[i].x1;
+	    rects[i].origin.y = boxes[i].y1;
+	    rects[i].size.width = boxes[i].x2 - boxes[i].x1;
+	    rects[i].size.height = boxes[i].y2 - boxes[i].y1;
 	}
-    } else {
-	/* XXX: Need to get the text clipped */
+	
+	CGContextClipToRects (drawingContext, rects, num_boxes);
+	
+	if (rects != stack_rects)
+	    free(rects);
     }
 
     /* TODO - bold and italic text


More information about the cairo-commit mailing list