summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cairo-scaled-font.c36
-rw-r--r--src/cairo-xlib-surface.c23
-rw-r--r--src/cairoint.h6
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,