[util/draw] Render color glyphs if cairo API available
This commit is contained in:
parent
542f8269cb
commit
cfc06c24d5
|
@ -194,6 +194,10 @@ AC_ARG_WITH(cairo,
|
|||
have_cairo=false
|
||||
if test "x$with_cairo" = "xyes" -o "x$with_cairo" = "xauto"; then
|
||||
PKG_CHECK_MODULES(CAIRO, cairo >= 1.8.0, have_cairo=true, :)
|
||||
save_libs=$LIBS
|
||||
LIBS="$LIBS $CAIRO_LIBS"
|
||||
AC_CHECK_FUNCS(cairo_user_font_face_set_render_color_glyph_func)
|
||||
LIBS=$save_libs
|
||||
fi
|
||||
if test "x$with_cairo" = "xyes" -a "x$have_cairo" != "xtrue"; then
|
||||
AC_MSG_ERROR([cairo support requested but not found])
|
||||
|
|
|
@ -186,6 +186,7 @@ endif
|
|||
|
||||
if cairo_dep.found()
|
||||
conf.set('HAVE_CAIRO', 1)
|
||||
check_funcs += [['cairo_user_font_face_set_render_color_glyph_func', {'deps': cairo_dep}]]
|
||||
endif
|
||||
|
||||
if cairo_ft_dep.found()
|
||||
|
|
|
@ -32,6 +32,8 @@
|
|||
#include <cairo.h>
|
||||
#include <hb.h>
|
||||
|
||||
#include "hb-blob.hh"
|
||||
|
||||
static void
|
||||
move_to (hb_draw_funcs_t *dfuncs,
|
||||
cairo_t *cr,
|
||||
|
@ -112,15 +114,99 @@ render_glyph (cairo_scaled_font_t *scaled_font,
|
|||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
#ifdef HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC
|
||||
|
||||
static cairo_status_t
|
||||
_hb_bytes_read_func (hb_bytes_t *src,
|
||||
char *data,
|
||||
unsigned length)
|
||||
{
|
||||
if (unlikely (src->length < length))
|
||||
return CAIRO_STATUS_READ_ERROR;
|
||||
|
||||
memcpy (data, src->arrayZ, length);
|
||||
*src += length;
|
||||
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
static cairo_status_t
|
||||
render_color_glyph (cairo_scaled_font_t *scaled_font,
|
||||
unsigned long glyph,
|
||||
cairo_t *cr,
|
||||
cairo_text_extents_t *extents)
|
||||
{
|
||||
hb_font_t *font = (hb_font_t *) (cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
|
||||
&_hb_font_cairo_user_data_key));
|
||||
|
||||
hb_blob_t *blob = hb_ot_color_glyph_reference_png (font, glyph);
|
||||
if (blob == hb_blob_get_empty ())
|
||||
return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||
|
||||
hb_position_t x_scale, y_scale;
|
||||
hb_font_get_scale (font, &x_scale, &y_scale);
|
||||
cairo_scale (cr, +1./x_scale, -1./y_scale);
|
||||
|
||||
#ifdef CAIRO_HAS_PNG_FUNCTIONS
|
||||
/* Draw PNG. */
|
||||
hb_bytes_t bytes = blob->as_bytes ();
|
||||
cairo_surface_t *surface = cairo_image_surface_create_from_png_stream ((cairo_read_func_t) _hb_bytes_read_func,
|
||||
std::addressof (bytes));
|
||||
hb_blob_destroy (blob);
|
||||
|
||||
if (unlikely (cairo_surface_status (surface)) != CAIRO_STATUS_SUCCESS)
|
||||
{
|
||||
cairo_surface_destroy (surface);
|
||||
return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
int width = cairo_image_surface_get_width (surface);
|
||||
int height = cairo_image_surface_get_width (surface);
|
||||
|
||||
hb_glyph_extents_t hb_extents;
|
||||
if (unlikely (!hb_font_get_glyph_extents (font, glyph, &hb_extents)))
|
||||
{
|
||||
cairo_surface_destroy (surface);
|
||||
return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
cairo_pattern_t *pattern = cairo_pattern_create_for_surface (surface);
|
||||
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_PAD);
|
||||
|
||||
cairo_matrix_t matrix = {(double) width, 0, 0, (double) height, 0, 0};
|
||||
cairo_pattern_set_matrix (pattern, &matrix);
|
||||
|
||||
cairo_translate (cr, hb_extents.x_bearing, hb_extents.y_bearing);
|
||||
cairo_scale (cr, hb_extents.width, hb_extents.height);
|
||||
cairo_set_source (cr, pattern);
|
||||
|
||||
cairo_rectangle (cr, 0, 0, 1, 1);
|
||||
cairo_fill (cr);
|
||||
cairo_pattern_destroy (pattern);
|
||||
|
||||
cairo_surface_destroy (surface);
|
||||
return CAIRO_STATUS_SUCCESS;
|
||||
#endif
|
||||
return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
|
||||
}
|
||||
#endif
|
||||
|
||||
static inline cairo_font_face_t *
|
||||
helper_cairo_create_user_font_face (const font_options_t *font_opts)
|
||||
{
|
||||
cairo_font_face_t *cairo_face = cairo_user_font_face_create ();
|
||||
cairo_user_font_face_set_render_glyph_func (cairo_face, render_glyph);
|
||||
|
||||
cairo_font_face_set_user_data (cairo_face,
|
||||
&_hb_font_cairo_user_data_key,
|
||||
hb_font_reference (font_opts->font),
|
||||
(cairo_destroy_func_t) hb_font_destroy);
|
||||
|
||||
cairo_user_font_face_set_render_glyph_func (cairo_face, render_glyph);
|
||||
#ifdef HAVE_CAIRO_USER_FONT_FACE_SET_RENDER_COLOR_GLYPH_FUNC
|
||||
if (hb_ot_color_has_png (hb_font_get_face (font_opts->font)))
|
||||
cairo_user_font_face_set_render_color_glyph_func (cairo_face, render_color_glyph);
|
||||
#endif
|
||||
|
||||
return cairo_face;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue