From cd259489e2f41caaa7441233d87b46fbd43991ae Mon Sep 17 00:00:00 2001 From: Chris Wilson Date: Tue, 28 Jul 2009 15:58:54 +0100 Subject: [gl] Fallback for overlapping glyphs. --- src/cairo-analysis-surface.c | 6 ++++-- src/cairo-gl-glyphs.c | 35 ++++++++++++++++++++--------------- src/cairo-gl-private.h | 13 +++++++++++++ src/cairo-scaled-font.c | 23 +++++++++++++++++++++-- src/cairo-surface-fallback.c | 3 ++- src/cairo-xcb-surface.c | 3 ++- src/cairo-xlib-surface.c | 3 ++- src/cairoint.h | 3 ++- 8 files changed, 66 insertions(+), 23 deletions(-) (limited to 'src') diff --git a/src/cairo-analysis-surface.c b/src/cairo-analysis-surface.c index eb1e87d4..5faa1b96 100644 --- a/src/cairo-analysis-surface.c +++ b/src/cairo-analysis-surface.c @@ -568,7 +568,8 @@ _cairo_analysis_surface_show_glyphs (void *abstract_surface, status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs, - &glyph_extents); + &glyph_extents, + NULL); if (unlikely (status)) return status; @@ -651,7 +652,8 @@ _cairo_analysis_surface_show_text_glyphs (void *abstract_surface, status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs, - &glyph_extents); + &glyph_extents, + NULL); if (unlikely (status)) return status; diff --git a/src/cairo-gl-glyphs.c b/src/cairo-gl-glyphs.c index 2e8cf777..5be984f9 100644 --- a/src/cairo-gl-glyphs.c +++ b/src/cairo-gl-glyphs.c @@ -344,18 +344,19 @@ _cairo_gl_surface_show_glyphs (void *abstract_dst, cairo_solid_pattern_t solid_pattern; cairo_gl_glyphs_setup_t setup; cairo_gl_composite_setup_t composite_setup; + cairo_bool_t overlap; GLuint vbo = 0; if (! GLEW_ARB_vertex_buffer_object) - return CAIRO_INT_STATUS_UNSUPPORTED; + return UNSUPPORTED ("requires ARB_vertex_buffer_object"); if (! _cairo_gl_operator_is_supported (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; + return UNSUPPORTED ("unsupported operator"); /* Just let unbounded operators go through the fallback code * instead of trying to do the fixups here */ if (! _cairo_operator_bounded_by_mask (op)) - return CAIRO_INT_STATUS_UNSUPPORTED; + return UNSUPPORTED ("unhandled unbound operator"); /* For CLEAR, cairo's rendering equation (quoting Owen's description in: * http://lists.cairographics.org/archives/cairo/2005-August/004992.html) @@ -404,34 +405,38 @@ _cairo_gl_surface_show_glyphs (void *abstract_dst, * But for now, fall back :) */ if (op == CAIRO_OPERATOR_SOURCE) - return CAIRO_INT_STATUS_UNSUPPORTED; + return UNSUPPORTED ("not handling SOURCE operator"); /* XXX we don't need ownership of the font as we use a global * glyph cache -- but we do need scaled_glyph eviction notification. :-( */ if (! _cairo_gl_surface_owns_font (dst, scaled_font)) - return CAIRO_INT_STATUS_UNSUPPORTED; + return UNSUPPORTED ("do not control font"); if (clip != NULL) { status = _cairo_clip_get_region (clip, &clip_region); - if (status == CAIRO_INT_STATUS_NOTHING_TO_DO) - return CAIRO_STATUS_SUCCESS; - else if (status != CAIRO_STATUS_SUCCESS) + /* the empty clip should never be propagated this far */ + assert (status != CAIRO_INT_STATUS_NOTHING_TO_DO); + if (unlikely (_cairo_status_is_error (status))) return status; + if (status == CAIRO_INT_STATUS_UNSUPPORTED) + return UNSUPPORTED ("unhandled clipmask"); } - /* XXX If glyphs overlap, build tmp mask and composite. - * Could we use the stencil instead but only write if alpha !=0 ? - * TEXKILL? PIXELKILL? - * Antialiasing issues - but using glyph images cause their own anyway. - */ - status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs, - &extents); + &extents, + &overlap); if (unlikely (status)) return status; + /* If the glyphs overlap, we need to build an intermediate mask rather + * then compositing directly. + * For the time being, just fallback. + */ + if (overlap) + return UNSUPPORTED ("overlapping glyphs"); + status = _cairo_gl_operand_init (&composite_setup.src, source, dst, extents.x, extents.y, extents.x, extents.y, diff --git a/src/cairo-gl-private.h b/src/cairo-gl-private.h index e8988eb3..378272bc 100644 --- a/src/cairo-gl-private.h +++ b/src/cairo-gl-private.h @@ -50,6 +50,19 @@ #define GL_GLEXT_PROTOTYPES #include +#define DEBUG_GL 0 + +#if DEBUG_GL && __GNUC__ +#define UNSUPPORTED(reason) ({ \ + fprintf (stderr, \ + "cairo-gl: hit unsupported operation in %s(), line %d: %s\n", \ + __FUNCTION__, __LINE__, reason); \ + CAIRO_INT_STATUS_UNSUPPORTED; \ +}) +#else +#define UNSUPPORTED(reason) CAIRO_INT_STATUS_UNSUPPORTED +#endif + typedef struct _cairo_gl_surface { cairo_surface_t base; diff --git a/src/cairo-scaled-font.c b/src/cairo-scaled-font.c index 2b5b26dd..3238c848 100644 --- a/src/cairo-scaled-font.c +++ b/src/cairo-scaled-font.c @@ -1902,6 +1902,15 @@ cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, } slim_hidden_def (cairo_scaled_font_text_to_glyphs); +static inline cairo_bool_t +_range_contains_glyph (const cairo_point_int_t *min, + const cairo_point_int_t *max, + int left, int top, + int right, int bottom) +{ + return right > min->x && left < max->x && bottom > min->y && top < max->y; +} + /* * Compute a device-space bounding box for the glyphs. */ @@ -1909,13 +1918,15 @@ cairo_status_t _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, const cairo_glyph_t *glyphs, int num_glyphs, - cairo_rectangle_int_t *extents) + cairo_rectangle_int_t *extents, + cairo_bool_t *overlap_out) { cairo_status_t status = CAIRO_STATUS_SUCCESS; - int i; cairo_point_int_t min = { CAIRO_RECT_INT_MAX, CAIRO_RECT_INT_MAX }; cairo_point_int_t max = { CAIRO_RECT_INT_MIN, CAIRO_RECT_INT_MIN }; cairo_scaled_glyph_t *glyph_cache[64]; + cairo_bool_t overlap = overlap_out ? FALSE : TRUE; + int i; if (unlikely (scaled_font->status)) return scaled_font->status; @@ -1954,6 +1965,11 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, right = x + _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x); bottom = y + _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y); + if (overlap == FALSE) { + overlap = _range_contains_glyph (&min, &max, + left, top, right, bottom); + } + if (left < min.x) min.x = left; if (right > max.x) max.x = right; if (top < min.y) min.y = top; @@ -1974,6 +1990,9 @@ _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, extents->width = extents->height = 0; } + if (overlap_out != NULL) + *overlap_out = overlap; + return CAIRO_STATUS_SUCCESS; } diff --git a/src/cairo-surface-fallback.c b/src/cairo-surface-fallback.c index 9867eea8..3bfb17de 100644 --- a/src/cairo-surface-fallback.c +++ b/src/cairo-surface-fallback.c @@ -1151,7 +1151,8 @@ _cairo_surface_fallback_show_glyphs (cairo_surface_t *surface, status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs, - &glyph_extents); + &glyph_extents, + NULL); if (unlikely (status)) return status; diff --git a/src/cairo-xcb-surface.c b/src/cairo-xcb-surface.c index 0650f8f6..7c5731f4 100644 --- a/src/cairo-xcb-surface.c +++ b/src/cairo-xcb-surface.c @@ -2558,7 +2558,8 @@ _cairo_xcb_surface_show_glyphs (void *abstract_dst, status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs, - &glyph_extents); + &glyph_extents, + NULL); if (status) goto BAIL; diff --git a/src/cairo-xlib-surface.c b/src/cairo-xlib-surface.c index 4bc244a5..edcb5e63 100644 --- a/src/cairo-xlib-surface.c +++ b/src/cairo-xlib-surface.c @@ -4196,7 +4196,8 @@ _cairo_xlib_surface_show_glyphs (void *abstract_dst, status = _cairo_scaled_font_glyph_device_extents (scaled_font, glyphs, num_glyphs, - &glyph_extents); + &glyph_extents, + NULL); if (unlikely (status)) goto BAIL0; diff --git a/src/cairoint.h b/src/cairoint.h index 6010e20f..4f839777 100644 --- a/src/cairoint.h +++ b/src/cairoint.h @@ -1673,7 +1673,8 @@ cairo_private cairo_status_t _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, const cairo_glyph_t *glyphs, int num_glyphs, - cairo_rectangle_int_t *extents); + cairo_rectangle_int_t *extents, + cairo_bool_t *overlap); cairo_private cairo_status_t _cairo_scaled_font_show_glyphs (cairo_scaled_font_t *scaled_font, -- cgit v1.2.3