Bug Summary

File:root/firefox-clang/gfx/cairo/cairo/src/cairo-user-font.c
Warning:line 452, column 6
Value stored to 'status' is never read

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name Unified_c_gfx_cairo_cairo_src5.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -fhalf-no-semantic-interposition -mframe-pointer=all -relaxed-aliasing -ffp-contract=off -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/cairo/cairo/src -fcoverage-compilation-dir=/root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/cairo/cairo/src -resource-dir /usr/lib/llvm-21/lib/clang/21 -include /root/firefox-clang/config/gcc_hidden.h -include /root/firefox-clang/obj-x86_64-pc-linux-gnu/mozilla-config.h -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/system_wrappers -U _FORTIFY_SOURCE -D _FORTIFY_SOURCE=2 -D _GLIBCXX_ASSERTIONS -D DEBUG=1 -D HAVE_FT_LOAD_SFNT_TABLE -D PACKAGE_VERSION="moz" -D PACKAGE_BUGREPORT="http://bugzilla.mozilla.org/" -D CAIRO_HAS_PTHREAD -D _GNU_SOURCE -D MOZ_TREE_PIXMAN -D SIZEOF_VOID_P=__SIZEOF_POINTER__ -D SIZEOF_INT=__SIZEOF_INT__ -D SIZEOF_LONG=__SIZEOF_LONG__ -D SIZEOF_LONG_LONG=__SIZEOF_LONG_LONG__ -D HAVE_UINT64_T -D HAVE_CXX11_ATOMIC_PRIMITIVES -D MOZ_HAS_MOZGLUE -D MOZILLA_INTERNAL_API -D IMPL_LIBXUL -D MOZ_SUPPORT_LEAKCHECKING -D STATIC_EXPORTABLE_JS_API -I /root/firefox-clang/gfx/cairo/cairo/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/gfx/cairo/cairo/src -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nspr -I /root/firefox-clang/obj-x86_64-pc-linux-gnu/dist/include/nss -D MOZILLA_CLIENT -I /usr/include/freetype2 -I /usr/include/libpng16 -I /usr/include/freetype2 -I /usr/include/libpng16 -internal-isystem /usr/lib/llvm-21/lib/clang/21/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O2 -Wno-error=tautological-type-limit-compare -Wno-range-loop-analysis -Wno-error=deprecated-declarations -Wno-error=array-bounds -Wno-error=free-nonheap-object -Wno-error=atomic-alignment -Wno-error=deprecated-builtins -Wno-psabi -Wno-error=builtin-macro-redefined -Wno-unknown-warning-option -Wno-enum-compare -Wno-int-to-pointer-cast -Wno-int-conversion -Wno-incompatible-pointer-types -Wno-sign-compare -Wno-type-limits -Wno-missing-field-initializers -Wno-conversion -Wno-narrowing -Wno-switch -Wno-unused -Wno-unused-variable -Wno-error=uninitialized -Wno-absolute-value -Wno-deprecated-register -Wno-incompatible-pointer-types -Wno-macro-redefined -Wno-shift-negative-value -Wno-tautological-compare -Wno-tautological-constant-out-of-range-compare -Wno-unreachable-code -ferror-limit 19 -fstrict-flex-arrays=1 -stack-protector 2 -fstack-clash-protection -ftrivial-auto-var-init=pattern -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2025-06-26-231904-1820671-1 -x c Unified_c_gfx_cairo_cairo_src5.c
1/* -*- Mode: c; tab-width: 8; c-basic-offset: 4; indent-tabs-mode: t; -*- */
2/* cairo - a vector graphics library with display and print output
3 *
4 * Copyright © 2006, 2008 Red Hat, Inc
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it either under the terms of the GNU Lesser General Public
8 * License version 2.1 as published by the Free Software Foundation
9 * (the "LGPL") or, at your option, under the terms of the Mozilla
10 * Public License Version 1.1 (the "MPL"). If you do not alter this
11 * notice, a recipient may use your version of this file under either
12 * the MPL or the LGPL.
13 *
14 * You should have received a copy of the LGPL along with this library
15 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
17 * You should have received a copy of the MPL along with this library
18 * in the file COPYING-MPL-1.1
19 *
20 * The contents of this file are subject to the Mozilla Public License
21 * Version 1.1 (the "License"); you may not use this file except in
22 * compliance with the License. You may obtain a copy of the License at
23 * http://www.mozilla.org/MPL/
24 *
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27 * the specific language governing rights and limitations.
28 *
29 * The Original Code is the cairo graphics library.
30 *
31 * The Initial Developer of the Original Code is Red Hat, Inc.
32 *
33 * Contributor(s):
34 * Kristian Høgsberg <krh@redhat.com>
35 * Behdad Esfahbod <behdad@behdad.org>
36 */
37
38#include "cairoint.h"
39#include "cairo-user-font-private.h"
40#include "cairo-recording-surface-private.h"
41#include "cairo-analysis-surface-private.h"
42#include "cairo-error-private.h"
43
44/**
45 * SECTION:cairo-user-fonts
46 * @Title:User Fonts
47 * @Short_Description: Font support with font data provided by the user
48 *
49 * The user-font feature allows the cairo user to provide drawings for glyphs
50 * in a font. This is most useful in implementing fonts in non-standard
51 * formats, like SVG fonts and Flash fonts, but can also be used by games and
52 * other application to draw "funky" fonts.
53 **/
54
55/**
56 * CAIRO_HAS_USER_FONT:
57 *
58 * Defined if the user font backend is available.
59 * This macro can be used to conditionally compile backend-specific code.
60 * The user font backend is always built in versions of cairo that support
61 * this feature (1.8 and later).
62 *
63 * Since: 1.8
64 **/
65
66typedef struct _cairo_user_scaled_font_methods {
67 cairo_user_scaled_font_init_func_t init;
68 cairo_user_scaled_font_render_glyph_func_t render_color_glyph;
69 cairo_user_scaled_font_render_glyph_func_t render_glyph;
70 cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph;
71 cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs;
72} cairo_user_scaled_font_methods_t;
73
74typedef struct _cairo_user_font_face {
75 cairo_font_face_t base;
76
77 /* Set to true after first scaled font is created. At that point,
78 * the scaled_font_methods cannot change anymore. */
79 cairo_bool_t immutable;
80 cairo_bool_t has_color;
81 cairo_user_scaled_font_methods_t scaled_font_methods;
82} cairo_user_font_face_t;
83
84typedef struct _cairo_user_scaled_font {
85 cairo_scaled_font_t base;
86
87 cairo_text_extents_t default_glyph_extents;
88
89 /* space to compute extents in, and factors to convert back to user space */
90 cairo_matrix_t extent_scale;
91 double extent_x_scale;
92 double extent_y_scale;
93
94 /* multiplier for metrics hinting */
95 double snap_x_scale;
96 double snap_y_scale;
97
98 cairo_pattern_t *foreground_marker;
99 cairo_pattern_t *foreground_pattern;
100 cairo_bool_t foreground_marker_used;
101 cairo_bool_t foreground_colors_used;
102
103} cairo_user_scaled_font_t;
104
105/* #cairo_user_scaled_font_t */
106
107static cairo_surface_t *
108_cairo_user_scaled_font_create_recording_surface (cairo_user_scaled_font_t *scaled_font,
109 cairo_bool_t color,
110 const cairo_color_t *foreground_color)
111{
112 cairo_content_t content;
113
114 if (color) {
115 content = CAIRO_CONTENT_COLOR_ALPHA;
116 } else {
117 content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ?
118 CAIRO_CONTENT_COLOR_ALPHA :
119 CAIRO_CONTENT_ALPHA;
120 }
121
122 if (scaled_font->foreground_pattern)
123 cairo_pattern_destroy_moz_cairo_pattern_destroy (scaled_font->foreground_pattern);
124
125 scaled_font->foreground_marker_used = FALSE0;
126 scaled_font->foreground_colors_used = FALSE0;
127 if (foreground_color) {
128 scaled_font->foreground_pattern = _cairo_pattern_create_solid (foreground_color);
129 } else {
130 scaled_font->foreground_pattern = cairo_pattern_create_rgb_moz_cairo_pattern_create_rgb (0, 0, 0);
131 }
132
133 return cairo_recording_surface_create_moz_cairo_recording_surface_create (content, NULL((void*)0));
134}
135
136static cairo_t *
137_cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t *scaled_font,
138 cairo_surface_t *recording_surface,
139 cairo_bool_t color)
140{
141 cairo_t *cr;
142
143 cr = cairo_create_moz_cairo_create (recording_surface);
144
145 if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
146 cairo_matrix_t scale;
147 scale = scaled_font->base.scale;
148 scale.x0 = scale.y0 = 0.;
149 cairo_set_matrix_moz_cairo_set_matrix (cr, &scale);
150 }
151
152 cairo_set_font_size_moz_cairo_set_font_size (cr, 1.0);
153 cairo_set_font_options_moz_cairo_set_font_options (cr, &scaled_font->base.options);
154 if (!color)
155 cairo_set_source_rgb_moz_cairo_set_source_rgb (cr, 1., 1., 1.);
156
157 return cr;
158}
159
160static cairo_int_status_t
161_cairo_user_scaled_glyph_init_record_glyph (cairo_user_scaled_font_t *scaled_font,
162 cairo_scaled_glyph_t *scaled_glyph,
163 const cairo_color_t *foreground_color)
164{
165 cairo_user_font_face_t *face =
166 (cairo_user_font_face_t *) scaled_font->base.font_face;
167 cairo_text_extents_t extents = scaled_font->default_glyph_extents;
168 cairo_surface_t *recording_surface = NULL((void*)0);
169 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
170 cairo_t *cr;
171 cairo_bool_t foreground_used = FALSE0;
172
173 if (!face->scaled_font_methods.render_color_glyph && !face->scaled_font_methods.render_glyph)
174 return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
175
176 /* special case for 0 rank matrix (as in _cairo_scaled_font_init): empty surface */
177 if (_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
178 recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, FALSE0, foreground_color);
179 _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
180 &scaled_font->base,
181 recording_surface,
182 NULL((void*)0));
183 } else {
184 status = CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
185
186 if (face->scaled_font_methods.render_color_glyph &&
187 scaled_font->base.options.color_mode != CAIRO_COLOR_MODE_NO_COLOR)
188 {
189 recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, TRUE1, foreground_color);
190
191 cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, TRUE1);
192 status = face->scaled_font_methods.render_color_glyph ((cairo_scaled_font_t *)scaled_font,
193 _cairo_scaled_glyph_index(scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
194 cr, &extents);
195 if (status == CAIRO_INT_STATUS_SUCCESS) {
196 status = cairo_status_moz_cairo_status (cr);
197 scaled_glyph->color_glyph = TRUE1;
198 scaled_glyph->color_glyph_set = TRUE1;
199 }
200
201 cairo_destroy_moz_cairo_destroy (cr);
202 foreground_used = scaled_font->foreground_marker_used || scaled_font->foreground_colors_used;
203 }
204
205 if (status == (cairo_int_status_t)CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED &&
206 face->scaled_font_methods.render_glyph) {
207 if (recording_surface)
208 cairo_surface_destroy_moz_cairo_surface_destroy (recording_surface);
209 recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font, FALSE0, foreground_color);
210 recording_surface->device_transform.x0 = .25 * _cairo_scaled_glyph_xphase (scaled_glyph)(int)(((scaled_glyph)->hash_entry.hash >> 24) & 3
)
;
211 recording_surface->device_transform.y0 = .25 * _cairo_scaled_glyph_yphase (scaled_glyph)(int)(((scaled_glyph)->hash_entry.hash >> 26) & 3
)
;
212
213 cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface, FALSE0);
214
215 status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
216 _cairo_scaled_glyph_index(scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
217 cr, &extents);
218 if (status == CAIRO_INT_STATUS_SUCCESS) {
219 status = cairo_status_moz_cairo_status (cr);
220 scaled_glyph->color_glyph = FALSE0;
221 scaled_glyph->color_glyph_set = TRUE1;
222 }
223
224 cairo_destroy_moz_cairo_destroy (cr);
225 foreground_used = FALSE0;
226 }
227
228 if (status != CAIRO_INT_STATUS_SUCCESS) {
229 if (recording_surface)
230 cairo_surface_destroy_moz_cairo_surface_destroy (recording_surface);
231 return status;
232 }
233
234 _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
235 &scaled_font->base,
236 recording_surface,
237 foreground_used ? foreground_color : NULL((void*)0));
238 }
239
240 /* set metrics */
241
242 if (extents.width == 0.) {
243 cairo_box_t bbox;
244 double x1, y1, x2, y2;
245 double x_scale, y_scale;
246
247 /* Compute extents.x/y/width/height from recording_surface,
248 * in font space.
249 */
250 status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
251 &bbox,
252 &scaled_font->extent_scale);
253 if (unlikely (status)(__builtin_expect (!!(status), 0)))
254 return status;
255
256 _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
257
258 x_scale = scaled_font->extent_x_scale;
259 y_scale = scaled_font->extent_y_scale;
260 extents.x_bearing = x1 * x_scale;
261 extents.y_bearing = y1 * y_scale;
262 extents.width = (x2 - x1) * x_scale;
263 extents.height = (y2 - y1) * y_scale;
264 }
265
266 if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
267 extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale;
268 extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale;
269 }
270
271 _cairo_scaled_glyph_set_metrics (scaled_glyph,
272 &scaled_font->base,
273 &extents);
274
275 return status;
276}
277
278static cairo_int_status_t
279_cairo_user_scaled_glyph_init_surface (cairo_user_scaled_font_t *scaled_font,
280 cairo_scaled_glyph_t *scaled_glyph,
281 cairo_scaled_glyph_info_t info,
282 const cairo_color_t *foreground_color)
283{
284 cairo_surface_t *surface;
285 cairo_format_t format;
286 int width, height;
287 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
288 cairo_bool_t foreground_used;
289
290 /* TODO
291 * extend the glyph cache to support argb glyphs.
292 * need to figure out the semantics and interaction with subpixel
293 * rendering first.
294 */
295
296 /* Only one info type at a time handled in this function */
297 assert (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE || info == CAIRO_SCALED_GLYPH_INFO_SURFACE)((void) sizeof ((info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE
|| info == CAIRO_SCALED_GLYPH_INFO_SURFACE) ? 1 : 0), __extension__
({ if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE || info
== CAIRO_SCALED_GLYPH_INFO_SURFACE) ; else __assert_fail ("info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE || info == CAIRO_SCALED_GLYPH_INFO_SURFACE"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-user-font.c"
, 297, __extension__ __PRETTY_FUNCTION__); }))
;
298
299 width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
300 _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
301 height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
302 _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
303
304 if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
305 format = CAIRO_FORMAT_ARGB32;
306 } else {
307 switch (scaled_font->base.options.antialias) {
308 default:
309 case CAIRO_ANTIALIAS_DEFAULT:
310 case CAIRO_ANTIALIAS_FAST:
311 case CAIRO_ANTIALIAS_GOOD:
312 case CAIRO_ANTIALIAS_GRAY:
313 format = CAIRO_FORMAT_A8;
314 break;
315 case CAIRO_ANTIALIAS_NONE:
316 format = CAIRO_FORMAT_A1;
317 break;
318 case CAIRO_ANTIALIAS_BEST:
319 case CAIRO_ANTIALIAS_SUBPIXEL:
320 format = CAIRO_FORMAT_ARGB32;
321 break;
322 }
323 }
324 surface = cairo_image_surface_create_moz_cairo_image_surface_create (format, width, height);
325
326 cairo_surface_set_device_offset_moz_cairo_surface_set_device_offset (surface,
327 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
328 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
329
330 if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
331 status = _cairo_recording_surface_replay_with_foreground_color (scaled_glyph->recording_surface,
332 surface,
333 foreground_color,
334 &foreground_used);
335
336 } else {
337 status = _cairo_recording_surface_replay (scaled_glyph->recording_surface, surface);
338 foreground_used = FALSE0;
339 }
340 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
341 cairo_surface_destroy_moz_cairo_surface_destroy(surface);
342 return status;
343 }
344
345 foreground_used = foreground_used || scaled_glyph->recording_uses_foreground_color;
346
347 if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
348 _cairo_scaled_glyph_set_color_surface (scaled_glyph,
349 &scaled_font->base,
350 (cairo_image_surface_t *)surface,
351 foreground_used ? foreground_color : NULL((void*)0));
352 surface = NULL((void*)0);
353 } else {
354 _cairo_scaled_glyph_set_surface (scaled_glyph,
355 &scaled_font->base,
356 (cairo_image_surface_t *) surface);
357 surface = NULL((void*)0);
358 }
359
360 if (surface)
361 cairo_surface_destroy_moz_cairo_surface_destroy (surface);
362
363 return status;
364}
365
366static void
367_cairo_user_scaled_glyph_fini (void *abstract_font)
368{
369 cairo_user_scaled_font_t *scaled_font = abstract_font;
370
371 if (scaled_font->foreground_pattern)
372 cairo_pattern_destroy_moz_cairo_pattern_destroy (scaled_font->foreground_pattern);
373
374 if (scaled_font->foreground_marker)
375 cairo_pattern_destroy_moz_cairo_pattern_destroy (scaled_font->foreground_marker);
376}
377
378static cairo_int_status_t
379_cairo_user_scaled_glyph_init (void *abstract_font,
380 cairo_scaled_glyph_t *scaled_glyph,
381 cairo_scaled_glyph_info_t info,
382 const cairo_color_t *foreground_color)
383{
384 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
385 cairo_user_scaled_font_t *scaled_font = abstract_font;
386
387 if (!scaled_glyph->recording_surface || (info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE)) {
388 status = _cairo_user_scaled_glyph_init_record_glyph (scaled_font, scaled_glyph, foreground_color);
389 if (status)
390 return status;
391 }
392
393 if (info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
394 if (!scaled_glyph->color_glyph )
395 return CAIRO_INT_STATUS_UNSUPPORTED;
396
397 status = _cairo_user_scaled_glyph_init_surface (scaled_font,
398 scaled_glyph,
399 CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
400 foreground_color);
401 if (status)
402 return status;
403 }
404
405 if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
406 status = _cairo_user_scaled_glyph_init_surface (scaled_font,
407 scaled_glyph,
408 CAIRO_SCALED_GLYPH_INFO_SURFACE,
409 NULL((void*)0));
410 if (status)
411 return status;
412 }
413
414 if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
415 cairo_path_fixed_t *path = _cairo_path_fixed_create ();
416 if (!path)
417 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
418
419 status = _cairo_recording_surface_get_path (scaled_glyph->recording_surface, path);
420 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
421 _cairo_path_fixed_destroy (path);
422 return status;
423 }
424
425 _cairo_scaled_glyph_set_path (scaled_glyph,
426 &scaled_font->base,
427 path);
428 }
429
430 return status;
431}
432
433static unsigned long
434_cairo_user_ucs4_to_index (void *abstract_font,
435 uint32_t ucs4)
436{
437 cairo_user_scaled_font_t *scaled_font = abstract_font;
438 cairo_user_font_face_t *face =
439 (cairo_user_font_face_t *) scaled_font->base.font_face;
440 unsigned long glyph = 0;
441
442 if (face->scaled_font_methods.unicode_to_glyph) {
443 cairo_status_t status;
444
445 status = face->scaled_font_methods.unicode_to_glyph (&scaled_font->base,
446 ucs4, &glyph);
447
448 if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
449 goto not_implemented;
450
451 if (status != CAIRO_STATUS_SUCCESS) {
452 status = _cairo_scaled_font_set_error (&scaled_font->base, status);
Value stored to 'status' is never read
453 glyph = 0;
454 }
455
456 } else {
457not_implemented:
458 glyph = ucs4;
459 }
460
461 return glyph;
462}
463
464static cairo_bool_t
465_cairo_user_has_color_glyphs (void *abstract_font)
466{
467 cairo_user_scaled_font_t *scaled_font = abstract_font;
468 cairo_user_font_face_t *face =
469 (cairo_user_font_face_t *) scaled_font->base.font_face;
470
471 return face->has_color;
472}
473
474static cairo_int_status_t
475_cairo_user_text_to_glyphs (void *abstract_font,
476 double x,
477 double y,
478 const char *utf8,
479 int utf8_len,
480 cairo_glyph_t **glyphs,
481 int *num_glyphs,
482 cairo_text_cluster_t **clusters,
483 int *num_clusters,
484 cairo_text_cluster_flags_t *cluster_flags)
485{
486 cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
487
488 cairo_user_scaled_font_t *scaled_font = abstract_font;
489 cairo_user_font_face_t *face =
490 (cairo_user_font_face_t *) scaled_font->base.font_face;
491
492 if (face->scaled_font_methods.text_to_glyphs) {
493 int i;
494 cairo_glyph_t *orig_glyphs = *glyphs;
495 int orig_num_glyphs = *num_glyphs;
496
497 status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
498 utf8, utf8_len,
499 glyphs, num_glyphs,
500 clusters, num_clusters, cluster_flags);
501
502 if (status != CAIRO_INT_STATUS_SUCCESS &&
503 status != CAIRO_INT_STATUS_USER_FONT_NOT_IMPLEMENTED)
504 return status;
505
506 if (status == CAIRO_INT_STATUS_USER_FONT_NOT_IMPLEMENTED ||
507 *num_glyphs < 0) {
508 if (orig_glyphs != *glyphs) {
509 cairo_glyph_free_moz_cairo_glyph_free (*glyphs);
510 *glyphs = orig_glyphs;
511 }
512 *num_glyphs = orig_num_glyphs;
513 return CAIRO_INT_STATUS_UNSUPPORTED;
514 }
515
516 /* Convert from font space to user space and add x,y */
517 for (i = 0; i < *num_glyphs; i++) {
518 double gx = (*glyphs)[i].x;
519 double gy = (*glyphs)[i].y;
520
521 cairo_matrix_transform_point_moz_cairo_matrix_transform_point (&scaled_font->base.font_matrix,
522 &gx, &gy);
523
524 (*glyphs)[i].x = gx + x;
525 (*glyphs)[i].y = gy + y;
526 }
527 }
528
529 return status;
530}
531
532static cairo_status_t
533_cairo_user_font_face_scaled_font_create (void *abstract_face,
534 const cairo_matrix_t *font_matrix,
535 const cairo_matrix_t *ctm,
536 const cairo_font_options_t *options,
537 cairo_scaled_font_t **scaled_font);
538
539static cairo_status_t
540_cairo_user_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
541 cairo_font_face_t **font_face)
542{
543 return _cairo_font_face_twin_create_for_toy (toy_face, font_face);
544}
545
546static const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = {
547 CAIRO_FONT_TYPE_USER,
548 _cairo_user_scaled_glyph_fini,
549 _cairo_user_scaled_glyph_init,
550 _cairo_user_text_to_glyphs,
551 _cairo_user_ucs4_to_index,
552 NULL((void*)0), /* load_truetype_table */
553 NULL((void*)0), /* index_to_ucs4 */
554 NULL((void*)0), /* is_synthetic */
555 NULL((void*)0), /* index_to_glyph_name */
556 NULL((void*)0), /* load_type1_data */
557 _cairo_user_has_color_glyphs,
558};
559
560/* #cairo_user_font_face_t */
561
562static cairo_status_t
563_cairo_user_font_face_scaled_font_create (void *abstract_face,
564 const cairo_matrix_t *font_matrix,
565 const cairo_matrix_t *ctm,
566 const cairo_font_options_t *options,
567 cairo_scaled_font_t **scaled_font)
568{
569 cairo_status_t status = CAIRO_STATUS_SUCCESS;
570 cairo_user_font_face_t *font_face = abstract_face;
571 cairo_user_scaled_font_t *user_scaled_font = NULL((void*)0);
572 cairo_font_extents_t font_extents = {1., 0., 1., 1., 0.};
573
574 font_face->immutable = TRUE1;
575
576 user_scaled_font = _cairo_malloc (sizeof (cairo_user_scaled_font_t))((sizeof (cairo_user_scaled_font_t)) != 0 ? malloc(sizeof (cairo_user_scaled_font_t
)) : ((void*)0))
;
577 if (unlikely (user_scaled_font == NULL)(__builtin_expect (!!(user_scaled_font == ((void*)0)), 0)))
578 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
579
580 status = _cairo_scaled_font_init (&user_scaled_font->base,
581 &font_face->base,
582 font_matrix, ctm, options,
583 &_cairo_user_scaled_font_backend);
584
585 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
586 free (user_scaled_font);
587 return status;
588 }
589
590 user_scaled_font->foreground_pattern = NULL((void*)0);
591 user_scaled_font->foreground_marker = _cairo_pattern_create_foreground_marker ();
592
593 /* XXX metrics hinting? */
594
595 /* compute a normalized version of font scale matrix to compute
596 * extents in. This is to minimize error caused by the cairo_fixed_t
597 * representation. */
598 {
599 double fixed_scale, x_scale, y_scale;
600
601 user_scaled_font->snap_x_scale = 1.0;
602 user_scaled_font->snap_y_scale = 1.0;
603 user_scaled_font->extent_scale = user_scaled_font->base.scale_inverse;
604 status = _cairo_matrix_compute_basis_scale_factors (&user_scaled_font->extent_scale,
605 &x_scale, &y_scale,
606 1);
607 if (status == CAIRO_STATUS_SUCCESS) {
608
609 if (x_scale == 0) x_scale = 1.;
610 if (y_scale == 0) y_scale = 1.;
611
612 user_scaled_font->snap_x_scale = x_scale;
613 user_scaled_font->snap_y_scale = y_scale;
614
615 /* since glyphs are pretty much 1.0x1.0, we can reduce error by
616 * scaling to a larger square. say, 1024.x1024. */
617 fixed_scale = 1024.;
618 x_scale /= fixed_scale;
619 y_scale /= fixed_scale;
620
621 cairo_matrix_scale_moz_cairo_matrix_scale (&user_scaled_font->extent_scale, 1. / x_scale, 1. / y_scale);
622
623 user_scaled_font->extent_x_scale = x_scale;
624 user_scaled_font->extent_y_scale = y_scale;
625 }
626 }
627
628 if (status == CAIRO_STATUS_SUCCESS &&
629 font_face->scaled_font_methods.init != NULL((void*)0))
630 {
631 /* Lock the scaled_font mutex such that user doesn't accidentally try
632 * to use it just yet. */
633 CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex)pthread_mutex_lock (&(user_scaled_font->base.mutex));
634
635 /* Give away fontmap lock such that user-font can use other fonts */
636 status = _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base);
637 if (status == CAIRO_STATUS_SUCCESS) {
638 cairo_surface_t *recording_surface;
639 cairo_t *cr;
640
641 recording_surface = _cairo_user_scaled_font_create_recording_surface (user_scaled_font, FALSE0, NULL((void*)0));
642 cr = _cairo_user_scaled_font_create_recording_context (user_scaled_font, recording_surface, FALSE0);
643 cairo_surface_destroy_moz_cairo_surface_destroy (recording_surface);
644
645 status = font_face->scaled_font_methods.init (&user_scaled_font->base,
646 cr,
647 &font_extents);
648
649 if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
650 status = CAIRO_STATUS_SUCCESS;
651
652 if (status == CAIRO_STATUS_SUCCESS)
653 status = cairo_status_moz_cairo_status (cr);
654
655 cairo_destroy_moz_cairo_destroy (cr);
656
657 _cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base);
658 }
659
660 CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex)pthread_mutex_unlock (&(user_scaled_font->base.mutex));
661 }
662
663 if (status == CAIRO_STATUS_SUCCESS)
664 status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
665
666 if (status != CAIRO_STATUS_SUCCESS) {
667 _cairo_scaled_font_fini (&user_scaled_font->base);
668 free (user_scaled_font);
669 } else {
670 user_scaled_font->default_glyph_extents.x_bearing = 0.;
671 user_scaled_font->default_glyph_extents.y_bearing = -font_extents.ascent;
672 user_scaled_font->default_glyph_extents.width = 0.;
673 user_scaled_font->default_glyph_extents.height = font_extents.ascent + font_extents.descent;
674 user_scaled_font->default_glyph_extents.x_advance = font_extents.max_x_advance;
675 user_scaled_font->default_glyph_extents.y_advance = 0.;
676
677 *scaled_font = &user_scaled_font->base;
678 }
679
680 return status;
681}
682
683const cairo_font_face_backend_t _cairo_user_font_face_backend = {
684 CAIRO_FONT_TYPE_USER,
685 _cairo_user_font_face_create_for_toy,
686 _cairo_font_face_destroy,
687 _cairo_user_font_face_scaled_font_create
688};
689
690
691cairo_bool_t
692_cairo_font_face_is_user (cairo_font_face_t *font_face)
693{
694 return font_face->backend == &_cairo_user_font_face_backend;
695}
696
697/* Implement the public interface */
698
699/**
700 * cairo_user_font_face_create:
701 *
702 * Creates a new user font-face.
703 *
704 * Use the setter functions to associate callbacks with the returned
705 * user font. The only mandatory callback is render_glyph.
706 *
707 * After the font-face is created, the user can attach arbitrary data
708 * (the actual font data) to it using cairo_font_face_set_user_data()
709 * and access it from the user-font callbacks by using
710 * cairo_scaled_font_get_font_face() followed by
711 * cairo_font_face_get_user_data().
712 *
713 * Return value: a newly created #cairo_font_face_t. Free with
714 * cairo_font_face_destroy() when you are done using it.
715 *
716 * Since: 1.8
717 **/
718cairo_font_face_t *
719cairo_user_font_face_create_moz_cairo_user_font_face_create (void)
720{
721 cairo_user_font_face_t *font_face;
722
723 font_face = _cairo_malloc (sizeof (cairo_user_font_face_t))((sizeof (cairo_user_font_face_t)) != 0 ? malloc(sizeof (cairo_user_font_face_t
)) : ((void*)0))
;
724 if (!font_face) {
725 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
726 return (cairo_font_face_t *)&_cairo_font_face_nil;
727 }
728
729 _cairo_font_face_init (&font_face->base, &_cairo_user_font_face_backend);
730
731 font_face->immutable = FALSE0;
732 font_face->has_color = FALSE0;
733 memset (&font_face->scaled_font_methods, 0, sizeof (font_face->scaled_font_methods));
734
735 return &font_face->base;
736}
737
738/* User-font method setters */
739
740
741/**
742 * cairo_user_font_face_set_init_func:
743 * @font_face: A user font face
744 * @init_func: The init callback, or %NULL
745 *
746 * Sets the scaled-font initialization function of a user-font.
747 * See #cairo_user_scaled_font_init_func_t for details of how the callback
748 * works.
749 *
750 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
751 * error will occur. A user font-face is immutable as soon as a scaled-font
752 * is created from it.
753 *
754 * Since: 1.8
755 **/
756void
757cairo_user_font_face_set_init_func_moz_cairo_user_font_face_set_init_func (cairo_font_face_t *font_face,
758 cairo_user_scaled_font_init_func_t init_func)
759{
760 cairo_user_font_face_t *user_font_face;
761
762 if (font_face->status)
763 return;
764
765 if (! _cairo_font_face_is_user (font_face)) {
766 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
767 return;
768 }
769
770 user_font_face = (cairo_user_font_face_t *) font_face;
771 if (user_font_face->immutable) {
772 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
773 return;
774 }
775 user_font_face->scaled_font_methods.init = init_func;
776}
777
778/**
779 * cairo_user_font_face_set_render_color_glyph_func:
780 * @font_face: A user font face
781 * @render_glyph_func: The render_glyph callback, or %NULL
782 *
783 * Sets the color glyph rendering function of a user-font.
784 * See #cairo_user_scaled_font_render_glyph_func_t for details of how the callback
785 * works.
786 *
787 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
788 * error will occur. A user font-face is immutable as soon as a scaled-font
789 * is created from it.
790 *
791 * The render_glyph callback is the only mandatory callback of a
792 * user-font. At least one of
793 * cairo_user_font_face_set_render_color_glyph_func() or
794 * cairo_user_font_face_set_render_glyph_func() must be called to set
795 * a render callback. If both callbacks are set, the color glyph
796 * render callback is invoked first. If the color glyph render
797 * callback returns %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED, the
798 * non-color version of the callback is invoked.
799 *
800 * If the callback is %NULL and a glyph is tried to be rendered using
801 * @font_face, a %CAIRO_STATUS_USER_FONT_ERROR will occur.
802 *
803 * Since: 1.18
804 **/
805void
806cairo_user_font_face_set_render_color_glyph_func (cairo_font_face_t *font_face,
807 cairo_user_scaled_font_render_glyph_func_t render_glyph_func)
808{
809 cairo_user_font_face_t *user_font_face;
810
811 if (font_face->status)
812 return;
813
814 if (! _cairo_font_face_is_user (font_face)) {
815 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
816 return;
817 }
818
819 user_font_face = (cairo_user_font_face_t *) font_face;
820 if (user_font_face->immutable) {
821 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
822 return;
823 }
824 user_font_face->scaled_font_methods.render_color_glyph = render_glyph_func;
825 user_font_face->has_color = render_glyph_func ? TRUE1 : FALSE0;
826}
827
828/**
829 * cairo_user_font_face_set_render_glyph_func:
830 * @font_face: A user font face
831 * @render_glyph_func: The render_glyph callback, or %NULL
832 *
833 * Sets the glyph rendering function of a user-font.
834 * See #cairo_user_scaled_font_render_glyph_func_t for details of how the callback
835 * works.
836 *
837 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
838 * error will occur. A user font-face is immutable as soon as a scaled-font
839 * is created from it.
840 *
841 * The render_glyph callback is the only mandatory callback of a
842 * user-font. At least one of
843 * cairo_user_font_face_set_render_color_glyph_func() or
844 * cairo_user_font_face_set_render_glyph_func() must be called to set
845 * a render callback. If both callbacks are set, the color glyph
846 * render callback is invoked first. If the color glyph render
847 * callback returns %CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED, the
848 * non-color version of the callback is invoked.
849 *
850 * If the callback is %NULL and a glyph is tried to be rendered using
851 * @font_face, a %CAIRO_STATUS_USER_FONT_ERROR will occur.
852 *
853 * Since: 1.8
854 **/
855void
856cairo_user_font_face_set_render_glyph_func_moz_cairo_user_font_face_set_render_glyph_func (cairo_font_face_t *font_face,
857 cairo_user_scaled_font_render_glyph_func_t render_glyph_func)
858{
859 cairo_user_font_face_t *user_font_face;
860
861 if (font_face->status)
862 return;
863
864 if (! _cairo_font_face_is_user (font_face)) {
865 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
866 return;
867 }
868
869 user_font_face = (cairo_user_font_face_t *) font_face;
870 if (user_font_face->immutable) {
871 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
872 return;
873 }
874 user_font_face->scaled_font_methods.render_glyph = render_glyph_func;
875}
876
877/**
878 * cairo_user_font_face_set_text_to_glyphs_func:
879 * @font_face: A user font face
880 * @text_to_glyphs_func: The text_to_glyphs callback, or %NULL
881 *
882 * Sets th text-to-glyphs conversion function of a user-font.
883 * See #cairo_user_scaled_font_text_to_glyphs_func_t for details of how the callback
884 * works.
885 *
886 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
887 * error will occur. A user font-face is immutable as soon as a scaled-font
888 * is created from it.
889 *
890 * Since: 1.8
891 **/
892void
893cairo_user_font_face_set_text_to_glyphs_func_moz_cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t *font_face,
894 cairo_user_scaled_font_text_to_glyphs_func_t text_to_glyphs_func)
895{
896 cairo_user_font_face_t *user_font_face;
897
898 if (font_face->status)
899 return;
900
901 if (! _cairo_font_face_is_user (font_face)) {
902 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
903 return;
904 }
905
906 user_font_face = (cairo_user_font_face_t *) font_face;
907 if (user_font_face->immutable) {
908 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
909 return;
910 }
911 user_font_face->scaled_font_methods.text_to_glyphs = text_to_glyphs_func;
912}
913
914/**
915 * cairo_user_font_face_set_unicode_to_glyph_func:
916 * @font_face: A user font face
917 * @unicode_to_glyph_func: The unicode_to_glyph callback, or %NULL
918 *
919 * Sets the unicode-to-glyph conversion function of a user-font.
920 * See #cairo_user_scaled_font_unicode_to_glyph_func_t for details of how the callback
921 * works.
922 *
923 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
924 * error will occur. A user font-face is immutable as soon as a scaled-font
925 * is created from it.
926 *
927 * Since: 1.8
928 **/
929void
930cairo_user_font_face_set_unicode_to_glyph_func_moz_cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t *font_face,
931 cairo_user_scaled_font_unicode_to_glyph_func_t unicode_to_glyph_func)
932{
933 cairo_user_font_face_t *user_font_face;
934 if (font_face->status)
935 return;
936
937 if (! _cairo_font_face_is_user (font_face)) {
938 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
939 return;
940 }
941
942 user_font_face = (cairo_user_font_face_t *) font_face;
943 if (user_font_face->immutable) {
944 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
945 return;
946 }
947 user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func;
948}
949
950/* User-font method getters */
951
952/**
953 * cairo_user_font_face_get_init_func:
954 * @font_face: A user font face
955 *
956 * Gets the scaled-font initialization function of a user-font.
957 *
958 * Return value: The init callback of @font_face
959 * or %NULL if none set or an error has occurred.
960 *
961 * Since: 1.8
962 **/
963cairo_user_scaled_font_init_func_t
964cairo_user_font_face_get_init_func_moz_cairo_user_font_face_get_init_func (cairo_font_face_t *font_face)
965{
966 cairo_user_font_face_t *user_font_face;
967
968 if (font_face->status)
969 return NULL((void*)0);
970
971 if (! _cairo_font_face_is_user (font_face)) {
972 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
973 return NULL((void*)0);
974 }
975
976 user_font_face = (cairo_user_font_face_t *) font_face;
977 return user_font_face->scaled_font_methods.init;
978}
979
980/**
981 * cairo_user_font_face_get_render_color_glyph_func:
982 * @font_face: A user font face
983 *
984 * Gets the color glyph rendering function of a user-font.
985 *
986 * Return value: The render_glyph callback of @font_face
987 * or %NULL if none set or an error has occurred.
988 *
989 * Since: 1.18
990 **/
991cairo_user_scaled_font_render_glyph_func_t
992cairo_user_font_face_get_render_color_glyph_func (cairo_font_face_t *font_face)
993{
994 cairo_user_font_face_t *user_font_face;
995
996 if (font_face->status)
997 return NULL((void*)0);
998
999 if (! _cairo_font_face_is_user (font_face)) {
1000 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
1001 return NULL((void*)0);
1002 }
1003
1004 user_font_face = (cairo_user_font_face_t *) font_face;
1005 return user_font_face->scaled_font_methods.render_color_glyph;
1006}
1007
1008/**
1009 * cairo_user_font_face_get_render_glyph_func:
1010 * @font_face: A user font face
1011 *
1012 * Gets the glyph rendering function of a user-font.
1013 *
1014 * Return value: The render_glyph callback of @font_face
1015 * or %NULL if none set or an error has occurred.
1016 *
1017 * Since: 1.8
1018 **/
1019cairo_user_scaled_font_render_glyph_func_t
1020cairo_user_font_face_get_render_glyph_func_moz_cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face)
1021{
1022 cairo_user_font_face_t *user_font_face;
1023
1024 if (font_face->status)
1025 return NULL((void*)0);
1026
1027 if (! _cairo_font_face_is_user (font_face)) {
1028 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
1029 return NULL((void*)0);
1030 }
1031
1032 user_font_face = (cairo_user_font_face_t *) font_face;
1033 return user_font_face->scaled_font_methods.render_glyph;
1034}
1035
1036/**
1037 * cairo_user_font_face_get_text_to_glyphs_func:
1038 * @font_face: A user font face
1039 *
1040 * Gets the text-to-glyphs conversion function of a user-font.
1041 *
1042 * Return value: The text_to_glyphs callback of @font_face
1043 * or %NULL if none set or an error occurred.
1044 *
1045 * Since: 1.8
1046 **/
1047cairo_user_scaled_font_text_to_glyphs_func_t
1048cairo_user_font_face_get_text_to_glyphs_func_moz_cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face)
1049{
1050 cairo_user_font_face_t *user_font_face;
1051
1052 if (font_face->status)
1053 return NULL((void*)0);
1054
1055 if (! _cairo_font_face_is_user (font_face)) {
1056 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
1057 return NULL((void*)0);
1058 }
1059
1060 user_font_face = (cairo_user_font_face_t *) font_face;
1061 return user_font_face->scaled_font_methods.text_to_glyphs;
1062}
1063
1064/**
1065 * cairo_user_font_face_get_unicode_to_glyph_func:
1066 * @font_face: A user font face
1067 *
1068 * Gets the unicode-to-glyph conversion function of a user-font.
1069 *
1070 * Return value: The unicode_to_glyph callback of @font_face
1071 * or %NULL if none set or an error occurred.
1072 *
1073 * Since: 1.8
1074 **/
1075cairo_user_scaled_font_unicode_to_glyph_func_t
1076cairo_user_font_face_get_unicode_to_glyph_func_moz_cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face)
1077{
1078 cairo_user_font_face_t *user_font_face;
1079
1080 if (font_face->status)
1081 return NULL((void*)0);
1082
1083 if (! _cairo_font_face_is_user (font_face)) {
1084 if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
1085 return NULL((void*)0);
1086 }
1087
1088 user_font_face = (cairo_user_font_face_t *) font_face;
1089 return user_font_face->scaled_font_methods.unicode_to_glyph;
1090}
1091
1092/**
1093 * cairo_user_scaled_font_get_foreground_marker:
1094 * @scaled_font: A user scaled font
1095 *
1096 * Gets the foreground pattern of the glyph currently being
1097 * rendered. A #cairo_user_scaled_font_render_glyph_func_t function
1098 * that has been set with
1099 * cairo_user_font_face_set_render_color_glyph_func() may call this
1100 * function to retrieve the current foreground pattern for the glyph
1101 * being rendered. The function should not be called outside of a
1102 * cairo_user_font_face_set_render_color_glyph_func() callback.
1103 *
1104 * The foreground marker pattern contains an internal marker to
1105 * indicate that it is to be substituted with the current source when
1106 * rendered to a surface. Querying the foreground marker will reveal a
1107 * solid black color, however this is not representative of the color
1108 * that will actually be used. Similarly, setting a solid black color
1109 * will render black, not the foreground pattern when the glyph is
1110 * painted to a surface. Using the foreground marker as the source
1111 * instead of cairo_user_scaled_font_get_foreground_source() in a
1112 * color render callback has the following benefits:
1113 *
1114 * 1. Cairo only needs to call the render callback once as it can
1115 * cache the recording. Cairo will substitute the actual foreground
1116 * color when rendering the recording.
1117 *
1118 * 2. On backends that have the concept of a foreground color in fonts such as
1119 * PDF, PostScript, and SVG, cairo can generate more optimal
1120 * output. The glyph can be included in an embedded font.
1121 *
1122 * The one drawback of the using foreground marker is the render
1123 * callback can not access the color components of the pattern as the
1124 * actual foreground pattern is not available at the time the render
1125 * callback is invoked. If the render callback needs to query the
1126 * foreground pattern, use
1127 * cairo_user_scaled_font_get_foreground_source().
1128 *
1129 * If the render callback simply wants to call cairo_set_source() with
1130 * the foreground pattern,
1131 * cairo_user_scaled_font_get_foreground_marker() is the preferred
1132 * function to use as it results in better performance than
1133 * cairo_user_scaled_font_get_foreground_source().
1134 *
1135 * Return value: the current foreground source marker pattern. This
1136 * object is owned by cairo. This object must not be modified or used
1137 * outside of a color render callback. To keep a reference to it,
1138 * you must call cairo_pattern_reference().
1139 *
1140 * Since: 1.18
1141 **/
1142cairo_pattern_t *
1143cairo_user_scaled_font_get_foreground_marker (cairo_scaled_font_t *scaled_font)
1144{
1145 cairo_user_scaled_font_t *user_scaled_font;
1146
1147 if (scaled_font->backend != &_cairo_user_scaled_font_backend)
1148 return _cairo_pattern_create_in_error (CAIRO_STATUS_FONT_TYPE_MISMATCH);
1149
1150 user_scaled_font = (cairo_user_scaled_font_t *)scaled_font;
1151 return user_scaled_font->foreground_marker;
1152}
1153
1154/**
1155 * cairo_user_scaled_font_get_foreground_source:
1156 * @scaled_font: A user scaled font
1157 *
1158 * Gets the foreground pattern of the glyph currently being
1159 * rendered. A #cairo_user_scaled_font_render_glyph_func_t function
1160 * that has been set with
1161 * cairo_user_font_face_set_render_color_glyph_func() may call this
1162 * function to retrieve the current foreground pattern for the glyph
1163 * being rendered. The function should not be called outside of a
1164 * cairo_user_font_face_set_render_color_glyph_func() callback.
1165 *
1166 * This function returns the current source at the time the glyph is
1167 * rendered. Compared with
1168 * cairo_user_scaled_font_get_foreground_marker(), this function
1169 * returns the actual source pattern that will be used to render the
1170 * glyph. The render callback is free to query the pattern and
1171 * extract color components or other pattern data. For example if the
1172 * render callback wants to create a gradient stop based on colors in
1173 * the foreground source pattern, it will need to use this function in
1174 * order to be able to query the colors in the foreground pattern.
1175 *
1176 * While this function does not have the restrictions on using the
1177 * pattern that cairo_user_scaled_font_get_foreground_marker() has, it
1178 * does incur a performance penalty. If a render callback calls this
1179 * function:
1180 *
1181 * 1. Cairo will call the render callback whenever the current pattern
1182 * of the context in which the glyph is rendered changes.
1183 *
1184 * 2. On backends that support font embedding (PDF, PostScript, and
1185 * SVG), cairo can not embed this glyph in a font. Instead the glyph
1186 * will be emitted as an image or sequence of drawing operations each
1187 * time it is used.
1188 *
1189 * Return value: the current foreground source pattern. This object is
1190 * owned by cairo. To keep a reference to it, you must call
1191 * cairo_pattern_reference().
1192 *
1193 * Since: 1.18
1194 **/
1195cairo_pattern_t *
1196cairo_user_scaled_font_get_foreground_source (cairo_scaled_font_t *scaled_font)
1197{
1198 cairo_user_scaled_font_t *user_scaled_font;
1199
1200 if (scaled_font->backend != &_cairo_user_scaled_font_backend)
1201 return _cairo_pattern_create_in_error (CAIRO_STATUS_FONT_TYPE_MISMATCH);
1202
1203 user_scaled_font = (cairo_user_scaled_font_t *)scaled_font;
1204 user_scaled_font->foreground_colors_used = TRUE1;
1205 return user_scaled_font->foreground_pattern;
1206}