[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