diff options
author | Andrea Canciani <ranma42@gmail.com> | 2011-01-07 00:19:55 +0100 |
---|---|---|
committer | Andrea Canciani <ranma42@gmail.com> | 2011-01-07 00:19:55 +0100 |
commit | 14afb69d3dc889715451cab6f54ec6ce73b431dd (patch) | |
tree | 8211626426ab80dd06d86c50051327461f2dfa80 | |
parent | 588dead005d69c022245ff017f53ff403b50e9db (diff) |
xlib: Handle a wider range of glyph positions
Backport the change from 588dead005d69c022245ff017f53ff403b50e9db to
Xlib.
-rw-r--r-- | src/cairo-xlib-surface.c | 44 |
1 files changed, 22 insertions, 22 deletions
diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 693ece2c7..8b5980435 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -4514,30 +4514,20 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_display_t *display, if (unlikely (status)) return status; - this_x = _cairo_lround (glyphs[i].d.x); - this_y = _cairo_lround (glyphs[i].d.y); - - /* Glyph skipping: - * - * We skip any glyphs that have troublesome coordinates. We want - * to make sure that (glyph2.x - (glyph1.x + glyph1.width)) fits in - * a signed 16bit integer, otherwise it will overflow in the render - * protocol. - * To ensure this, we'll make sure that (glyph2.x - glyph1.x) fits in - * a signed 15bit integer. The trivial option would be to allow - * coordinates -8192..8192, but that's kinda dull. It probably will - * take a decade or so to get monitors 8192x4096 or something. A - * negative value of -8192 on the other hand, is absolutely useless. - * Note that we do want to allow some negative positions. The glyph - * may start off the screen but part of it make it to the screen. - * Anyway, we will allow positions in the range -4096..122887. That - * will buy us a few more years before this stops working. - * - * Update: upon seeing weird glyphs, we just return and let fallback - * code do the job. + /* The glyph coordinates must be representable in an int16_t. + * When possible, they will be expressed as an offset from the + * previous glyph, otherwise they will be an offset from the + * surface origin. If we can't guarantee this to be possible, + * fallback. */ - if (((this_x+4096)|(this_y+4096))&~0x3fffu) + if (glyphs[i].d.x > INT16_MAX || glyphs[i].d.y > INT16_MAX || + glyphs[i].d.x < INT16_MIN || glyphs[i].d.y < INT16_MIN) + { break; + } + + this_x = _cairo_lround (glyphs[i].d.x); + this_y = _cairo_lround (glyphs[i].d.y); /* Send unsent glyphs to the server */ if (_cairo_xlib_scaled_glyph_get_glyphset_info (scaled_glyph) == NULL) { @@ -4585,8 +4575,18 @@ _cairo_xlib_surface_emit_glyphs (cairo_xlib_display_t *display, * prefer the latter is the fact that Xserver ADDs all glyphs * to the mask first, and then composes that to final surface, * though it's not a big deal. + * + * If the glyph has a coordinate which cannot be represented + * as a 16-bit offset from the previous glyph, flush the + * current chunk. The current glyph will be the first one in + * the next chunk, thus its coordinates will be an offset from + * the destination origin. This offset is guaranteed to be + * representable as 16-bit offset (otherwise we would have + * fallen back). */ if (request_size + width > max_request_size - _cairo_sz_xGlyphElt || + this_x - x > INT16_MAX || this_x - x < INT16_MIN || + this_y - y > INT16_MAX || this_y - y < INT16_MIN || (this_glyphset_info != glyphset_info)) { status = _emit_glyphs_chunk (display, dst, glyphs, i, scaled_font, op, src, attributes, |