diff options
-rw-r--r-- | src/cairo-scaled-font.c | 36 | ||||
-rw-r--r-- | src/cairo-xlib-surface.c | 23 | ||||
-rw-r--r-- | src/cairoint.h | 6 |
3 files changed, 65 insertions, 0 deletions
diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index 74a2c88c..199ad39e 100644 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -2021,6 +2021,42 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, return CAIRO_STATUS_SUCCESS; } +void +_cairo_scaled_font_glyph_approximate_extents (cairo_scaled_font_t *scaled_font, + const cairo_glyph_t *glyphs, + int num_glyphs, + cairo_rectangle_int_t *extents) +{ + double x0 = HUGE_VAL, x1 = -HUGE_VAL; + double y0 = HUGE_VAL, y1 = -HUGE_VAL; + int i; + + for (i = 0; i < num_glyphs; i++) { + double g; + + g = glyphs[i].x; + if (g < x0) x0 = g; + if (g > x1) x1 = g; + + g = glyphs[i].y; + if (g < y0) y0 = g; + if (g > y1) y1 = g; + } + + if (x0 <= x1 && y0 <= y1) { + extents->x = floor (x0 - scaled_font->extents.max_x_advance); + extents->width = ceil (x1 + scaled_font->extents.max_x_advance); + extents->width -= extents->x; + + extents->y = floor (y0 - scaled_font->extents.ascent); + extents->height = ceil (y1 + scaled_font->extents.descent); + extents->height -= extents->y; + } else { + extents->x = extents->y = 0; + extents->width = extents->height = 0; + } +} + cairo_status_t _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, cairo_operator_t op, diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 375c6605..2b5b801b 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -4413,6 +4413,29 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, if (! _cairo_xlib_surface_owns_font (dst, scaled_font)) return UNSUPPORTED ("unowned font"); + if (clip_region != NULL && + cairo_region_num_rectangles (clip_region) == 1) + { + cairo_rectangle_int_t glyph_extents; + const cairo_rectangle_int_t *clip_extents; + + /* Can we do without the clip? + * Around 50% of the time the clip is redundant (firefox). + */ + _cairo_scaled_font_glyph_approximate_extents (scaled_font, + glyphs, num_glyphs, + &glyph_extents); + + clip_extents = &clip->path->extents; + if (clip_extents->x <= glyph_extents.x && + clip_extents->y <= glyph_extents.y && + clip_extents->x + clip_extents->width >= glyph_extents.x + glyph_extents.width && + clip_extents->y + clip_extents->height >= glyph_extents.y + glyph_extents.height) + { + clip_region = NULL; + } + } + status = _cairo_xlib_surface_set_clip_region (dst, clip_region); if (unlikely (status)) return status; diff --git a/src/cairoint.h b/src/cairoint.h index f6a45596..8b82454f 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -1726,6 +1726,12 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, cairo_rectangle_int_t *extents, cairo_bool_t *overlap); +cairo_private void +_cairo_scaled_font_glyph_approximate_extents (cairo_scaled_font_t *scaled_font, + const cairo_glyph_t *glyphs, + int num_glyphs, + cairo_rectangle_int_t *extents); + cairo_private cairo_status_t _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, cairo_operator_t op, |