composite: Perform a quick is-clipped for glyphs

Computing the exact bbox of the glyphs and whether they are overlapped
is expensive. However, we can often check whether they are visible just
by looking at the maximal extents of the fonts along with the bbox of
the positions; much cheaper.

Signed-off-by: Chris Wilson <chris@chris-wilson.co.uk>
This commit is contained in:
Chris Wilson 2011-07-24 10:03:48 +01:00
parent 05bed4c574
commit dc67d8e7f9
3 changed files with 28 additions and 18 deletions

View file

@ -234,6 +234,17 @@ _cairo_composite_rectangles_init_for_glyphs (cairo_composite_rectangles_t *exten
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
/* Computing the exact bbox and the overlap is expensive.
* First perform a cheap test to see if the glyphs are all clipped out.
*/
if (extents->is_bounded & CAIRO_OPERATOR_BOUND_BY_MASK) {
_cairo_scaled_font_glyph_approximate_extents (scaled_font,
glyphs, num_glyphs,
&extents->mask);
if (! _cairo_rectangle_intersect (&extents->bounded, &extents->mask))
return CAIRO_INT_STATUS_NOTHING_TO_DO;
}
status = _cairo_scaled_font_glyph_device_extents (scaled_font,
glyphs, num_glyphs,
&extents->mask,

View file

@ -2193,11 +2193,14 @@ _cairo_scaled_font_glyph_approximate_extents (cairo_scaled_font_t *scaled_font,
int num_glyphs,
cairo_rectangle_int_t *extents)
{
double x0 = HUGE_VAL, x1 = -HUGE_VAL;
double y0 = HUGE_VAL, y1 = -HUGE_VAL;
double x0, x1, y0, y1, pad;
int i;
for (i = 0; i < num_glyphs; i++) {
assert (num_glyphs);
x0 = x1 = glyphs[0].x;
y0 = y1 = glyphs[0].y;
for (i = 1; i < num_glyphs; i++) {
double g;
g = glyphs[i].x;
@ -2209,18 +2212,14 @@ _cairo_scaled_font_glyph_approximate_extents (cairo_scaled_font_t *scaled_font,
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;
pad = MAX(scaled_font->fs_extents.max_x_advance,
scaled_font->fs_extents.height);
pad *= scaled_font->max_scale;
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;
}
extents->x = floor (x0 - pad);
extents->width = ceil (x1 + pad) - extents->x;
extents->y = floor (y0 - pad);
extents->height = ceil (y1 + pad) - extents->y;
}
cairo_status_t

View file

@ -1060,7 +1060,7 @@ typedef struct {
* portions below the baseline. Note that this is not always
* exactly equal to the maximum of the extents of all the
* glyphs in the font, but rather is picked to express the
* font designer's intent as to how the the font should
* font designer's intent as to how the font should
* align with elements below it.
* @height: the recommended vertical distance between baselines when
* setting consecutive lines of text with the font. This
@ -1070,10 +1070,10 @@ typedef struct {
* is at a premium, most fonts can be set with only
* a distance of @ascent+@descent between lines.
* @max_x_advance: the maximum distance in the X direction that
* the the origin is advanced for any glyph in the font.
* the origin is advanced for any glyph in the font.
* @max_y_advance: the maximum distance in the Y direction that
* the the origin is advanced for any glyph in the font.
* this will be zero for normal fonts used for horizontal
* the origin is advanced for any glyph in the font.
* This will be zero for normal fonts used for horizontal
* writing. (The scripts of East Asia are sometimes written
* vertically.)
*