mirror of
https://gitlab.freedesktop.org/cairo/cairo.git
synced 2026-01-02 21:40:15 +01:00
[gl] Fallback for overlapping glyphs.
This commit is contained in:
parent
3d8f1d3dc8
commit
cd259489e2
8 changed files with 66 additions and 23 deletions
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue