[gl] Fallback for overlapping glyphs.

This commit is contained in:
Chris Wilson 2009-07-28 15:58:54 +01:00
parent 3d8f1d3dc8
commit cd259489e2
8 changed files with 66 additions and 23 deletions

View file

@ -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;

View file

@ -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,

View file

@ -50,6 +50,19 @@
#define GL_GLEXT_PROTOTYPES
#include <GL/glext.h>
#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;

View file

@ -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;
}

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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,