Add cairo_scaled_font_text_to_glyphs()

And update user-font text_to_glyphs() method to match.

Currently disable the win32-font text_to_glyphs(), until that one
is updated.  Or better yet, remove it and implement ucs4_to_index().
It's the toy font API afterall.
This commit is contained in:
Behdad Esfahbod 2008-08-07 22:06:15 -04:00
parent b8fc845094
commit d9408041aa
8 changed files with 301 additions and 128 deletions

View file

@ -1445,12 +1445,16 @@ _cairo_gstate_get_font_extents (cairo_gstate_t *gstate,
} }
cairo_status_t cairo_status_t
_cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate, _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
const char *utf8, double x,
double x, double y,
double y, const char *utf8,
cairo_glyph_t **glyphs, int utf8_len,
int *num_glyphs) cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward)
{ {
cairo_status_t status; cairo_status_t status;
@ -1458,8 +1462,11 @@ _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
if (status) if (status)
return status; return status;
return _cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y, return cairo_scaled_font_text_to_glyphs (gstate->scaled_font, x, y,
utf8, glyphs, num_glyphs); utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward);
} }
cairo_status_t cairo_status_t
@ -1536,7 +1543,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
if (num_glyphs <= ARRAY_LENGTH (stack_transformed_glyphs)) { if (num_glyphs <= ARRAY_LENGTH (stack_transformed_glyphs)) {
transformed_glyphs = stack_transformed_glyphs; transformed_glyphs = stack_transformed_glyphs;
} else { } else {
transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t)); transformed_glyphs = cairo_glyph_allocate (num_glyphs);
if (transformed_glyphs == NULL) if (transformed_glyphs == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY); return _cairo_error (CAIRO_STATUS_NO_MEMORY);
} }
@ -1551,6 +1558,10 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
if (status) if (status)
goto CLEANUP_GLYPHS; goto CLEANUP_GLYPHS;
/* Just in case */
if (!clusters)
num_clusters = 0;
/* For really huge font sizes, we can just do path;fill instead of /* For really huge font sizes, we can just do path;fill instead of
* show_glyphs, as show_glyphs would put excess pressure on the cache, * show_glyphs, as show_glyphs would put excess pressure on the cache,
* and moreover, not all components below us correctly handle huge font * and moreover, not all components below us correctly handle huge font
@ -1598,7 +1609,7 @@ _cairo_gstate_show_text_glyphs (cairo_gstate_t *gstate,
CLEANUP_GLYPHS: CLEANUP_GLYPHS:
if (transformed_glyphs != stack_transformed_glyphs) if (transformed_glyphs != stack_transformed_glyphs)
free (transformed_glyphs); cairo_glyph_free (transformed_glyphs);
return status; return status;
} }
@ -1620,7 +1631,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
if (num_glyphs < ARRAY_LENGTH (stack_transformed_glyphs)) if (num_glyphs < ARRAY_LENGTH (stack_transformed_glyphs))
transformed_glyphs = stack_transformed_glyphs; transformed_glyphs = stack_transformed_glyphs;
else else
transformed_glyphs = _cairo_malloc_ab (num_glyphs, sizeof(cairo_glyph_t)); transformed_glyphs = cairo_glyph_allocate (num_glyphs);
if (transformed_glyphs == NULL) if (transformed_glyphs == NULL)
return _cairo_error (CAIRO_STATUS_NO_MEMORY); return _cairo_error (CAIRO_STATUS_NO_MEMORY);
@ -1634,7 +1645,7 @@ _cairo_gstate_glyph_path (cairo_gstate_t *gstate,
CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex); CAIRO_MUTEX_UNLOCK (gstate->scaled_font->mutex);
if (transformed_glyphs != stack_transformed_glyphs) if (transformed_glyphs != stack_transformed_glyphs)
free (transformed_glyphs); cairo_glyph_free (transformed_glyphs);
return status; return status;
} }

View file

@ -1109,7 +1109,7 @@ cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font,
cairo_text_extents_t *extents) cairo_text_extents_t *extents)
{ {
cairo_status_t status; cairo_status_t status;
cairo_glyph_t *glyphs; cairo_glyph_t *glyphs = NULL;
int num_glyphs; int num_glyphs;
if (scaled_font->status) if (scaled_font->status)
@ -1118,7 +1118,11 @@ cairo_scaled_font_text_extents (cairo_scaled_font_t *scaled_font,
if (utf8 == NULL) if (utf8 == NULL)
goto ZERO_EXTENTS; goto ZERO_EXTENTS;
status = _cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0., utf8, &glyphs, &num_glyphs); status = cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0.,
utf8, -1,
&glyphs, &num_glyphs,
NULL, NULL,
NULL);
if (status) if (status)
goto ZERO_EXTENTS; goto ZERO_EXTENTS;
@ -1265,70 +1269,148 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
slim_hidden_def (cairo_scaled_font_glyph_extents); slim_hidden_def (cairo_scaled_font_glyph_extents);
cairo_status_t cairo_status_t
_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font, cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
double x, double x,
double y, double y,
const char *utf8, const char *utf8,
cairo_glyph_t **glyphs, int utf8_len,
int *num_glyphs) cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward)
{ {
int i; int i;
uint32_t *ucs4 = NULL; int num_chars = 0;
const char *p;
cairo_status_t status; cairo_status_t status;
cairo_scaled_glyph_t *scaled_glyph; cairo_glyph_t *orig_glyphs;
cairo_text_cluster_t *orig_clusters;
*num_glyphs = 0;
*glyphs = NULL;
status = scaled_font->status; status = scaled_font->status;
if (status) if (status)
return status; return status;
if (utf8[0] == '\0') /* A slew of sanity checks */
return CAIRO_STATUS_SUCCESS;
/* glyphs and num_glyphs can't be NULL */
if (glyphs == NULL ||
num_glyphs == NULL) {
status = CAIRO_STATUS_NULL_POINTER;
goto BAIL;
}
/* No NULLs for non-NULLs! */
if ((utf8_len && utf8 == NULL) ||
(clusters && num_clusters == NULL) ||
(clusters && backward == NULL)) {
status = CAIRO_STATUS_NULL_POINTER;
goto BAIL;
}
/* A -1 for utf8_len means NUL-terminated */
if (utf8_len == -1)
utf8_len = strlen (utf8);
/* A NULL *glyphs means no prealloced glyphs array */
if (glyphs && *glyphs == NULL)
*num_glyphs = 0;
/* A NULL *clusters means no prealloced clusters array */
if (clusters && *clusters == NULL)
*num_clusters = 0;
if (!clusters && num_clusters) {
num_clusters = NULL;
}
if (backward) {
*backward = FALSE;
}
if (!clusters && backward) {
backward = NULL;
}
/* Apart from that, no negatives */
if (utf8_len < 0 ||
*num_glyphs < 0 ||
(num_clusters && *num_clusters < 0)) {
status = CAIRO_STATUS_NEGATIVE_COUNT;
goto BAIL;
}
if (utf8_len == 0) {
status = CAIRO_STATUS_SUCCESS;
goto BAIL;
}
/* validate input so backend does not have to */
status = _cairo_utf8_to_ucs4 (utf8, utf8_len, NULL, &num_chars);
if (status)
goto BAIL;
CAIRO_MUTEX_LOCK (scaled_font->mutex); CAIRO_MUTEX_LOCK (scaled_font->mutex);
_cairo_scaled_font_freeze_cache (scaled_font); _cairo_scaled_font_freeze_cache (scaled_font);
orig_glyphs = *glyphs;
orig_clusters = clusters ? *clusters : NULL;
if (scaled_font->backend->text_to_glyphs) { if (scaled_font->backend->text_to_glyphs) {
/* validate input so backend does not have to */ status = scaled_font->backend->text_to_glyphs (scaled_font, x, y,
status = _cairo_utf8_to_ucs4 (utf8, -1, NULL, NULL); utf8, utf8_len,
if (status) glyphs, num_glyphs,
goto DONE; clusters, num_clusters,
backward);
status = scaled_font->backend->text_to_glyphs (scaled_font,
x, y, utf8,
glyphs, num_glyphs);
if (status != CAIRO_INT_STATUS_UNSUPPORTED) if (status != CAIRO_INT_STATUS_UNSUPPORTED)
goto DONE; goto DONE;
} }
status = _cairo_utf8_to_ucs4 (utf8, -1, &ucs4, num_glyphs); if (*num_glyphs < num_chars) {
if (status) *glyphs = cairo_glyph_allocate (num_chars);
goto DONE; if (*glyphs == NULL) {
status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto DONE;
}
}
*num_glyphs = num_chars;
*glyphs = (cairo_glyph_t *) _cairo_malloc_ab ((*num_glyphs), sizeof (cairo_glyph_t)); if (clusters) {
if (*num_clusters < num_chars) {
if (*glyphs == NULL) { *clusters = cairo_text_cluster_allocate (num_chars);
status = _cairo_error (CAIRO_STATUS_NO_MEMORY); if (*clusters == NULL) {
goto DONE; status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
goto DONE;
}
}
*num_clusters = num_chars;
} }
for (i = 0; i < *num_glyphs; i++) { p = utf8;
(*glyphs)[i].index = (*scaled_font->backend-> for (i = 0; i < num_chars; i++) {
ucs4_to_index) (scaled_font, ucs4[i]); int num_bytes;
uint32_t unicode;
cairo_scaled_glyph_t *scaled_glyph;
num_bytes = _cairo_utf8_get_char_validated (p, &unicode);
p += num_bytes;
(*glyphs)[i].index = (*scaled_font->backend->ucs4_to_index) (scaled_font, unicode);
(*glyphs)[i].x = x; (*glyphs)[i].x = x;
(*glyphs)[i].y = y; (*glyphs)[i].y = y;
if (clusters) {
(*clusters)[i].num_bytes = num_bytes;
(*clusters)[i].num_glyphs = 1;
}
status = _cairo_scaled_glyph_lookup (scaled_font, status = _cairo_scaled_glyph_lookup (scaled_font,
(*glyphs)[i].index, (*glyphs)[i].index,
CAIRO_SCALED_GLYPH_INFO_METRICS, CAIRO_SCALED_GLYPH_INFO_METRICS,
&scaled_glyph); &scaled_glyph);
if (status) { if (status) {
free (*glyphs);
*glyphs = NULL;
goto DONE; goto DONE;
} }
@ -1336,14 +1418,37 @@ _cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
y += scaled_glyph->metrics.y_advance; y += scaled_glyph->metrics.y_advance;
} }
DONE: DONE: /* error that should be logged on scaled_font happened */
_cairo_scaled_font_thaw_cache (scaled_font); _cairo_scaled_font_thaw_cache (scaled_font);
CAIRO_MUTEX_UNLOCK (scaled_font->mutex); CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
if (ucs4) if (status) {
free (ucs4); *num_glyphs = 0;
if (*glyphs != orig_glyphs) {
cairo_glyph_free (*glyphs);
*glyphs = orig_glyphs;
}
if (clusters) {
*num_clusters = 0;
if (*clusters != orig_clusters) {
cairo_text_cluster_free (*clusters);
*clusters = orig_clusters;
}
}
}
return _cairo_scaled_font_set_error (scaled_font, status); return _cairo_scaled_font_set_error (scaled_font, status);
BAIL: /* error with input arguments */
if (num_glyphs)
*num_glyphs = 0;
if (num_clusters)
*num_clusters = 0;
return status;
} }
/* /*

View file

@ -265,12 +265,16 @@ _cairo_user_ucs4_to_index (void *abstract_font,
} }
static cairo_int_status_t static cairo_int_status_t
_cairo_user_text_to_glyphs (void *abstract_font, _cairo_user_text_to_glyphs (void *abstract_font,
double x, double x,
double y, double y,
const char *utf8, const char *utf8,
cairo_glyph_t **glyphs, int utf8_len,
int *num_glyphs) cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward)
{ {
cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED; cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
@ -280,25 +284,21 @@ _cairo_user_text_to_glyphs (void *abstract_font,
if (face->scaled_font_methods.text_to_glyphs) { if (face->scaled_font_methods.text_to_glyphs) {
int i; int i;
int orig_num_glyphs = *num_glyphs;
*glyphs = NULL;
*num_glyphs = -1;
/* XXX currently user allocs glyphs array but cairo frees it */
status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base, status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
utf8, glyphs, num_glyphs); utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward);
if (status != CAIRO_STATUS_SUCCESS) { if (status != CAIRO_STATUS_SUCCESS)
status = _cairo_scaled_font_set_error (&scaled_font->base, status);
if (*glyphs) {
free (*glyphs);
*glyphs = NULL;
}
return status; return status;
}
if (*num_glyphs < 0) if (*num_glyphs < 0) {
*num_glyphs = orig_num_glyphs;
return CAIRO_INT_STATUS_UNSUPPORTED; return CAIRO_INT_STATUS_UNSUPPORTED;
}
/* Convert from font space to user space and add x,y */ /* Convert from font space to user space and add x,y */
for (i = 0; i < *num_glyphs; i++) { for (i = 0; i < *num_glyphs; i++) {

View file

@ -1780,7 +1780,7 @@ const cairo_scaled_font_backend_t _cairo_win32_scaled_font_backend = {
_cairo_win32_scaled_font_create_toy, _cairo_win32_scaled_font_create_toy,
_cairo_win32_scaled_font_fini, _cairo_win32_scaled_font_fini,
_cairo_win32_scaled_font_glyph_init, _cairo_win32_scaled_font_glyph_init,
_cairo_win32_scaled_font_text_to_glyphs, /* _cairo_win32_scaled_font_text_to_glyphs, FIXME */
NULL, /* ucs4_to_index */ NULL, /* ucs4_to_index */
_cairo_win32_scaled_font_show_glyphs, _cairo_win32_scaled_font_show_glyphs,
_cairo_win32_scaled_font_load_truetype_table, _cairo_win32_scaled_font_load_truetype_table,

View file

@ -3013,16 +3013,18 @@ cairo_text_extents (cairo_t *cr,
cairo_get_current_point (cr, &x, &y); cairo_get_current_point (cr, &x, &y);
status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8, status = _cairo_gstate_text_to_glyphs (cr->gstate,
x, y, x, y,
&glyphs, &num_glyphs); utf8, strlen (utf8),
&glyphs, &num_glyphs,
NULL, NULL,
NULL);
if (status == CAIRO_STATUS_SUCCESS) if (status == CAIRO_STATUS_SUCCESS)
status = _cairo_gstate_glyph_extents (cr->gstate, status = _cairo_gstate_glyph_extents (cr->gstate,
glyphs, num_glyphs, glyphs, num_glyphs,
extents); extents);
if (glyphs) cairo_glyph_free (glyphs);
free (glyphs);
if (status) if (status)
_cairo_set_error (cr, status); _cairo_set_error (cr, status);
@ -3116,7 +3118,9 @@ cairo_show_text (cairo_t *cr, const char *utf8)
cairo_text_extents_t extents; cairo_text_extents_t extents;
cairo_status_t status; cairo_status_t status;
cairo_glyph_t *glyphs = NULL, *last_glyph; cairo_glyph_t *glyphs = NULL, *last_glyph;
int num_glyphs; cairo_text_cluster_t *clusters = NULL;
int utf8_len, num_glyphs, num_clusters;
cairo_bool_t backward;
double x, y; double x, y;
if (cr->status) if (cr->status)
@ -3127,9 +3131,14 @@ cairo_show_text (cairo_t *cr, const char *utf8)
cairo_get_current_point (cr, &x, &y); cairo_get_current_point (cr, &x, &y);
status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8, utf8_len = strlen (utf8);
status = _cairo_gstate_text_to_glyphs (cr->gstate,
x, y, x, y,
&glyphs, &num_glyphs); utf8, utf8_len,
&glyphs, &num_glyphs,
cairo_has_show_text_glyphs (cr) ? &clusters : NULL, &num_clusters,
&backward);
if (status) if (status)
goto BAIL; goto BAIL;
@ -3137,10 +3146,10 @@ cairo_show_text (cairo_t *cr, const char *utf8)
return; return;
status = _cairo_gstate_show_text_glyphs (cr->gstate, status = _cairo_gstate_show_text_glyphs (cr->gstate,
NULL, 0, utf8, utf8_len,
glyphs, num_glyphs, glyphs, num_glyphs,
NULL, 0, clusters, num_clusters,
FALSE); backward);
if (status) if (status)
goto BAIL; goto BAIL;
@ -3156,8 +3165,8 @@ cairo_show_text (cairo_t *cr, const char *utf8)
cairo_move_to (cr, x, y); cairo_move_to (cr, x, y);
BAIL: BAIL:
if (glyphs) cairo_glyph_free (glyphs);
free (glyphs); cairo_text_cluster_free (clusters);
if (status) if (status)
_cairo_set_error (cr, status); _cairo_set_error (cr, status);
@ -3226,6 +3235,14 @@ cairo_show_text_glyphs (cairo_t *cr,
/* A slew of sanity checks */ /* A slew of sanity checks */
/* No NULLs for non-zeros */
if ((num_glyphs && glyphs == NULL) ||
(utf8_len && utf8 == NULL) ||
(num_clusters && clusters == NULL)) {
_cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
return;
}
/* A -1 for utf8_len means NUL-terminated */ /* A -1 for utf8_len means NUL-terminated */
if (utf8_len == -1) if (utf8_len == -1)
utf8_len = strlen (utf8); utf8_len = strlen (utf8);
@ -3236,14 +3253,6 @@ cairo_show_text_glyphs (cairo_t *cr,
return; return;
} }
/* And no NULLs for non-zeros */
if ((num_glyphs && glyphs == NULL) ||
(utf8_len && utf8 == NULL) ||
(num_clusters && clusters == NULL)) {
_cairo_set_error (cr, CAIRO_STATUS_NULL_POINTER);
return;
}
/* Make sure clusters cover the entire glyphs and utf8 arrays, /* Make sure clusters cover the entire glyphs and utf8 arrays,
* and that cluster boundaries are UTF-8 boundaries. */ * and that cluster boundaries are UTF-8 boundaries. */
{ {
@ -3343,9 +3352,12 @@ cairo_text_path (cairo_t *cr, const char *utf8)
cairo_get_current_point (cr, &x, &y); cairo_get_current_point (cr, &x, &y);
status = _cairo_gstate_text_to_glyphs (cr->gstate, utf8, status = _cairo_gstate_text_to_glyphs (cr->gstate,
x, y, x, y,
&glyphs, &num_glyphs); utf8, strlen (utf8),
&glyphs, &num_glyphs,
NULL, NULL,
NULL);
if (status) if (status)
goto BAIL; goto BAIL;
@ -3373,8 +3385,7 @@ cairo_text_path (cairo_t *cr, const char *utf8)
cairo_move_to (cr, x, y); cairo_move_to (cr, x, y);
BAIL: BAIL:
if (glyphs) cairo_glyph_free (glyphs);
free (glyphs);
if (status) if (status)
_cairo_set_error (cr, status); _cairo_set_error (cr, status);

View file

@ -1330,6 +1330,18 @@ cairo_scaled_font_glyph_extents (cairo_scaled_font_t *scaled_font,
int num_glyphs, int num_glyphs,
cairo_text_extents_t *extents); cairo_text_extents_t *extents);
cairo_public cairo_status_t
cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
double x,
double y,
const char *utf8,
int utf8_len,
cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward);
cairo_public cairo_font_face_t * cairo_public cairo_font_face_t *
cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font); cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font);
@ -1468,6 +1480,7 @@ typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scal
* @glyphs: output array of glyphs, in font space * @glyphs: output array of glyphs, in font space
* @num_glyphs: number of output glyphs * @num_glyphs: number of output glyphs
* *
* XXXXXXXXXXXXX
* #cairo_user_scaled_font_text_to_glyphs_func_t is the type of function which * #cairo_user_scaled_font_text_to_glyphs_func_t is the type of function which
* is called to convert input text to an array of glyphs. This is used by the * is called to convert input text to an array of glyphs. This is used by the
* cairo_show_text() operation. * cairo_show_text() operation.
@ -1496,9 +1509,13 @@ typedef cairo_status_t (*cairo_user_scaled_font_render_glyph_func_t) (cairo_scal
* Since: 1.8 * Since: 1.8
**/ **/
typedef cairo_status_t (*cairo_user_scaled_font_text_to_glyphs_func_t) (cairo_scaled_font_t *scaled_font, typedef cairo_status_t (*cairo_user_scaled_font_text_to_glyphs_func_t) (cairo_scaled_font_t *scaled_font,
const char *utf8, const char *utf8,
cairo_glyph_t **glyphs, int utf8_len,
int *num_glyphs); cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward);
/** /**
* cairo_user_scaled_font_unicode_to_glyph_func_t: * cairo_user_scaled_font_unicode_to_glyph_func_t:

View file

@ -408,12 +408,16 @@ struct _cairo_scaled_font_backend {
* then just converting characters one by one. * then just converting characters one by one.
*/ */
cairo_warn cairo_int_status_t cairo_warn cairo_int_status_t
(*text_to_glyphs) (void *scaled_font, (*text_to_glyphs) (void *scaled_font,
double x, double x,
double y, double y,
const char *utf8, const char *utf8,
cairo_glyph_t **glyphs, int utf8_len,
int *num_glyphs); cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward);
unsigned long unsigned long
(*ucs4_to_index) (void *scaled_font, (*ucs4_to_index) (void *scaled_font,
@ -1219,12 +1223,16 @@ _cairo_gstate_set_font_face (cairo_gstate_t *gstate,
cairo_font_face_t *font_face); cairo_font_face_t *font_face);
cairo_private cairo_status_t cairo_private cairo_status_t
_cairo_gstate_text_to_glyphs (cairo_gstate_t *font, _cairo_gstate_text_to_glyphs (cairo_gstate_t *gstate,
const char *utf8, double x,
double x, double y,
double y, const char *utf8,
cairo_glyph_t **glyphs, int utf8_len,
int *num_glyphs); cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward);
cairo_private cairo_status_t cairo_private cairo_status_t
_cairo_gstate_glyph_extents (cairo_gstate_t *gstate, _cairo_gstate_glyph_extents (cairo_gstate_t *gstate,
@ -1528,14 +1536,6 @@ cairo_private cairo_status_t
_cairo_scaled_font_font_extents (cairo_scaled_font_t *scaled_font, _cairo_scaled_font_font_extents (cairo_scaled_font_t *scaled_font,
cairo_font_extents_t *extents); cairo_font_extents_t *extents);
cairo_private cairo_status_t
_cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
double x,
double y,
const char *utf8,
cairo_glyph_t **glyphs,
int *num_glyphs);
cairo_private cairo_status_t cairo_private cairo_status_t
_cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font, _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t *scaled_font,
const cairo_glyph_t *glyphs, const cairo_glyph_t *glyphs,

View file

@ -51,7 +51,7 @@ cairo_test_t test = {
draw draw
}; };
static cairo_user_data_key_t fallback_font_face_key; static cairo_user_data_key_t fallback_font_key;
static cairo_status_t static cairo_status_t
test_scaled_font_init (cairo_scaled_font_t *scaled_font, test_scaled_font_init (cairo_scaled_font_t *scaled_font,
@ -60,7 +60,12 @@ test_scaled_font_init (cairo_scaled_font_t *scaled_font,
{ {
cairo_set_font_face (cr, cairo_set_font_face (cr,
cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font), cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
&fallback_font_face_key)); &fallback_font_key));
cairo_scaled_font_set_user_data (scaled_font,
&fallback_font_key,
cairo_scaled_font_reference (cairo_get_scaled_font (cr)),
(cairo_destroy_func_t) cairo_scaled_font_destroy);
cairo_font_extents (cr, extents); cairo_font_extents (cr, extents);
@ -73,21 +78,44 @@ test_scaled_font_render_glyph (cairo_scaled_font_t *scaled_font,
cairo_t *cr, cairo_t *cr,
cairo_text_extents_t *extents) cairo_text_extents_t *extents)
{ {
char text[2] = "\0"; cairo_glyph_t cairo_glyph;
/* XXX only works for ASCII. need ucs4_to_utf8 :( */ cairo_glyph.index = glyph;
text[0] = glyph; cairo_glyph.x = 0;
cairo_glyph.y = 0;
cairo_set_font_face (cr, cairo_set_font_face (cr,
cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font), cairo_font_face_get_user_data (cairo_scaled_font_get_font_face (scaled_font),
&fallback_font_face_key)); &fallback_font_key));
cairo_show_text (cr, text); cairo_show_glyphs (cr, &cairo_glyph, 1);
cairo_text_extents (cr, text, extents); cairo_glyph_extents (cr, &cairo_glyph, 1, extents);
return CAIRO_STATUS_SUCCESS; return CAIRO_STATUS_SUCCESS;
} }
static cairo_status_t
test_scaled_font_text_to_glyphs (cairo_scaled_font_t *scaled_font,
const char *utf8,
int utf8_len,
cairo_glyph_t **glyphs,
int *num_glyphs,
cairo_text_cluster_t **clusters,
int *num_clusters,
cairo_bool_t *backward)
{
cairo_scaled_font_t *fallback_scaled_font;
fallback_scaled_font = cairo_scaled_font_get_user_data (scaled_font,
&fallback_font_key);
return cairo_scaled_font_text_to_glyphs (fallback_scaled_font, 0, 0,
utf8, utf8_len,
glyphs, num_glyphs,
clusters, num_clusters,
backward);
}
static cairo_font_face_t *user_font_face = NULL; static cairo_font_face_t *user_font_face = NULL;
static cairo_font_face_t * static cairo_font_face_t *
@ -99,6 +127,7 @@ get_user_font_face (void)
user_font_face = cairo_user_font_face_create (); user_font_face = cairo_user_font_face_create ();
cairo_user_font_face_set_init_func (user_font_face, test_scaled_font_init); cairo_user_font_face_set_init_func (user_font_face, test_scaled_font_init);
cairo_user_font_face_set_render_glyph_func (user_font_face, test_scaled_font_render_glyph); cairo_user_font_face_set_render_glyph_func (user_font_face, test_scaled_font_render_glyph);
cairo_user_font_face_set_text_to_glyphs_func (user_font_face, test_scaled_font_text_to_glyphs);
/* This also happens to be default font face on cairo_t, so does /* This also happens to be default font face on cairo_t, so does
* not make much sense here. For demonstration only. * not make much sense here. For demonstration only.
@ -108,9 +137,9 @@ get_user_font_face (void)
CAIRO_FONT_WEIGHT_NORMAL); CAIRO_FONT_WEIGHT_NORMAL);
cairo_font_face_set_user_data (user_font_face, cairo_font_face_set_user_data (user_font_face,
&fallback_font_face_key, &fallback_font_key,
fallback_font_face, fallback_font_face,
cairo_font_face_destroy); (cairo_destroy_func_t) cairo_font_face_destroy);
} }
return user_font_face; return user_font_face;