ShaderEffect subclasses from Effect, not DependencyObject
[moon.git] / cairo / src / cairo-user-font.c
blobddcbc77c8b65b2c08c9a866f6a31126a67c88319
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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-meta-surface-private.h"
40 #include "cairo-analysis-surface-private.h"
42 typedef struct _cairo_user_scaled_font_methods {
43 cairo_user_scaled_font_init_func_t init;
44 cairo_user_scaled_font_render_glyph_func_t render_glyph;
45 cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph;
46 cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs;
47 } cairo_user_scaled_font_methods_t;
49 typedef struct _cairo_user_font_face {
50 cairo_font_face_t base;
52 /* Set to true after first scaled font is created. At that point,
53 * the scaled_font_methods cannot change anymore. */
54 cairo_bool_t immutable;
56 cairo_user_scaled_font_methods_t scaled_font_methods;
57 } cairo_user_font_face_t;
59 typedef struct _cairo_user_scaled_font {
60 cairo_scaled_font_t base;
62 cairo_text_extents_t default_glyph_extents;
64 /* space to compute extents in, and factors to convert back to user space */
65 cairo_matrix_t extent_scale;
66 double extent_x_scale;
67 double extent_y_scale;
69 /* multiplier for metrics hinting */
70 double snap_x_scale;
71 double snap_y_scale;
73 } cairo_user_scaled_font_t;
75 /* #cairo_user_scaled_font_t */
77 static cairo_t *
78 _cairo_user_scaled_font_create_meta_context (cairo_user_scaled_font_t *scaled_font)
80 cairo_content_t content;
81 cairo_surface_t *meta_surface;
82 cairo_t *cr;
84 content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ?
85 CAIRO_CONTENT_COLOR_ALPHA :
86 CAIRO_CONTENT_ALPHA;
88 meta_surface = _cairo_meta_surface_create (content, -1, -1);
89 cr = cairo_create (meta_surface);
90 cairo_surface_destroy (meta_surface);
92 cairo_set_matrix (cr, &scaled_font->base.scale);
93 cairo_set_font_size (cr, 1.0);
94 cairo_set_font_options (cr, &scaled_font->base.options);
96 return cr;
99 static cairo_int_status_t
100 _cairo_user_scaled_glyph_init (void *abstract_font,
101 cairo_scaled_glyph_t *scaled_glyph,
102 cairo_scaled_glyph_info_t info)
104 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
105 cairo_user_scaled_font_t *scaled_font = abstract_font;
106 cairo_surface_t *meta_surface = scaled_glyph->meta_surface;
108 if (!scaled_glyph->meta_surface) {
109 cairo_user_font_face_t *face =
110 (cairo_user_font_face_t *) scaled_font->base.font_face;
111 cairo_text_extents_t extents = scaled_font->default_glyph_extents;
112 cairo_t *cr;
114 cr = _cairo_user_scaled_font_create_meta_context (scaled_font);
116 if (face->scaled_font_methods.render_glyph)
117 status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
118 _cairo_scaled_glyph_index(scaled_glyph),
119 cr, &extents);
120 else
121 status = CAIRO_STATUS_USER_FONT_ERROR;
123 if (status == CAIRO_STATUS_SUCCESS)
124 status = cairo_status (cr);
126 meta_surface = cairo_surface_reference (cairo_get_target (cr));
128 cairo_destroy (cr);
130 if (status) {
131 cairo_surface_destroy (meta_surface);
132 return status;
135 _cairo_scaled_glyph_set_meta_surface (scaled_glyph,
136 &scaled_font->base,
137 meta_surface);
140 /* set metrics */
142 if (extents.width == 0.) {
143 /* Compute extents.x/y/width/height from meta_surface, in font space */
145 cairo_box_t bbox;
146 double x1, y1, x2, y2;
147 double x_scale, y_scale;
148 cairo_surface_t *null_surface;
149 cairo_surface_t *analysis_surface;
151 null_surface = _cairo_null_surface_create (cairo_surface_get_content (meta_surface));
152 analysis_surface = _cairo_analysis_surface_create (null_surface, -1, -1);
153 cairo_surface_destroy (null_surface);
154 status = analysis_surface->status;
155 if (status)
156 return status;
158 _cairo_analysis_surface_set_ctm (analysis_surface,
159 &scaled_font->extent_scale);
160 status = _cairo_meta_surface_replay (meta_surface,
161 analysis_surface);
162 _cairo_analysis_surface_get_bounding_box (analysis_surface, &bbox);
163 cairo_surface_destroy (analysis_surface);
165 if (status)
166 return status;
168 _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
170 x_scale = scaled_font->extent_x_scale;
171 y_scale = scaled_font->extent_y_scale;
172 extents.x_bearing = x1 * x_scale;
173 extents.y_bearing = y1 * y_scale;
174 extents.width = (x2 - x1) * x_scale;
175 extents.height = (y2 - y1) * y_scale;
178 if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
179 extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale;
180 extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale;
183 _cairo_scaled_glyph_set_metrics (scaled_glyph,
184 &scaled_font->base,
185 &extents);
188 if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
189 cairo_surface_t *surface;
190 cairo_status_t status = CAIRO_STATUS_SUCCESS;
191 cairo_format_t format;
192 int width, height;
194 /* TODO
195 * extend the glyph cache to support argb glyphs.
196 * need to figure out the semantics and interaction with subpixel
197 * rendering first.
200 width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
201 _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
202 height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
203 _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
205 switch (scaled_font->base.options.antialias) {
206 default:
207 case CAIRO_ANTIALIAS_DEFAULT:
208 case CAIRO_ANTIALIAS_GRAY: format = CAIRO_FORMAT_A8; break;
209 case CAIRO_ANTIALIAS_NONE: format = CAIRO_FORMAT_A1; break;
210 case CAIRO_ANTIALIAS_SUBPIXEL: format = CAIRO_FORMAT_ARGB32; break;
212 surface = cairo_image_surface_create (format, width, height);
214 cairo_surface_set_device_offset (surface,
215 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
216 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
217 status = _cairo_meta_surface_replay (meta_surface, surface);
219 if (status) {
220 cairo_surface_destroy(surface);
221 return status;
224 _cairo_scaled_glyph_set_surface (scaled_glyph,
225 &scaled_font->base,
226 (cairo_image_surface_t *) surface);
229 if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
230 cairo_path_fixed_t *path = _cairo_path_fixed_create ();
231 if (!path)
232 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
234 status = _cairo_meta_surface_get_path (meta_surface, path);
236 if (status) {
237 _cairo_path_fixed_destroy (path);
238 return status;
241 _cairo_scaled_glyph_set_path (scaled_glyph,
242 &scaled_font->base,
243 path);
246 return status;
249 static unsigned long
250 _cairo_user_ucs4_to_index (void *abstract_font,
251 uint32_t ucs4)
253 cairo_user_scaled_font_t *scaled_font = abstract_font;
254 cairo_user_font_face_t *face =
255 (cairo_user_font_face_t *) scaled_font->base.font_face;
256 unsigned long glyph = 0;
258 if (face->scaled_font_methods.unicode_to_glyph) {
259 cairo_status_t status;
261 status = face->scaled_font_methods.unicode_to_glyph (&scaled_font->base,
262 ucs4, &glyph);
264 if (status != CAIRO_STATUS_SUCCESS) {
265 status = _cairo_scaled_font_set_error (&scaled_font->base, status);
266 glyph = 0;
269 } else {
270 glyph = ucs4;
273 return glyph;
276 static cairo_int_status_t
277 _cairo_user_text_to_glyphs (void *abstract_font,
278 double x,
279 double y,
280 const char *utf8,
281 int utf8_len,
282 cairo_glyph_t **glyphs,
283 int *num_glyphs,
284 cairo_text_cluster_t **clusters,
285 int *num_clusters,
286 cairo_text_cluster_flags_t *cluster_flags)
288 cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
290 cairo_user_scaled_font_t *scaled_font = abstract_font;
291 cairo_user_font_face_t *face =
292 (cairo_user_font_face_t *) scaled_font->base.font_face;
294 if (face->scaled_font_methods.text_to_glyphs) {
295 int i;
296 cairo_glyph_t *orig_glyphs = *glyphs;
297 int orig_num_glyphs = *num_glyphs;
299 status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
300 utf8, utf8_len,
301 glyphs, num_glyphs,
302 clusters, num_clusters, cluster_flags);
304 if (status != CAIRO_STATUS_SUCCESS)
305 return status;
307 if (*num_glyphs < 0) {
308 if (orig_glyphs != *glyphs) {
309 cairo_glyph_free (*glyphs);
310 *glyphs = orig_glyphs;
312 *num_glyphs = orig_num_glyphs;
313 return CAIRO_INT_STATUS_UNSUPPORTED;
316 /* Convert from font space to user space and add x,y */
317 for (i = 0; i < *num_glyphs; i++) {
318 double gx = (*glyphs)[i].x;
319 double gy = (*glyphs)[i].y;
321 cairo_matrix_transform_point (&scaled_font->base.font_matrix,
322 &gx, &gy);
324 (*glyphs)[i].x = gx + x;
325 (*glyphs)[i].y = gy + y;
329 return status;
332 static cairo_status_t
333 _cairo_user_font_face_scaled_font_create (void *abstract_face,
334 const cairo_matrix_t *font_matrix,
335 const cairo_matrix_t *ctm,
336 const cairo_font_options_t *options,
337 cairo_scaled_font_t **scaled_font);
339 static cairo_status_t
340 _cairo_user_scaled_font_get_implementation (cairo_toy_font_face_t *toy_face,
341 cairo_font_face_t **font_face_out)
343 static cairo_user_data_key_t twin_font_face_key;
345 cairo_font_face_t *face;
346 cairo_status_t status;
348 face = cairo_font_face_get_user_data (&toy_face->base,
349 &twin_font_face_key);
350 if (!face) {
351 face = _cairo_font_face_twin_create (cairo_toy_font_face_get_slant (&toy_face->base),
352 cairo_toy_font_face_get_weight (&toy_face->base));
354 status = cairo_font_face_set_user_data (&toy_face->base,
355 &twin_font_face_key,
356 face,
357 (cairo_destroy_func_t) cairo_font_face_destroy);
359 if (status) {
360 cairo_font_face_destroy (face);
361 return status;
365 *font_face_out = face;
366 return CAIRO_STATUS_SUCCESS;
369 static cairo_status_t
370 _cairo_user_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
371 const cairo_matrix_t *font_matrix,
372 const cairo_matrix_t *ctm,
373 const cairo_font_options_t *font_options,
374 cairo_scaled_font_t **font)
376 cairo_font_face_t *face;
377 cairo_status_t status;
379 status = _cairo_user_scaled_font_get_implementation (toy_face, &face);
380 if (status)
381 return status;
383 status = _cairo_user_font_face_scaled_font_create (face,
384 font_matrix,
385 ctm,
386 font_options,
387 font);
388 if (status)
389 return status;
391 return CAIRO_STATUS_SUCCESS;
394 const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = {
395 CAIRO_FONT_TYPE_USER,
396 _cairo_user_scaled_font_get_implementation,
397 _cairo_user_scaled_font_create_toy, /* create_toy */
398 NULL, /* scaled_font_fini */
399 _cairo_user_scaled_glyph_init,
400 _cairo_user_text_to_glyphs,
401 _cairo_user_ucs4_to_index,
402 NULL, /* show_glyphs */
403 NULL, /* load_truetype_table */
404 NULL /* index_to_ucs4 */
407 /* #cairo_user_font_face_t */
409 static cairo_status_t
410 _cairo_user_font_face_scaled_font_create (void *abstract_face,
411 const cairo_matrix_t *font_matrix,
412 const cairo_matrix_t *ctm,
413 const cairo_font_options_t *options,
414 cairo_scaled_font_t **scaled_font)
416 cairo_status_t status = CAIRO_STATUS_SUCCESS;
417 cairo_user_font_face_t *font_face = abstract_face;
418 cairo_user_scaled_font_t *user_scaled_font = NULL;
419 cairo_font_extents_t font_extents = {1., 0., 1., 1., 0.};
421 font_face->immutable = TRUE;
423 user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t));
424 if (user_scaled_font == NULL)
425 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
427 status = _cairo_scaled_font_init (&user_scaled_font->base,
428 &font_face->base,
429 font_matrix, ctm, options,
430 &_cairo_user_scaled_font_backend);
432 if (status) {
433 free (user_scaled_font);
434 return status;
437 /* XXX metrics hinting? */
439 /* compute a normalized version of font scale matrix to compute
440 * extents in. This is to minimize error caused by the cairo_fixed_t
441 * representation. */
443 double fixed_scale, x_scale, y_scale;
445 user_scaled_font->extent_scale = user_scaled_font->base.scale_inverse;
446 status = _cairo_matrix_compute_basis_scale_factors (&user_scaled_font->extent_scale,
447 &x_scale, &y_scale,
449 if (status == CAIRO_STATUS_SUCCESS) {
451 if (x_scale == 0) x_scale = 1.;
452 if (y_scale == 0) y_scale = 1.;
454 user_scaled_font->snap_x_scale = x_scale;
455 user_scaled_font->snap_y_scale = y_scale;
457 /* since glyphs are pretty much 1.0x1.0, we can reduce error by
458 * scaling to a larger square. say, 1024.x1024. */
459 fixed_scale = 1024.;
460 x_scale /= fixed_scale;
461 y_scale /= fixed_scale;
463 cairo_matrix_scale (&user_scaled_font->extent_scale, 1. / x_scale, 1. / y_scale);
465 user_scaled_font->extent_x_scale = x_scale;
466 user_scaled_font->extent_y_scale = y_scale;
470 if (status == CAIRO_STATUS_SUCCESS &&
471 font_face->scaled_font_methods.init != NULL)
473 /* Lock the scaled_font mutex such that user doesn't accidentally try
474 * to use it just yet. */
475 CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex);
477 /* Give away fontmap lock such that user-font can use other fonts */
478 status = _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base);
479 if (status == CAIRO_STATUS_SUCCESS) {
480 cairo_t *cr;
482 cr = _cairo_user_scaled_font_create_meta_context (user_scaled_font);
484 status = font_face->scaled_font_methods.init (&user_scaled_font->base,
486 &font_extents);
488 if (status == CAIRO_STATUS_SUCCESS)
489 status = cairo_status (cr);
491 cairo_destroy (cr);
493 _cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base);
496 CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex);
499 if (status == CAIRO_STATUS_SUCCESS)
500 status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
502 if (status != CAIRO_STATUS_SUCCESS) {
503 _cairo_scaled_font_fini (&user_scaled_font->base);
504 free (user_scaled_font);
505 } else {
506 user_scaled_font->default_glyph_extents.x_bearing = 0.;
507 user_scaled_font->default_glyph_extents.y_bearing = -font_extents.ascent;
508 user_scaled_font->default_glyph_extents.width = 0.;
509 user_scaled_font->default_glyph_extents.height = font_extents.ascent + font_extents.descent;
510 user_scaled_font->default_glyph_extents.x_advance = font_extents.max_x_advance;
511 user_scaled_font->default_glyph_extents.y_advance = 0.;
513 *scaled_font = &user_scaled_font->base;
516 return status;
519 static const cairo_font_face_backend_t _cairo_user_font_face_backend = {
520 CAIRO_FONT_TYPE_USER,
521 NULL, /* destroy */
522 NULL, /* direct implementation */
523 _cairo_user_font_face_scaled_font_create
527 cairo_bool_t
528 _cairo_font_face_is_user (cairo_font_face_t *font_face)
530 return font_face->backend == &_cairo_user_font_face_backend;
533 /* Implement the public interface */
536 * cairo_user_font_face_create:
538 * Creates a new user font-face.
540 * Use the setter functions to associate callbacks with the returned
541 * user font. The only mandatory callback is render_glyph.
543 * After the font-face is created, the user can attach arbitrary data
544 * (the actual font data) to it using cairo_font_face_set_user_data()
545 * and access it from the user-font callbacks by using
546 * cairo_scaled_font_get_font_face() followed by
547 * cairo_font_face_get_user_data().
549 * Return value: a newly created #cairo_font_face_t. Free with
550 * cairo_font_face_destroy() when you are done using it.
552 * Since: 1.8
554 cairo_font_face_t *
555 cairo_user_font_face_create (void)
557 cairo_user_font_face_t *font_face;
559 font_face = malloc (sizeof (cairo_user_font_face_t));
560 if (!font_face) {
561 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
562 return (cairo_font_face_t *)&_cairo_font_face_nil;
565 _cairo_font_face_init (&font_face->base, &_cairo_user_font_face_backend);
567 font_face->immutable = FALSE;
568 memset (&font_face->scaled_font_methods, 0, sizeof (font_face->scaled_font_methods));
570 return &font_face->base;
572 slim_hidden_def(cairo_user_font_face_create);
574 /* User-font method setters */
578 * cairo_user_font_face_set_init_func:
579 * @font_face: A user font face
580 * @init_func: The init callback, or %NULL
582 * Sets the scaled-font initialization function of a user-font.
583 * See #cairo_user_scaled_font_init_func_t for details of how the callback
584 * works.
586 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
587 * error will occur. A user font-face is immutable as soon as a scaled-font
588 * is created from it.
590 * Since: 1.8
592 void
593 cairo_user_font_face_set_init_func (cairo_font_face_t *font_face,
594 cairo_user_scaled_font_init_func_t init_func)
596 cairo_user_font_face_t *user_font_face;
598 if (font_face->status)
599 return;
601 if (! _cairo_font_face_is_user (font_face)) {
602 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
603 return;
606 user_font_face = (cairo_user_font_face_t *) font_face;
607 if (user_font_face->immutable) {
608 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
609 return;
611 user_font_face->scaled_font_methods.init = init_func;
613 slim_hidden_def(cairo_user_font_face_set_init_func);
616 * cairo_user_font_face_set_render_glyph_func:
617 * @font_face: A user font face
618 * @render_glyph_func: The render_glyph callback, or %NULL
620 * Sets the glyph rendering function of a user-font.
621 * See #cairo_user_scaled_font_render_glyph_func_t for details of how the callback
622 * works.
624 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
625 * error will occur. A user font-face is immutable as soon as a scaled-font
626 * is created from it.
628 * The render_glyph callback is the only mandatory callback of a user-font.
629 * If the callback is %NULL and a glyph is tried to be rendered using
630 * @font_face, a %CAIRO_STATUS_USER_FONT_ERROR will occur.
632 * Since: 1.8
634 void
635 cairo_user_font_face_set_render_glyph_func (cairo_font_face_t *font_face,
636 cairo_user_scaled_font_render_glyph_func_t render_glyph_func)
638 cairo_user_font_face_t *user_font_face;
640 if (font_face->status)
641 return;
643 if (! _cairo_font_face_is_user (font_face)) {
644 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
645 return;
648 user_font_face = (cairo_user_font_face_t *) font_face;
649 if (user_font_face->immutable) {
650 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
651 return;
653 user_font_face->scaled_font_methods.render_glyph = render_glyph_func;
655 slim_hidden_def(cairo_user_font_face_set_render_glyph_func);
658 * cairo_user_font_face_set_text_to_glyphs_func:
659 * @font_face: A user font face
660 * @text_to_glyphs_func: The text_to_glyphs callback, or %NULL
662 * Sets th text-to-glyphs conversion function of a user-font.
663 * See #cairo_user_scaled_font_text_to_glyphs_func_t for details of how the callback
664 * works.
666 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
667 * error will occur. A user font-face is immutable as soon as a scaled-font
668 * is created from it.
670 * Since: 1.8
672 void
673 cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t *font_face,
674 cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs_func)
676 cairo_user_font_face_t *user_font_face;
678 if (font_face->status)
679 return;
681 if (! _cairo_font_face_is_user (font_face)) {
682 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
683 return;
686 user_font_face = (cairo_user_font_face_t *) font_face;
687 if (user_font_face->immutable) {
688 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
689 return;
691 user_font_face->scaled_font_methods.text_to_glyphs = text_to_glyphs_func;
695 * cairo_user_font_face_set_unicode_to_glyph_func:
696 * @font_face: A user font face
697 * @unicode_to_glyph_func: The unicode_to_glyph callback, or %NULL
699 * Sets the unicode-to-glyph conversion function of a user-font.
700 * See #cairo_user_scaled_font_unicode_to_glyph_func_t for details of how the callback
701 * works.
703 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
704 * error will occur. A user font-face is immutable as soon as a scaled-font
705 * is created from it.
707 * Since: 1.8
709 void
710 cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t *font_face,
711 cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph_func)
713 cairo_user_font_face_t *user_font_face;
714 if (font_face->status)
715 return;
717 if (! _cairo_font_face_is_user (font_face)) {
718 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
719 return;
722 user_font_face = (cairo_user_font_face_t *) font_face;
723 if (user_font_face->immutable) {
724 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
725 return;
727 user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func;
729 slim_hidden_def(cairo_user_font_face_set_unicode_to_glyph_func);
731 /* User-font method getters */
734 * cairo_user_font_face_get_init_func:
735 * @font_face: A user font face
737 * Gets the scaled-font initialization function of a user-font.
739 * Return value: The init callback of @font_face
740 * or %NULL if none set or an error has occurred.
742 * Since: 1.8
744 cairo_user_scaled_font_init_func_t
745 cairo_user_font_face_get_init_func (cairo_font_face_t *font_face)
747 cairo_user_font_face_t *user_font_face;
749 if (font_face->status)
750 return NULL;
752 if (! _cairo_font_face_is_user (font_face)) {
753 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
754 return NULL;
757 user_font_face = (cairo_user_font_face_t *) font_face;
758 return user_font_face->scaled_font_methods.init;
762 * cairo_user_font_face_get_render_glyph_func:
763 * @font_face: A user font face
765 * Gets the glyph rendering function of a user-font.
767 * Return value: The render_glyph callback of @font_face
768 * or %NULL if none set or an error has occurred.
770 * Since: 1.8
772 cairo_user_scaled_font_render_glyph_func_t
773 cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face)
775 cairo_user_font_face_t *user_font_face;
777 if (font_face->status)
778 return NULL;
780 if (! _cairo_font_face_is_user (font_face)) {
781 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
782 return NULL;
785 user_font_face = (cairo_user_font_face_t *) font_face;
786 return user_font_face->scaled_font_methods.render_glyph;
790 * cairo_user_font_face_get_text_to_glyphs_func:
791 * @font_face: A user font face
793 * Gets the text-to-glyphs conversion function of a user-font.
795 * Return value: The text_to_glyphs callback of @font_face
796 * or %NULL if none set or an error occurred.
798 * Since: 1.8
800 cairo_user_scaled_font_text_to_glyphs_func_t
801 cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face)
803 cairo_user_font_face_t *user_font_face;
805 if (font_face->status)
806 return NULL;
808 if (! _cairo_font_face_is_user (font_face)) {
809 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
810 return NULL;
813 user_font_face = (cairo_user_font_face_t *) font_face;
814 return user_font_face->scaled_font_methods.text_to_glyphs;
818 * cairo_user_font_face_get_unicode_to_glyph_func:
819 * @font_face: A user font face
821 * Gets the unicode-to-glyph conversion function of a user-font.
823 * Return value: The unicode_to_glyph callback of @font_face
824 * or %NULL if none set or an error occurred.
826 * Since: 1.8
828 cairo_user_scaled_font_unicode_to_glyph_func_t
829 cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face)
831 cairo_user_font_face_t *user_font_face;
833 if (font_face->status)
834 return NULL;
836 if (! _cairo_font_face_is_user (font_face)) {
837 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
838 return NULL;
841 user_font_face = (cairo_user_font_face_t *) font_face;
842 return user_font_face->scaled_font_methods.unicode_to_glyph;