beta-0.89.2
[luatex.git] / source / libs / cairo / cairo-src / src / cairo-user-font.c
blob6d2de2097d5039b69b27273d378ed2847b69d785
1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2006, 2008 Red Hat, Inc
5 * This library is free software; you can redistribute it and/or
6 * modify it either under the terms of the GNU Lesser General Public
7 * License version 2.1 as published by the Free Software Foundation
8 * (the "LGPL") or, at your option, under the terms of the Mozilla
9 * Public License Version 1.1 (the "MPL"). If you do not alter this
10 * notice, a recipient may use your version of this file under either
11 * the MPL or the LGPL.
13 * You should have received a copy of the LGPL along with this library
14 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16 * You should have received a copy of the MPL along with this library
17 * in the file COPYING-MPL-1.1
19 * The contents of this file are subject to the Mozilla Public License
20 * Version 1.1 (the "License"); you may not use this file except in
21 * compliance with the License. You may obtain a copy of the License at
22 * http://www.mozilla.org/MPL/
24 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26 * the specific language governing rights and limitations.
28 * The Original Code is the cairo graphics library.
30 * The Initial Developer of the Original Code is Red Hat, Inc.
32 * Contributor(s):
33 * Kristian Høgsberg <krh@redhat.com>
34 * Behdad Esfahbod <behdad@behdad.org>
37 #include "cairoint.h"
38 #include "cairo-user-font-private.h"
39 #include "cairo-recording-surface-private.h"
40 #include "cairo-analysis-surface-private.h"
41 #include "cairo-error-private.h"
43 /**
44 * SECTION:cairo-user-fonts
45 * @Title:User Fonts
46 * @Short_Description: Font support with font data provided by the user
48 * The user-font feature allows the cairo user to provide drawings for glyphs
49 * in a font. This is most useful in implementing fonts in non-standard
50 * formats, like SVG fonts and Flash fonts, but can also be used by games and
51 * other application to draw "funky" fonts.
52 **/
54 /**
55 * CAIRO_HAS_USER_FONT:
57 * Defined if the user font backend is available.
58 * This macro can be used to conditionally compile backend-specific code.
59 * The user font backend is always built in versions of cairo that support
60 * this feature (1.8 and later).
62 * Since: 1.8
63 **/
65 typedef struct _cairo_user_scaled_font_methods {
66 cairo_user_scaled_font_init_func_t init;
67 cairo_user_scaled_font_render_glyph_func_t render_glyph;
68 cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph;
69 cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs;
70 } cairo_user_scaled_font_methods_t;
72 typedef struct _cairo_user_font_face {
73 cairo_font_face_t base;
75 /* Set to true after first scaled font is created. At that point,
76 * the scaled_font_methods cannot change anymore. */
77 cairo_bool_t immutable;
79 cairo_user_scaled_font_methods_t scaled_font_methods;
80 } cairo_user_font_face_t;
82 typedef struct _cairo_user_scaled_font {
83 cairo_scaled_font_t base;
85 cairo_text_extents_t default_glyph_extents;
87 /* space to compute extents in, and factors to convert back to user space */
88 cairo_matrix_t extent_scale;
89 double extent_x_scale;
90 double extent_y_scale;
92 /* multiplier for metrics hinting */
93 double snap_x_scale;
94 double snap_y_scale;
96 } cairo_user_scaled_font_t;
98 /* #cairo_user_scaled_font_t */
100 static cairo_surface_t *
101 _cairo_user_scaled_font_create_recording_surface (const cairo_user_scaled_font_t *scaled_font)
103 cairo_content_t content;
105 content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ?
106 CAIRO_CONTENT_COLOR_ALPHA :
107 CAIRO_CONTENT_ALPHA;
109 return cairo_recording_surface_create (content, NULL);
113 static cairo_t *
114 _cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t *scaled_font,
115 cairo_surface_t *recording_surface)
117 cairo_t *cr;
119 cr = cairo_create (recording_surface);
121 if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
122 cairo_matrix_t scale;
123 scale = scaled_font->base.scale;
124 scale.x0 = scale.y0 = 0.;
125 cairo_set_matrix (cr, &scale);
128 cairo_set_font_size (cr, 1.0);
129 cairo_set_font_options (cr, &scaled_font->base.options);
130 cairo_set_source_rgb (cr, 1., 1., 1.);
132 return cr;
135 static cairo_int_status_t
136 _cairo_user_scaled_glyph_init (void *abstract_font,
137 cairo_scaled_glyph_t *scaled_glyph,
138 cairo_scaled_glyph_info_t info)
140 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
141 cairo_user_scaled_font_t *scaled_font = abstract_font;
142 cairo_surface_t *recording_surface = scaled_glyph->recording_surface;
144 if (!scaled_glyph->recording_surface) {
145 cairo_user_font_face_t *face =
146 (cairo_user_font_face_t *) scaled_font->base.font_face;
147 cairo_text_extents_t extents = scaled_font->default_glyph_extents;
148 cairo_t *cr;
150 if (!face->scaled_font_methods.render_glyph)
151 return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
153 recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font);
155 /* special case for 0 rank matrix (as in _cairo_scaled_font_init): empty surface */
156 if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
157 cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface);
158 status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
159 _cairo_scaled_glyph_index(scaled_glyph),
160 cr, &extents);
161 if (status == CAIRO_INT_STATUS_SUCCESS)
162 status = cairo_status (cr);
164 cairo_destroy (cr);
166 if (unlikely (status)) {
167 cairo_surface_destroy (recording_surface);
168 return status;
172 _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
173 &scaled_font->base,
174 recording_surface);
177 /* set metrics */
179 if (extents.width == 0.) {
180 cairo_box_t bbox;
181 double x1, y1, x2, y2;
182 double x_scale, y_scale;
184 /* Compute extents.x/y/width/height from recording_surface,
185 * in font space.
187 status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
188 &bbox,
189 &scaled_font->extent_scale);
190 if (unlikely (status))
191 return status;
193 _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
195 x_scale = scaled_font->extent_x_scale;
196 y_scale = scaled_font->extent_y_scale;
197 extents.x_bearing = x1 * x_scale;
198 extents.y_bearing = y1 * y_scale;
199 extents.width = (x2 - x1) * x_scale;
200 extents.height = (y2 - y1) * y_scale;
203 if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
204 extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale;
205 extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale;
208 _cairo_scaled_glyph_set_metrics (scaled_glyph,
209 &scaled_font->base,
210 &extents);
213 if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
214 cairo_surface_t *surface;
215 cairo_format_t format;
216 int width, height;
218 /* TODO
219 * extend the glyph cache to support argb glyphs.
220 * need to figure out the semantics and interaction with subpixel
221 * rendering first.
224 width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
225 _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
226 height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
227 _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
229 switch (scaled_font->base.options.antialias) {
230 default:
231 case CAIRO_ANTIALIAS_DEFAULT:
232 case CAIRO_ANTIALIAS_FAST:
233 case CAIRO_ANTIALIAS_GOOD:
234 case CAIRO_ANTIALIAS_GRAY: format = CAIRO_FORMAT_A8; break;
235 case CAIRO_ANTIALIAS_NONE: format = CAIRO_FORMAT_A1; break;
236 case CAIRO_ANTIALIAS_BEST:
237 case CAIRO_ANTIALIAS_SUBPIXEL: format = CAIRO_FORMAT_ARGB32; break;
239 surface = cairo_image_surface_create (format, width, height);
241 cairo_surface_set_device_offset (surface,
242 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
243 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
244 status = _cairo_recording_surface_replay (recording_surface, surface);
246 if (unlikely (status)) {
247 cairo_surface_destroy(surface);
248 return status;
251 _cairo_scaled_glyph_set_surface (scaled_glyph,
252 &scaled_font->base,
253 (cairo_image_surface_t *) surface);
256 if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
257 cairo_path_fixed_t *path = _cairo_path_fixed_create ();
258 if (!path)
259 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
261 status = _cairo_recording_surface_get_path (recording_surface, path);
262 if (unlikely (status)) {
263 _cairo_path_fixed_destroy (path);
264 return status;
267 _cairo_scaled_glyph_set_path (scaled_glyph,
268 &scaled_font->base,
269 path);
272 return status;
275 static unsigned long
276 _cairo_user_ucs4_to_index (void *abstract_font,
277 uint32_t ucs4)
279 cairo_user_scaled_font_t *scaled_font = abstract_font;
280 cairo_user_font_face_t *face =
281 (cairo_user_font_face_t *) scaled_font->base.font_face;
282 unsigned long glyph = 0;
284 if (face->scaled_font_methods.unicode_to_glyph) {
285 cairo_status_t status;
287 status = face->scaled_font_methods.unicode_to_glyph (&scaled_font->base,
288 ucs4, &glyph);
290 if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
291 goto not_implemented;
293 if (status != CAIRO_STATUS_SUCCESS) {
294 status = _cairo_scaled_font_set_error (&scaled_font->base, status);
295 glyph = 0;
298 } else {
299 not_implemented:
300 glyph = ucs4;
303 return glyph;
306 static cairo_int_status_t
307 _cairo_user_text_to_glyphs (void *abstract_font,
308 double x,
309 double y,
310 const char *utf8,
311 int utf8_len,
312 cairo_glyph_t **glyphs,
313 int *num_glyphs,
314 cairo_text_cluster_t **clusters,
315 int *num_clusters,
316 cairo_text_cluster_flags_t *cluster_flags)
318 cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
320 cairo_user_scaled_font_t *scaled_font = abstract_font;
321 cairo_user_font_face_t *face =
322 (cairo_user_font_face_t *) scaled_font->base.font_face;
324 if (face->scaled_font_methods.text_to_glyphs) {
325 int i;
326 cairo_glyph_t *orig_glyphs = *glyphs;
327 int orig_num_glyphs = *num_glyphs;
329 status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
330 utf8, utf8_len,
331 glyphs, num_glyphs,
332 clusters, num_clusters, cluster_flags);
334 if (status != CAIRO_INT_STATUS_SUCCESS &&
335 status != CAIRO_INT_STATUS_USER_FONT_NOT_IMPLEMENTED)
336 return status;
338 if (status == CAIRO_INT_STATUS_USER_FONT_NOT_IMPLEMENTED ||
339 *num_glyphs < 0) {
340 if (orig_glyphs != *glyphs) {
341 cairo_glyph_free (*glyphs);
342 *glyphs = orig_glyphs;
344 *num_glyphs = orig_num_glyphs;
345 return CAIRO_INT_STATUS_UNSUPPORTED;
348 /* Convert from font space to user space and add x,y */
349 for (i = 0; i < *num_glyphs; i++) {
350 double gx = (*glyphs)[i].x;
351 double gy = (*glyphs)[i].y;
353 cairo_matrix_transform_point (&scaled_font->base.font_matrix,
354 &gx, &gy);
356 (*glyphs)[i].x = gx + x;
357 (*glyphs)[i].y = gy + y;
361 return status;
364 static cairo_status_t
365 _cairo_user_font_face_scaled_font_create (void *abstract_face,
366 const cairo_matrix_t *font_matrix,
367 const cairo_matrix_t *ctm,
368 const cairo_font_options_t *options,
369 cairo_scaled_font_t **scaled_font);
371 static cairo_status_t
372 _cairo_user_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
373 cairo_font_face_t **font_face)
375 return _cairo_font_face_twin_create_for_toy (toy_face, font_face);
378 static const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = {
379 CAIRO_FONT_TYPE_USER,
380 NULL, /* scaled_font_fini */
381 _cairo_user_scaled_glyph_init,
382 _cairo_user_text_to_glyphs,
383 _cairo_user_ucs4_to_index,
384 NULL, /* show_glyphs */
385 NULL, /* load_truetype_table */
386 NULL /* index_to_ucs4 */
389 /* #cairo_user_font_face_t */
391 static cairo_status_t
392 _cairo_user_font_face_scaled_font_create (void *abstract_face,
393 const cairo_matrix_t *font_matrix,
394 const cairo_matrix_t *ctm,
395 const cairo_font_options_t *options,
396 cairo_scaled_font_t **scaled_font)
398 cairo_status_t status = CAIRO_STATUS_SUCCESS;
399 cairo_user_font_face_t *font_face = abstract_face;
400 cairo_user_scaled_font_t *user_scaled_font = NULL;
401 cairo_font_extents_t font_extents = {1., 0., 1., 1., 0.};
403 font_face->immutable = TRUE;
405 user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t));
406 if (unlikely (user_scaled_font == NULL))
407 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
409 status = _cairo_scaled_font_init (&user_scaled_font->base,
410 &font_face->base,
411 font_matrix, ctm, options,
412 &_cairo_user_scaled_font_backend);
414 if (unlikely (status)) {
415 free (user_scaled_font);
416 return status;
419 /* XXX metrics hinting? */
421 /* compute a normalized version of font scale matrix to compute
422 * extents in. This is to minimize error caused by the cairo_fixed_t
423 * representation. */
425 double fixed_scale, x_scale, y_scale;
427 user_scaled_font->extent_scale = user_scaled_font->base.scale_inverse;
428 status = _cairo_matrix_compute_basis_scale_factors (&user_scaled_font->extent_scale,
429 &x_scale, &y_scale,
431 if (status == CAIRO_STATUS_SUCCESS) {
433 if (x_scale == 0) x_scale = 1.;
434 if (y_scale == 0) y_scale = 1.;
436 user_scaled_font->snap_x_scale = x_scale;
437 user_scaled_font->snap_y_scale = y_scale;
439 /* since glyphs are pretty much 1.0x1.0, we can reduce error by
440 * scaling to a larger square. say, 1024.x1024. */
441 fixed_scale = 1024.;
442 x_scale /= fixed_scale;
443 y_scale /= fixed_scale;
445 cairo_matrix_scale (&user_scaled_font->extent_scale, 1. / x_scale, 1. / y_scale);
447 user_scaled_font->extent_x_scale = x_scale;
448 user_scaled_font->extent_y_scale = y_scale;
452 if (status == CAIRO_STATUS_SUCCESS &&
453 font_face->scaled_font_methods.init != NULL)
455 /* Lock the scaled_font mutex such that user doesn't accidentally try
456 * to use it just yet. */
457 CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex);
459 /* Give away fontmap lock such that user-font can use other fonts */
460 status = _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base);
461 if (status == CAIRO_STATUS_SUCCESS) {
462 cairo_surface_t *recording_surface;
463 cairo_t *cr;
465 recording_surface = _cairo_user_scaled_font_create_recording_surface (user_scaled_font);
466 cr = _cairo_user_scaled_font_create_recording_context (user_scaled_font, recording_surface);
467 cairo_surface_destroy (recording_surface);
469 status = font_face->scaled_font_methods.init (&user_scaled_font->base,
471 &font_extents);
473 if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
474 status = CAIRO_STATUS_SUCCESS;
476 if (status == CAIRO_STATUS_SUCCESS)
477 status = cairo_status (cr);
479 cairo_destroy (cr);
481 _cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base);
484 CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex);
487 if (status == CAIRO_STATUS_SUCCESS)
488 status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
490 if (status != CAIRO_STATUS_SUCCESS) {
491 _cairo_scaled_font_fini (&user_scaled_font->base);
492 free (user_scaled_font);
493 } else {
494 user_scaled_font->default_glyph_extents.x_bearing = 0.;
495 user_scaled_font->default_glyph_extents.y_bearing = -font_extents.ascent;
496 user_scaled_font->default_glyph_extents.width = 0.;
497 user_scaled_font->default_glyph_extents.height = font_extents.ascent + font_extents.descent;
498 user_scaled_font->default_glyph_extents.x_advance = font_extents.max_x_advance;
499 user_scaled_font->default_glyph_extents.y_advance = 0.;
501 *scaled_font = &user_scaled_font->base;
504 return status;
507 const cairo_font_face_backend_t _cairo_user_font_face_backend = {
508 CAIRO_FONT_TYPE_USER,
509 _cairo_user_font_face_create_for_toy,
510 _cairo_font_face_destroy,
511 _cairo_user_font_face_scaled_font_create
515 cairo_bool_t
516 _cairo_font_face_is_user (cairo_font_face_t *font_face)
518 return font_face->backend == &_cairo_user_font_face_backend;
521 /* Implement the public interface */
524 * cairo_user_font_face_create:
526 * Creates a new user font-face.
528 * Use the setter functions to associate callbacks with the returned
529 * user font. The only mandatory callback is render_glyph.
531 * After the font-face is created, the user can attach arbitrary data
532 * (the actual font data) to it using cairo_font_face_set_user_data()
533 * and access it from the user-font callbacks by using
534 * cairo_scaled_font_get_font_face() followed by
535 * cairo_font_face_get_user_data().
537 * Return value: a newly created #cairo_font_face_t. Free with
538 * cairo_font_face_destroy() when you are done using it.
540 * Since: 1.8
542 cairo_font_face_t *
543 cairo_user_font_face_create (void)
545 cairo_user_font_face_t *font_face;
547 font_face = malloc (sizeof (cairo_user_font_face_t));
548 if (!font_face) {
549 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
550 return (cairo_font_face_t *)&_cairo_font_face_nil;
553 _cairo_font_face_init (&font_face->base, &_cairo_user_font_face_backend);
555 font_face->immutable = FALSE;
556 memset (&font_face->scaled_font_methods, 0, sizeof (font_face->scaled_font_methods));
558 return &font_face->base;
560 slim_hidden_def(cairo_user_font_face_create);
562 /* User-font method setters */
566 * cairo_user_font_face_set_init_func:
567 * @font_face: A user font face
568 * @init_func: The init callback, or %NULL
570 * Sets the scaled-font initialization function of a user-font.
571 * See #cairo_user_scaled_font_init_func_t for details of how the callback
572 * works.
574 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
575 * error will occur. A user font-face is immutable as soon as a scaled-font
576 * is created from it.
578 * Since: 1.8
580 void
581 cairo_user_font_face_set_init_func (cairo_font_face_t *font_face,
582 cairo_user_scaled_font_init_func_t init_func)
584 cairo_user_font_face_t *user_font_face;
586 if (font_face->status)
587 return;
589 if (! _cairo_font_face_is_user (font_face)) {
590 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
591 return;
594 user_font_face = (cairo_user_font_face_t *) font_face;
595 if (user_font_face->immutable) {
596 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
597 return;
599 user_font_face->scaled_font_methods.init = init_func;
601 slim_hidden_def(cairo_user_font_face_set_init_func);
604 * cairo_user_font_face_set_render_glyph_func:
605 * @font_face: A user font face
606 * @render_glyph_func: The render_glyph callback, or %NULL
608 * Sets the glyph rendering function of a user-font.
609 * See #cairo_user_scaled_font_render_glyph_func_t for details of how the callback
610 * works.
612 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
613 * error will occur. A user font-face is immutable as soon as a scaled-font
614 * is created from it.
616 * The render_glyph callback is the only mandatory callback of a user-font.
617 * If the callback is %NULL and a glyph is tried to be rendered using
618 * @font_face, a %CAIRO_STATUS_USER_FONT_ERROR will occur.
620 * Since: 1.8
622 void
623 cairo_user_font_face_set_render_glyph_func (cairo_font_face_t *font_face,
624 cairo_user_scaled_font_render_glyph_func_t render_glyph_func)
626 cairo_user_font_face_t *user_font_face;
628 if (font_face->status)
629 return;
631 if (! _cairo_font_face_is_user (font_face)) {
632 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
633 return;
636 user_font_face = (cairo_user_font_face_t *) font_face;
637 if (user_font_face->immutable) {
638 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
639 return;
641 user_font_face->scaled_font_methods.render_glyph = render_glyph_func;
643 slim_hidden_def(cairo_user_font_face_set_render_glyph_func);
646 * cairo_user_font_face_set_text_to_glyphs_func:
647 * @font_face: A user font face
648 * @text_to_glyphs_func: The text_to_glyphs callback, or %NULL
650 * Sets th text-to-glyphs conversion function of a user-font.
651 * See #cairo_user_scaled_font_text_to_glyphs_func_t for details of how the callback
652 * works.
654 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
655 * error will occur. A user font-face is immutable as soon as a scaled-font
656 * is created from it.
658 * Since: 1.8
660 void
661 cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t *font_face,
662 cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs_func)
664 cairo_user_font_face_t *user_font_face;
666 if (font_face->status)
667 return;
669 if (! _cairo_font_face_is_user (font_face)) {
670 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
671 return;
674 user_font_face = (cairo_user_font_face_t *) font_face;
675 if (user_font_face->immutable) {
676 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
677 return;
679 user_font_face->scaled_font_methods.text_to_glyphs = text_to_glyphs_func;
683 * cairo_user_font_face_set_unicode_to_glyph_func:
684 * @font_face: A user font face
685 * @unicode_to_glyph_func: The unicode_to_glyph callback, or %NULL
687 * Sets the unicode-to-glyph conversion function of a user-font.
688 * See #cairo_user_scaled_font_unicode_to_glyph_func_t for details of how the callback
689 * works.
691 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
692 * error will occur. A user font-face is immutable as soon as a scaled-font
693 * is created from it.
695 * Since: 1.8
697 void
698 cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t *font_face,
699 cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph_func)
701 cairo_user_font_face_t *user_font_face;
702 if (font_face->status)
703 return;
705 if (! _cairo_font_face_is_user (font_face)) {
706 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
707 return;
710 user_font_face = (cairo_user_font_face_t *) font_face;
711 if (user_font_face->immutable) {
712 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
713 return;
715 user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func;
717 slim_hidden_def(cairo_user_font_face_set_unicode_to_glyph_func);
719 /* User-font method getters */
722 * cairo_user_font_face_get_init_func:
723 * @font_face: A user font face
725 * Gets the scaled-font initialization function of a user-font.
727 * Return value: The init callback of @font_face
728 * or %NULL if none set or an error has occurred.
730 * Since: 1.8
732 cairo_user_scaled_font_init_func_t
733 cairo_user_font_face_get_init_func (cairo_font_face_t *font_face)
735 cairo_user_font_face_t *user_font_face;
737 if (font_face->status)
738 return NULL;
740 if (! _cairo_font_face_is_user (font_face)) {
741 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
742 return NULL;
745 user_font_face = (cairo_user_font_face_t *) font_face;
746 return user_font_face->scaled_font_methods.init;
750 * cairo_user_font_face_get_render_glyph_func:
751 * @font_face: A user font face
753 * Gets the glyph rendering function of a user-font.
755 * Return value: The render_glyph callback of @font_face
756 * or %NULL if none set or an error has occurred.
758 * Since: 1.8
760 cairo_user_scaled_font_render_glyph_func_t
761 cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face)
763 cairo_user_font_face_t *user_font_face;
765 if (font_face->status)
766 return NULL;
768 if (! _cairo_font_face_is_user (font_face)) {
769 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
770 return NULL;
773 user_font_face = (cairo_user_font_face_t *) font_face;
774 return user_font_face->scaled_font_methods.render_glyph;
778 * cairo_user_font_face_get_text_to_glyphs_func:
779 * @font_face: A user font face
781 * Gets the text-to-glyphs conversion function of a user-font.
783 * Return value: The text_to_glyphs callback of @font_face
784 * or %NULL if none set or an error occurred.
786 * Since: 1.8
788 cairo_user_scaled_font_text_to_glyphs_func_t
789 cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face)
791 cairo_user_font_face_t *user_font_face;
793 if (font_face->status)
794 return NULL;
796 if (! _cairo_font_face_is_user (font_face)) {
797 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
798 return NULL;
801 user_font_face = (cairo_user_font_face_t *) font_face;
802 return user_font_face->scaled_font_methods.text_to_glyphs;
806 * cairo_user_font_face_get_unicode_to_glyph_func:
807 * @font_face: A user font face
809 * Gets the unicode-to-glyph conversion function of a user-font.
811 * Return value: The unicode_to_glyph callback of @font_face
812 * or %NULL if none set or an error occurred.
814 * Since: 1.8
816 cairo_user_scaled_font_unicode_to_glyph_func_t
817 cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face)
819 cairo_user_font_face_t *user_font_face;
821 if (font_face->status)
822 return NULL;
824 if (! _cairo_font_face_is_user (font_face)) {
825 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
826 return NULL;
829 user_font_face = (cairo_user_font_face_t *) font_face;
830 return user_font_face->scaled_font_methods.unicode_to_glyph;