Bug Summary

File:root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c
Warning:line 1718, column 5
1st function call argument is an uninitialized value

Annotated Source Code

Press '?' to see keyboard shortcuts

clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -O2 -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name cairo-ft-font.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-23/lib/clang/23 -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 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-23/lib/clang/23/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/16/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -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-character-conversion -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 -fdiagnostics-absolute-paths -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -mllvm -dwarf-linkage-names=Abstract -faddrsig -fdwarf2-cfi-asm -o /tmp/scan-build-2026-09-01-224014-2642839-1 -x c /root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c
1/* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2/* cairo - a vector graphics library with display and print output
3 *
4 * Copyright © 2000 Keith Packard
5 * Copyright © 2005 Red Hat, Inc
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it either under the terms of the GNU Lesser General Public
9 * License version 2.1 as published by the Free Software Foundation
10 * (the "LGPL") or, at your option, under the terms of the Mozilla
11 * Public License Version 1.1 (the "MPL"). If you do not alter this
12 * notice, a recipient may use your version of this file under either
13 * the MPL or the LGPL.
14 *
15 * You should have received a copy of the LGPL along with this library
16 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
18 * You should have received a copy of the MPL along with this library
19 * in the file COPYING-MPL-1.1
20 *
21 * The contents of this file are subject to the Mozilla Public License
22 * Version 1.1 (the "License"); you may not use this file except in
23 * compliance with the License. You may obtain a copy of the License at
24 * http://www.mozilla.org/MPL/
25 *
26 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
27 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
28 * the specific language governing rights and limitations.
29 *
30 * The Original Code is the cairo graphics library.
31 *
32 * The Initial Developer of the Original Code is Red Hat, Inc.
33 *
34 * Contributor(s):
35 * Graydon Hoare <graydon@redhat.com>
36 * Owen Taylor <otaylor@redhat.com>
37 * Keith Packard <keithp@keithp.com>
38 * Carl Worth <cworth@cworth.org>
39 */
40
41#define _DEFAULT_SOURCE1 /* for strdup() */
42#include "cairoint.h"
43
44#include "cairo-error-private.h"
45#include "cairo-image-surface-private.h"
46#include "cairo-ft-private.h"
47#include "cairo-list-inline.h"
48#include "cairo-path-private.h"
49#include "cairo-pattern-private.h"
50#include "cairo-pixman-private.h"
51#include "cairo-recording-surface-private.h"
52
53#include <float.h>
54
55#include "cairo-fontconfig-private.h"
56
57#include <ft2build.h>
58#include FT_FREETYPE_H<freetype/freetype.h>
59#include FT_OUTLINE_H<freetype/ftoutln.h>
60#include FT_IMAGE_H<freetype/ftimage.h>
61#include FT_BITMAP_H<freetype/ftbitmap.h>
62#include FT_TRUETYPE_TABLES_H<freetype/tttables.h>
63#ifndef FT_FONT_FORMATS_H<freetype/ftfntfmt.h>
64#define FT_FONT_FORMATS_H<freetype/ftfntfmt.h> FT_XFREE86_H<freetype/ftfntfmt.h>
65#define FT_Get_Font_Format FT_Get_X11_Font_Format
66#endif
67#include FT_FONT_FORMATS_H<freetype/ftfntfmt.h>
68#include FT_MULTIPLE_MASTERS_H<freetype/ftmm.h>
69#include FT_SYNTHESIS_H<freetype/ftsynth.h>
70
71#ifdef FT_COLOR_H<freetype/ftcolor.h>
72#include FT_COLOR_H<freetype/ftcolor.h>
73#endif
74
75#include FT_LCD_FILTER_H<freetype/ftlcdfil.h>
76
77#if HAVE_FT_SVG_DOCUMENT
78#include FT_OTSVG_H<freetype/otsvg.h>
79#endif
80
81#if HAVE_UNISTD_H1
82#include <unistd.h>
83#elif !defined(access)
84#define access(p, m) 0
85#endif
86#include <dlfcn.h>
87
88/* FreeType version older than 2.11 does not have the FT_RENDER_MODE_SDF enum value in FT_Render_Mode */
89#if FREETYPE_MAJOR2 > 2 || (FREETYPE_MAJOR2 == 2 && FREETYPE_MINOR14 >= 11)
90#define HAVE_FT_RENDER_MODE_SDF1 1
91#endif
92
93#define DOUBLE_FROM_26_6(t)((double)(t) / 64.0) ((double)(t) / 64.0)
94#define DOUBLE_TO_16_16(d)((FT_Fixed)((d) * 65536.0)) ((FT_Fixed)((d) * 65536.0))
95#define DOUBLE_FROM_16_16(t)((double)(t) / 65536.0) ((double)(t) / 65536.0)
96
97/* SCALE() mimics code from commit 399b00a99b2bbc1c56a05974c936aa69a08021f5
98 * concerning a potential division by 0, but instead of doing a * (1/b), it
99 * does a/b, thus improving the accuracy. With a * (1/b), for a bitmap font
100 * of size 13, the computed -y_bearing was 0x1.6000000000001p+3 instead of
101 * 0x1.6p+3 (= 11). This triggered a bug in GNU Emacs (when built against
102 * cairo), which rounded the value to an integer with ceil().
103 * Details:
104 * https://gitlab.freedesktop.org/cairo/cairo/-/issues/503
105 * https://debbugs.gnu.org/cgi/bugreport.cgi?bug=44284
106 *
107 * Note that rounding errors are not necessarily expected by applications
108 * in simple cases like the GNU Emacs one (an identity transformation,
109 * which should normally leave the inputs unchanged). However, with the
110 * current cairo code, due to the scaling, there is no guarantee that
111 * rounding errors will always be avoided at the end. For instance,
112 * (a/b)*b may be different from a, but this is still better than doing
113 * (a*(1/b))*b.
114 *
115 * According to the commit mentioned above, avoiding a division by zero
116 * was an attempt to fix
117 * https://bugzilla.gnome.org/show_bug.cgi?id=311299
118 * but this did not actually solve the problem. So it might be possible
119 * to change SCALE() to just do (a) / (b).
120 */
121#define SCALE(a,b)((b) == 0 ? 0.0 : (a) / (b)) ((b) == 0 ? 0.0 : (a) / (b))
122
123/* This is the max number of FT_face objects we keep open at once
124 */
125#define MAX_OPEN_FACES10 10
126
127extern void mozilla_AddRefSharedFTFace(void* aContext);
128extern void mozilla_ReleaseSharedFTFace(void* aContext, void* aOwner);
129/* Returns true if the face's state has been modified by another owner. */
130extern int mozilla_LockSharedFTFace(void* aContext, void* aOwner);
131extern void mozilla_UnlockSharedFTFace(void* aContext);
132extern FT_Error mozilla_LoadFTGlyph(FT_Face aFace, uint32_t aGlyphIndex, int32_t aFlags);
133extern void mozilla_LockFTLibrary(FT_Library aLibrary);
134extern void mozilla_UnlockFTLibrary(FT_Library aLibrary);
135
136#define CAIRO_FT_LOCK(unscaled)((unscaled)->face_context ? (void)mozilla_LockSharedFTFace
((unscaled)->face_context, ((void*)0)) : (void)pthread_mutex_lock
(&((unscaled)->mutex)))
\
137 ((unscaled)->face_context \
138 ? (void)mozilla_LockSharedFTFace((unscaled)->face_context, NULL((void*)0)) \
139 : (void)CAIRO_MUTEX_LOCK((unscaled)->mutex)pthread_mutex_lock (&((unscaled)->mutex)))
140#define CAIRO_FT_UNLOCK(unscaled)((unscaled)->face_context ? mozilla_UnlockSharedFTFace((unscaled
)->face_context) : (void)pthread_mutex_unlock (&((unscaled
)->mutex)))
\
141 ((unscaled)->face_context \
142 ? mozilla_UnlockSharedFTFace((unscaled)->face_context) \
143 : (void)CAIRO_MUTEX_UNLOCK((unscaled)->mutex)pthread_mutex_unlock (&((unscaled)->mutex)))
144
145/**
146 * Function types for FreeType symbols we'll look up at runtime, rather than
147 * relying on build-time checks for availability.
148 */
149typedef FT_Error (*GetVarFunc) (FT_Face, FT_MM_Var**);
150typedef FT_Error (*DoneVarFunc) (FT_Library, FT_MM_Var*);
151typedef FT_Error (*GetVarDesignCoordsFunc) (FT_Face, FT_UInt, FT_Fixed*);
152typedef FT_Error (*SetVarDesignCoordsFunc) (FT_Face, FT_UInt, FT_Fixed*);
153typedef FT_Error (*GetVarBlendCoordsFunc) (FT_Face, FT_UInt, FT_Fixed*);
154
155/**
156 * SECTION:cairo-ft
157 * @Title: FreeType Fonts
158 * @Short_Description: Font support for FreeType
159 * @See_Also: #cairo_font_face_t
160 *
161 * The FreeType font backend is primarily used to render text on GNU/Linux
162 * systems, but can be used on other platforms too.
163 **/
164
165/**
166 * CAIRO_HAS_FT_FONT:
167 *
168 * Defined if the FreeType font backend is available.
169 * This macro can be used to conditionally compile backend-specific code.
170 *
171 * Since: 1.0
172 **/
173
174/**
175 * CAIRO_HAS_FC_FONT:
176 *
177 * Defined if the Fontconfig-specific functions of the FreeType font backend
178 * are available.
179 * This macro can be used to conditionally compile backend-specific code.
180 *
181 * Since: 1.10
182 **/
183
184/*
185 * The simple 2x2 matrix is converted into separate scale and shape
186 * factors so that hinting works right
187 */
188
189typedef struct _cairo_ft_font_transform {
190 double x_scale, y_scale;
191 double shape[2][2];
192} cairo_ft_font_transform_t;
193
194/*
195 * We create an object that corresponds to a single font on the disk;
196 * (identified by a filename/id pair) these are shared between all
197 * fonts using that file. For cairo_ft_font_face_create_for_ft_face(), we
198 * just create a one-off version with a permanent face value.
199 */
200
201typedef struct _cairo_ft_font_face cairo_ft_font_face_t;
202
203struct _cairo_ft_unscaled_font {
204 cairo_unscaled_font_t base;
205
206 cairo_bool_t from_face; /* was the FT_Face provided by user? */
207 FT_Face face; /* provided or cached face */
208 void *face_context;
209
210 /* only set if from_face is false */
211 char *filename;
212 int id;
213
214 /* We temporarily scale the unscaled font as needed */
215 cairo_bool_t have_scale;
216 cairo_matrix_t current_scale;
217 double x_scale; /* Extracted X scale factor */
218 double y_scale; /* Extracted Y scale factor */
219 cairo_bool_t have_shape; /* true if the current scale has a non-scale component*/
220 cairo_matrix_t current_shape;
221 FT_Matrix Current_Shape;
222
223 unsigned int have_color_set : 1;
224 unsigned int have_color : 1; /* true if the font contains color glyphs */
225 FT_Fixed *variations; /* variation settings that FT_Face came */
226 unsigned int num_palettes;
227
228 cairo_mutex_t mutex;
229 int lock_count;
230
231 cairo_ft_font_face_t *faces; /* Linked list of faces for this font */
232};
233
234static int
235_cairo_ft_unscaled_font_keys_equal (const void *key_a,
236 const void *key_b);
237
238static void
239_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled);
240
241typedef struct _cairo_ft_options {
242 cairo_font_options_t base;
243 unsigned int load_flags; /* flags for FT_Load_Glyph */
244 unsigned int synth_flags;
245} cairo_ft_options_t;
246
247static void
248_cairo_ft_options_init_copy (cairo_ft_options_t *options,
249 const cairo_ft_options_t *other)
250{
251 _cairo_font_options_init_copy (&options->base, &other->base);
252 options->load_flags = other->load_flags;
253 options->synth_flags = other->synth_flags;
254}
255
256static void
257_cairo_ft_options_fini (cairo_ft_options_t *options)
258{
259 _cairo_font_options_fini (&options->base);
260}
261
262struct _cairo_ft_font_face {
263 cairo_font_face_t base;
264
265 cairo_ft_unscaled_font_t *unscaled;
266 cairo_ft_options_t ft_options;
267 cairo_ft_font_face_t *next;
268
269#if CAIRO_HAS_FC_FONT1
270 FcPattern *pattern; /* if pattern is set, the above fields will be NULL */
271 cairo_font_face_t *resolved_font_face;
272 FcConfig *resolved_config;
273#endif
274};
275
276static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;
277
278#if CAIRO_HAS_FC_FONT1
279static cairo_status_t
280_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
281 FcPattern *pattern);
282
283static cairo_font_face_t *
284_cairo_ft_resolve_pattern (FcPattern *pattern,
285 const cairo_matrix_t *font_matrix,
286 const cairo_matrix_t *ctm,
287 const cairo_font_options_t *options);
288
289#endif
290
291cairo_status_t
292_cairo_ft_to_cairo_error (FT_Error error)
293{
294 /* Currently we don't get many (any?) useful statuses here.
295 * Populate as needed. */
296 switch (error)
297 {
298 case FT_Err_Ok:
299 return CAIRO_STATUS_SUCCESS;
300 case FT_Err_Out_Of_Memory:
301 return CAIRO_STATUS_NO_MEMORY;
302 default:
303 return CAIRO_STATUS_FREETYPE_ERROR;
304 }
305}
306
307/*
308 * We maintain a hash table to map file/id => #cairo_ft_unscaled_font_t.
309 * The hash table itself isn't limited in size. However, we limit the
310 * number of FT_Face objects we keep around; when we've exceeded that
311 * limit and need to create a new FT_Face, we dump the FT_Face from a
312 * random #cairo_ft_unscaled_font_t which has an unlocked FT_Face, (if
313 * there are any).
314 */
315
316typedef struct _cairo_ft_unscaled_font_map {
317 cairo_hash_table_t *hash_table;
318 FT_Library ft_library;
319 int num_open_faces;
320} cairo_ft_unscaled_font_map_t;
321
322static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL((void*)0);
323
324
325static FT_Face
326_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled);
327
328static void
329_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled);
330
331static cairo_bool_t
332_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font);
333
334
335static void
336_font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
337 cairo_ft_unscaled_font_t *unscaled)
338{
339 if (unscaled->face) {
340 FT_Done_Face (unscaled->face);
341 unscaled->face = NULL((void*)0);
342 unscaled->have_scale = FALSE0;
343
344 font_map->num_open_faces--;
345 }
346}
347
348static cairo_status_t
349_cairo_ft_unscaled_font_map_create (void)
350{
351 cairo_ft_unscaled_font_map_t *font_map;
352
353 /* This function is only intended to be called from
354 * _cairo_ft_unscaled_font_map_lock. So we'll crash if we can
355 * detect some other call path. */
356 assert (cairo_ft_unscaled_font_map == NULL)((void) sizeof (__assert_single_arg (cairo_ft_unscaled_font_map
== ((void*)0))), __extension__ ({ if (cairo_ft_unscaled_font_map
== ((void*)0)) ; else __assert_fail ("cairo_ft_unscaled_font_map == NULL"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c", 356
, __extension__ __PRETTY_FUNCTION__); }))
;
357
358 font_map = _cairo_calloc (sizeof (cairo_ft_unscaled_font_map_t))((sizeof (cairo_ft_unscaled_font_map_t)) != 0 ? calloc(1,sizeof
(cairo_ft_unscaled_font_map_t)) : ((void*)0))
;
359 if (unlikely (font_map == NULL)(__builtin_expect (!!(font_map == ((void*)0)), 0)))
360 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
361
362 font_map->hash_table =
363 _cairo_hash_table_create (_cairo_ft_unscaled_font_keys_equal);
364
365 if (unlikely (font_map->hash_table == NULL)(__builtin_expect (!!(font_map->hash_table == ((void*)0)),
0))
)
366 goto FAIL;
367
368 if (unlikely (FT_Init_FreeType (&font_map->ft_library))(__builtin_expect (!!(FT_Init_FreeType (&font_map->ft_library
)), 0))
)
369 goto FAIL;
370
371 font_map->num_open_faces = 0;
372
373 cairo_ft_unscaled_font_map = font_map;
374 return CAIRO_STATUS_SUCCESS;
375
376FAIL:
377 if (font_map->hash_table)
378 _cairo_hash_table_destroy (font_map->hash_table);
379 free (font_map);
380
381 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
382}
383
384
385static void
386_cairo_ft_unscaled_font_map_pluck_entry (void *entry, void *closure)
387{
388 cairo_ft_unscaled_font_t *unscaled = entry;
389 cairo_ft_unscaled_font_map_t *font_map = closure;
390
391 _cairo_hash_table_remove (font_map->hash_table,
392 &unscaled->base.hash_entry);
393
394 if (unscaled->from_face)
395 mozilla_ReleaseSharedFTFace (unscaled->face_context, unscaled);
396 else
397 _font_map_release_face_lock_held (font_map, unscaled);
398
399 _cairo_ft_unscaled_font_fini (unscaled);
400 free (unscaled);
401}
402
403static void
404_cairo_ft_unscaled_font_map_destroy (void)
405{
406 cairo_ft_unscaled_font_map_t *font_map;
407
408 CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex)pthread_mutex_lock (&(_cairo_ft_unscaled_font_map_mutex));
409 font_map = cairo_ft_unscaled_font_map;
410 cairo_ft_unscaled_font_map = NULL((void*)0);
411 CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex)pthread_mutex_unlock (&(_cairo_ft_unscaled_font_map_mutex
))
;
412
413 if (font_map != NULL((void*)0)) {
414 _cairo_hash_table_foreach (font_map->hash_table,
415 _cairo_ft_unscaled_font_map_pluck_entry,
416 font_map);
417 assert (font_map->num_open_faces == 0)((void) sizeof (__assert_single_arg (font_map->num_open_faces
== 0)), __extension__ ({ if (font_map->num_open_faces == 0
) ; else __assert_fail ("font_map->num_open_faces == 0", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c"
, 417, __extension__ __PRETTY_FUNCTION__); }))
;
418
419 FT_Done_FreeType (font_map->ft_library);
420
421 _cairo_hash_table_destroy (font_map->hash_table);
422
423 free (font_map);
424 }
425}
426
427static cairo_ft_unscaled_font_map_t *
428_cairo_ft_unscaled_font_map_lock (void)
429{
430 CAIRO_MUTEX_INITIALIZE ()do { } while (0);
431
432 CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex)pthread_mutex_lock (&(_cairo_ft_unscaled_font_map_mutex));
433
434 if (unlikely (cairo_ft_unscaled_font_map == NULL)(__builtin_expect (!!(cairo_ft_unscaled_font_map == ((void*)0
)), 0))
) {
435 if (unlikely (_cairo_ft_unscaled_font_map_create ())(__builtin_expect (!!(_cairo_ft_unscaled_font_map_create ()),
0))
) {
436 CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex)pthread_mutex_unlock (&(_cairo_ft_unscaled_font_map_mutex
))
;
437 return NULL((void*)0);
438 }
439 }
440
441 return cairo_ft_unscaled_font_map;
442}
443
444static void
445_cairo_ft_unscaled_font_map_unlock (void)
446{
447 CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex)pthread_mutex_unlock (&(_cairo_ft_unscaled_font_map_mutex
))
;
448}
449
450static void
451_cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
452 cairo_bool_t from_face,
453 char *filename,
454 int id,
455 FT_Face face,
456 void *face_context)
457{
458 uintptr_t hash;
459
460 key->from_face = from_face;
461 key->filename = filename;
462 key->id = id;
463 key->face = face;
464 key->face_context = face_context;
465
466 hash = _cairo_hash_string (filename);
467 /* the constants are just arbitrary primes */
468 hash += ((uintptr_t) id) * 1607;
469 hash += ((uintptr_t) face) * 2137;
470
471 key->base.hash_entry.hash = hash;
472}
473
474/**
475 * _cairo_ft_unscaled_font_init:
476 *
477 * Initialize a #cairo_ft_unscaled_font_t.
478 *
479 * There are two basic flavors of #cairo_ft_unscaled_font_t, one
480 * created from an FT_Face and the other created from a filename/id
481 * pair. These two flavors are identified as from_face and !from_face.
482 *
483 * To initialize a from_face font, pass filename==%NULL, id=0 and the
484 * desired face.
485 *
486 * To initialize a !from_face font, pass the filename/id as desired
487 * and face==%NULL.
488 *
489 * Note that the code handles these two flavors in very distinct
490 * ways. For example there is a hash_table mapping
491 * filename/id->#cairo_unscaled_font_t in the !from_face case, but no
492 * parallel in the from_face case, (where the calling code would have
493 * to do its own mapping to ensure similar sharing).
494 **/
495static cairo_status_t
496_cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
497 cairo_bool_t from_face,
498 const char *filename,
499 int id,
500 FT_Face face,
501 void *face_context)
502{
503 _cairo_unscaled_font_init (&unscaled->base,
504 &cairo_ft_unscaled_font_backend);
505
506 unscaled->variations = NULL((void*)0);
507
508 if (from_face) {
509 FT_MM_Var *ft_mm_var;
510 unscaled->from_face = TRUE1;
511 _cairo_ft_unscaled_font_init_key (unscaled, TRUE1, NULL((void*)0), id, face, face_context);
512
513
514 unscaled->have_color = FT_HAS_COLOR (face)( !!( (face)->face_flags & ( 1L << 14 ) ) ) != 0;
515 unscaled->have_color_set = TRUE1;
516
517 static GetVarFunc getVar;
518 static DoneVarFunc doneVar;
519 static GetVarDesignCoordsFunc getVarDesignCoords;
520
521 static int firstTime = 1;
522 if (firstTime) {
523 getVar = (GetVarFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Get_MM_Var");
524 doneVar = (DoneVarFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Done_MM_Var");
525 getVarDesignCoords = (GetVarDesignCoordsFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Get_Var_Design_Coordinates");
526 firstTime = 0;
527 }
528
529 if (getVar && getVarDesignCoords) {
530 if (0 == (*getVar) (face, &ft_mm_var))
531 {
532 unscaled->variations = _cairo_calloc_ab (ft_mm_var->num_axis, sizeof (FT_Fixed));
533 if (unscaled->variations)
534 (*getVarDesignCoords) (face, ft_mm_var->num_axis, unscaled->variations);
535 if (doneVar)
536 (*doneVar) (face->glyph->library, ft_mm_var);
537 else
538 free (ft_mm_var);
539 }
540 }
541 } else {
542 char *filename_copy;
543
544 unscaled->from_face = FALSE0;
545 unscaled->face = NULL((void*)0);
546 unscaled->face_context = NULL((void*)0);
547
548 filename_copy = strdup (filename);
549 if (unlikely (filename_copy == NULL)(__builtin_expect (!!(filename_copy == ((void*)0)), 0)))
550 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
551
552 _cairo_ft_unscaled_font_init_key (unscaled, FALSE0, filename_copy, id, NULL((void*)0), NULL((void*)0));
553
554 unscaled->have_color_set = FALSE0;
555 }
556
557 unscaled->have_scale = FALSE0;
558 CAIRO_MUTEX_INIT (unscaled->mutex)do { cairo_mutex_t _tmp_mutex = { { 0, 0, 0, 0, PTHREAD_MUTEX_TIMED_NP
, 0, 0, { ((void*)0), ((void*)0) } } }; memcpy (&(unscaled
->mutex), &_tmp_mutex, sizeof (_tmp_mutex)); } while (
0)
;
559 unscaled->lock_count = 0;
560
561 unscaled->faces = NULL((void*)0);
562
563 return CAIRO_STATUS_SUCCESS;
564}
565
566/**
567 * _cairo_ft_unscaled_font_fini:
568 *
569 * Free all data associated with a #cairo_ft_unscaled_font_t.
570 *
571 * CAUTION: The unscaled->face field must be %NULL before calling this
572 * function. This is because the #cairo_ft_unscaled_font_t_map keeps a
573 * count of these faces (font_map->num_open_faces) so it maintains the
574 * unscaled->face field while it has its lock held. See
575 * _font_map_release_face_lock_held().
576 **/
577static void
578_cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
579{
580 assert (unscaled->face == NULL)((void) sizeof (__assert_single_arg (unscaled->face == ((void
*)0))), __extension__ ({ if (unscaled->face == ((void*)0))
; else __assert_fail ("unscaled->face == NULL", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c"
, 580, __extension__ __PRETTY_FUNCTION__); }))
;
581
582 free (unscaled->filename);
583 unscaled->filename = NULL((void*)0);
584
585 free (unscaled->variations);
586
587 CAIRO_MUTEX_FINI (unscaled->mutex)pthread_mutex_destroy (&(unscaled->mutex));
588}
589
590static int
591_cairo_ft_unscaled_font_keys_equal (const void *key_a,
592 const void *key_b)
593{
594 const cairo_ft_unscaled_font_t *unscaled_a = key_a;
595 const cairo_ft_unscaled_font_t *unscaled_b = key_b;
596
597 if (unscaled_a->id == unscaled_b->id &&
598 unscaled_a->from_face == unscaled_b->from_face)
599 {
600 if (unscaled_a->from_face)
601 return unscaled_a->face == unscaled_b->face &&
602 unscaled_a->face_context == unscaled_b->face_context;
603
604 if (unscaled_a->filename == NULL((void*)0) && unscaled_b->filename == NULL((void*)0))
605 return TRUE1;
606 else if (unscaled_a->filename == NULL((void*)0) || unscaled_b->filename == NULL((void*)0))
607 return FALSE0;
608 else
609 return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0);
610 }
611
612 return FALSE0;
613}
614
615/* Finds or creates a #cairo_ft_unscaled_font_t for the filename/id from
616 * pattern. Returns a new reference to the unscaled font.
617 */
618static cairo_status_t
619_cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
620 char *filename,
621 int id,
622 FT_Face font_face,
623 void *face_context,
624 cairo_ft_unscaled_font_t **out)
625{
626 cairo_ft_unscaled_font_t key, *unscaled;
627 cairo_ft_unscaled_font_map_t *font_map;
628 cairo_status_t status;
629
630 font_map = _cairo_ft_unscaled_font_map_lock ();
631 if (unlikely (font_map == NULL)(__builtin_expect (!!(font_map == ((void*)0)), 0)))
632 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
633
634 _cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, font_face, face_context);
635
636 /* Return existing unscaled font if it exists in the hash table. */
637 unscaled = _cairo_hash_table_lookup (font_map->hash_table,
638 &key.base.hash_entry);
639 if (unscaled != NULL((void*)0)) {
640 _cairo_unscaled_font_reference (&unscaled->base);
641 goto DONE;
642 }
643
644 /* Otherwise create it and insert into hash table. */
645 unscaled = _cairo_calloc (sizeof (cairo_ft_unscaled_font_t))((sizeof (cairo_ft_unscaled_font_t)) != 0 ? calloc(1,sizeof (
cairo_ft_unscaled_font_t)) : ((void*)0))
;
646 if (unlikely (unscaled == NULL)(__builtin_expect (!!(unscaled == ((void*)0)), 0))) {
647 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
648 goto UNWIND_FONT_MAP_LOCK;
649 }
650
651 status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, font_face, face_context);
652 if (unlikely (status)(__builtin_expect (!!(status), 0)))
653 goto UNWIND_UNSCALED_MALLOC;
654
655 assert (unscaled->base.hash_entry.hash == key.base.hash_entry.hash)((void) sizeof (__assert_single_arg (unscaled->base.hash_entry
.hash == key.base.hash_entry.hash)), __extension__ ({ if (unscaled
->base.hash_entry.hash == key.base.hash_entry.hash) ; else
__assert_fail ("unscaled->base.hash_entry.hash == key.base.hash_entry.hash"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c", 655
, __extension__ __PRETTY_FUNCTION__); }))
;
656 status = _cairo_hash_table_insert (font_map->hash_table,
657 &unscaled->base.hash_entry);
658 if (unlikely (status)(__builtin_expect (!!(status), 0)))
659 goto UNWIND_UNSCALED_FONT_INIT;
660
661 mozilla_AddRefSharedFTFace (face_context);
662
663DONE:
664 _cairo_ft_unscaled_font_map_unlock ();
665 *out = unscaled;
666 return CAIRO_STATUS_SUCCESS;
667
668UNWIND_UNSCALED_FONT_INIT:
669 _cairo_ft_unscaled_font_fini (unscaled);
670UNWIND_UNSCALED_MALLOC:
671 free (unscaled);
672UNWIND_FONT_MAP_LOCK:
673 _cairo_ft_unscaled_font_map_unlock ();
674 return status;
675}
676
677
678#if CAIRO_HAS_FC_FONT1
679static cairo_status_t
680_cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern,
681 cairo_ft_unscaled_font_t **out)
682{
683 FT_Face font_face = NULL((void*)0);
684 char *filename = NULL((void*)0);
685 int id = 0;
686 FcResult ret;
687
688 ret = FcPatternGetFTFace (pattern, FC_FT_FACE"ftface", 0, &font_face);
689 if (ret == FcResultMatch)
690 goto DONE;
691 if (ret == FcResultOutOfMemory)
692 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
693
694 ret = FcPatternGetString (pattern, FC_FILE"file", 0, (FcChar8 **) &filename);
695 if (ret == FcResultOutOfMemory)
696 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
697 if (ret == FcResultMatch) {
698 if (access (filename, R_OK4) == 0) {
699 /* If FC_INDEX is not set, we just use 0 */
700 ret = FcPatternGetInteger (pattern, FC_INDEX"index", 0, &id);
701 if (ret == FcResultOutOfMemory)
702 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
703
704 goto DONE;
705 } else
706 return _cairo_error (CAIRO_STATUS_FILE_NOT_FOUND);
707 }
708
709 /* The pattern contains neither a face nor a filename, resolve it later. */
710 *out = NULL((void*)0);
711 return CAIRO_STATUS_SUCCESS;
712
713DONE:
714 return _cairo_ft_unscaled_font_create_internal (font_face != NULL((void*)0),
715 filename, id, font_face, NULL((void*)0),
716 out);
717}
718#endif
719
720static cairo_status_t
721_cairo_ft_unscaled_font_create_from_face (FT_Face face,
722 void *face_context,
723 cairo_ft_unscaled_font_t **out)
724{
725 return _cairo_ft_unscaled_font_create_internal (TRUE1, NULL((void*)0), face->face_index, face, face_context, out);
726}
727
728static cairo_bool_t
729_cairo_ft_unscaled_font_destroy (void *abstract_font)
730{
731 cairo_ft_unscaled_font_t *unscaled = abstract_font;
732 cairo_ft_unscaled_font_map_t *font_map;
733
734 font_map = _cairo_ft_unscaled_font_map_lock ();
735 /* All created objects must have been mapped in the font map. */
736 assert (font_map != NULL)((void) sizeof (__assert_single_arg (font_map != ((void*)0)))
, __extension__ ({ if (font_map != ((void*)0)) ; else __assert_fail
("font_map != NULL", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c"
, 736, __extension__ __PRETTY_FUNCTION__); }))
;
737
738 if (! _cairo_reference_count_dec_and_test (&unscaled->base.ref_count)(__atomic_fetch_sub(&(&unscaled->base.ref_count)->
ref_count, 1, 5) == 1)
) {
739 /* somebody recreated the font whilst we waited for the lock */
740 _cairo_ft_unscaled_font_map_unlock ();
741 return FALSE0;
742 }
743
744 _cairo_hash_table_remove (font_map->hash_table,
745 &unscaled->base.hash_entry);
746
747 if (unscaled->from_face) {
748 /* See comments in _ft_font_face_destroy about the "zombie" state
749 * for a _ft_font_face.
750 */
751 if (unscaled->faces && unscaled->faces->unscaled == NULL((void*)0)) {
752 assert (unscaled->faces->next == NULL)((void) sizeof (__assert_single_arg (unscaled->faces->next
== ((void*)0))), __extension__ ({ if (unscaled->faces->
next == ((void*)0)) ; else __assert_fail ("unscaled->faces->next == NULL"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c", 752
, __extension__ __PRETTY_FUNCTION__); }))
;
753 CAIRO_FT_LOCK (unscaled)((unscaled)->face_context ? (void)mozilla_LockSharedFTFace
((unscaled)->face_context, ((void*)0)) : (void)pthread_mutex_lock
(&((unscaled)->mutex)))
;
754 cairo_font_face_destroy_moz_cairo_font_face_destroy (&unscaled->faces->base);
755 CAIRO_FT_UNLOCK (unscaled)((unscaled)->face_context ? mozilla_UnlockSharedFTFace((unscaled
)->face_context) : (void)pthread_mutex_unlock (&((unscaled
)->mutex)))
;
756 }
757 mozilla_ReleaseSharedFTFace (unscaled->face_context, unscaled);
758 } else {
759 _font_map_release_face_lock_held (font_map, unscaled);
760 }
761 unscaled->face = NULL((void*)0);
762 unscaled->face_context = NULL((void*)0);
763
764 _cairo_ft_unscaled_font_map_unlock ();
765
766 _cairo_ft_unscaled_font_fini (unscaled);
767 return TRUE1;
768}
769
770static cairo_bool_t
771_has_unlocked_face (const void *entry)
772{
773 const cairo_ft_unscaled_font_t *unscaled = entry;
774
775 return (!unscaled->from_face && unscaled->lock_count == 0 && unscaled->face);
776}
777
778/* Ensures that an unscaled font has a face object. If we exceed
779 * MAX_OPEN_FACES, try to close some.
780 *
781 * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
782 * set the scale on the face, but just returns it at the last scale.
783 */
784static cairo_warn FT_Face
785_cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
786{
787 cairo_ft_unscaled_font_map_t *font_map;
788 FT_Face face = NULL((void*)0);
789 FT_Error error;
790
791 if (unscaled->face_context) {
792 if (!mozilla_LockSharedFTFace (unscaled->face_context, unscaled)) {
793 unscaled->have_scale = FALSE0;
794 }
795 } else {
796 CAIRO_FT_LOCK (unscaled)((unscaled)->face_context ? (void)mozilla_LockSharedFTFace
((unscaled)->face_context, ((void*)0)) : (void)pthread_mutex_lock
(&((unscaled)->mutex)))
;
797 }
798 unscaled->lock_count++;
799
800 if (unscaled->face)
801 return unscaled->face;
802
803 /* If this unscaled font was created from an FT_Face then we just
804 * returned it above. */
805 assert (!unscaled->from_face)((void) sizeof (__assert_single_arg (!unscaled->from_face)
), __extension__ ({ if (!unscaled->from_face) ; else __assert_fail
("!unscaled->from_face", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c"
, 805, __extension__ __PRETTY_FUNCTION__); }))
;
806
807 font_map = _cairo_ft_unscaled_font_map_lock ();
808 {
809 assert (font_map != NULL)((void) sizeof (__assert_single_arg (font_map != ((void*)0)))
, __extension__ ({ if (font_map != ((void*)0)) ; else __assert_fail
("font_map != NULL", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c"
, 809, __extension__ __PRETTY_FUNCTION__); }))
;
810
811 while (font_map->num_open_faces >= MAX_OPEN_FACES10)
812 {
813 cairo_ft_unscaled_font_t *entry;
814
815 entry = _cairo_hash_table_random_entry (font_map->hash_table,
816 _has_unlocked_face);
817 if (entry == NULL((void*)0))
818 break;
819
820 _font_map_release_face_lock_held (font_map, entry);
821 }
822 }
823 _cairo_ft_unscaled_font_map_unlock ();
824
825 error = FT_New_Face (font_map->ft_library,
826 unscaled->filename,
827 unscaled->id,
828 &face);
829 if (error)
830 {
831 unscaled->lock_count--;
832 CAIRO_FT_UNLOCK (unscaled)((unscaled)->face_context ? mozilla_UnlockSharedFTFace((unscaled
)->face_context) : (void)pthread_mutex_unlock (&((unscaled
)->mutex)))
;
833 _cairo_error_throw (_cairo_ft_to_cairo_error (error))do { cairo_status_t status__ = _cairo_error (_cairo_ft_to_cairo_error
(error)); (void) status__; } while (0)
;
834 return NULL((void*)0);
835 }
836
837 unscaled->face = face;
838
839 unscaled->have_color = FT_HAS_COLOR (face)( !!( (face)->face_flags & ( 1L << 14 ) ) ) != 0;
840 unscaled->have_color_set = TRUE1;
841
842 font_map->num_open_faces++;
843
844 return face;
845}
846
847
848/* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face
849 */
850static void
851_cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
852{
853 assert (unscaled->lock_count > 0)((void) sizeof (__assert_single_arg (unscaled->lock_count >
0)), __extension__ ({ if (unscaled->lock_count > 0) ; else
__assert_fail ("unscaled->lock_count > 0", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c"
, 853, __extension__ __PRETTY_FUNCTION__); }))
;
854
855 unscaled->lock_count--;
856
857 CAIRO_FT_UNLOCK (unscaled)((unscaled)->face_context ? mozilla_UnlockSharedFTFace((unscaled
)->face_context) : (void)pthread_mutex_unlock (&((unscaled
)->mutex)))
;
858}
859
860
861static cairo_status_t
862_compute_transform (cairo_ft_font_transform_t *sf,
863 cairo_matrix_t *scale,
864 cairo_ft_unscaled_font_t *unscaled)
865{
866 cairo_status_t status;
867 double x_scale, y_scale;
868 cairo_matrix_t normalized = *scale;
869
870 /* The font matrix has x and y "scale" components which we extract and
871 * use as character scale values. These influence the way freetype
872 * chooses hints, as well as selecting different bitmaps in
873 * hand-rendered fonts. We also copy the normalized matrix to
874 * freetype's transformation.
875 */
876
877 status = _cairo_matrix_compute_basis_scale_factors (scale,
878 &x_scale, &y_scale,
879 1);
880 if (unlikely (status)(__builtin_expect (!!(status), 0)))
881 return status;
882
883 /* FreeType docs say this about x_scale and y_scale:
884 * "A character width or height smaller than 1pt is set to 1pt;"
885 * So, we cap them from below at 1.0 and let the FT transform
886 * take care of sub-1.0 scaling. */
887 if (x_scale < 1.0)
888 x_scale = 1.0;
889 if (y_scale < 1.0)
890 y_scale = 1.0;
891
892 if (unscaled && (unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE( 1L << 0 )) == 0) {
893 double min_distance = DBL_MAX1.7976931348623157e+308;
894 cairo_bool_t magnify = TRUE1;
895 int i;
896 double best_x_size = 0;
897 double best_y_size = 0;
898
899 for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
900 double x_size = unscaled->face->available_sizes[i].x_ppem / 64.;
901 double y_size = unscaled->face->available_sizes[i].y_ppem / 64.;
902 double distance = y_size - y_scale;
903
904 /*
905 * distance is positive if current strike is larger than desired
906 * size, and negative if smaller.
907 *
908 * We like to prefer down-scaling to upscaling.
909 */
910
911 if ((magnify && distance >= 0) || fabs (distance) <= min_distance) {
912 magnify = distance < 0;
913 min_distance = fabs (distance);
914 best_x_size = x_size;
915 best_y_size = y_size;
916 }
917 }
918
919 x_scale = best_x_size;
920 y_scale = best_y_size;
921 }
922
923 sf->x_scale = x_scale;
924 sf->y_scale = y_scale;
925
926 cairo_matrix_scale_moz_cairo_matrix_scale (&normalized, 1.0 / x_scale, 1.0 / y_scale);
927
928 _cairo_matrix_get_affine (&normalized,
929 &sf->shape[0][0], &sf->shape[0][1],
930 &sf->shape[1][0], &sf->shape[1][1],
931 NULL((void*)0), NULL((void*)0));
932
933 return CAIRO_STATUS_SUCCESS;
934}
935
936/* Temporarily scales an unscaled font to the give scale. We catch
937 * scaling to the same size, since changing a FT_Face is expensive.
938 */
939static cairo_status_t
940_cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
941 cairo_matrix_t *scale)
942{
943 cairo_status_t status;
944 cairo_ft_font_transform_t sf;
945 FT_Matrix mat;
946 FT_Error error;
947
948 assert (unscaled->face != NULL)((void) sizeof (__assert_single_arg (unscaled->face != ((void
*)0))), __extension__ ({ if (unscaled->face != ((void*)0))
; else __assert_fail ("unscaled->face != NULL", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c"
, 948, __extension__ __PRETTY_FUNCTION__); }))
;
949
950 if (unscaled->have_scale &&
951 scale->xx == unscaled->current_scale.xx &&
952 scale->yx == unscaled->current_scale.yx &&
953 scale->xy == unscaled->current_scale.xy &&
954 scale->yy == unscaled->current_scale.yy)
955 return CAIRO_STATUS_SUCCESS;
956
957 unscaled->have_scale = TRUE1;
958 unscaled->current_scale = *scale;
959
960 status = _compute_transform (&sf, scale, unscaled);
961 if (unlikely (status)(__builtin_expect (!!(status), 0)))
962 return status;
963
964 unscaled->x_scale = sf.x_scale;
965 unscaled->y_scale = sf.y_scale;
966
967 mat.xx = DOUBLE_TO_16_16(sf.shape[0][0])((FT_Fixed)((sf.shape[0][0]) * 65536.0));
968 mat.yx = - DOUBLE_TO_16_16(sf.shape[0][1])((FT_Fixed)((sf.shape[0][1]) * 65536.0));
969 mat.xy = - DOUBLE_TO_16_16(sf.shape[1][0])((FT_Fixed)((sf.shape[1][0]) * 65536.0));
970 mat.yy = DOUBLE_TO_16_16(sf.shape[1][1])((FT_Fixed)((sf.shape[1][1]) * 65536.0));
971
972 unscaled->have_shape = (mat.xx != 0x10000 ||
973 mat.yx != 0x00000 ||
974 mat.xy != 0x00000 ||
975 mat.yy != 0x10000);
976
977 unscaled->Current_Shape = mat;
978 cairo_matrix_init_moz_cairo_matrix_init (&unscaled->current_shape,
979 sf.shape[0][0], sf.shape[0][1],
980 sf.shape[1][0], sf.shape[1][1],
981 0.0, 0.0);
982
983 FT_Set_Transform(unscaled->face, &mat, NULL((void*)0));
984
985 error = FT_Set_Char_Size (unscaled->face,
986 sf.x_scale * 64.0 + .5,
987 sf.y_scale * 64.0 + .5,
988 0, 0);
989 if (error)
990 return _cairo_error (_cairo_ft_to_cairo_error (error));
991
992 return CAIRO_STATUS_SUCCESS;
993}
994
995/* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
996 * into a different format. For example, we want to convert a
997 * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
998 * ARGB or ABGR bitmap.
999 *
1000 * this function prepares a target descriptor for this operation.
1001 *
1002 * input :: target bitmap descriptor. The function will set its
1003 * 'width', 'rows' and 'pitch' fields, and only these
1004 *
1005 * slot :: the glyph slot containing the source bitmap. this
1006 * function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
1007 *
1008 * mode :: the requested final rendering mode. supported values are
1009 * MONO, NORMAL (i.e. gray), LCD and LCD_V
1010 *
1011 * the function returns the size in bytes of the corresponding buffer,
1012 * it's up to the caller to allocate the corresponding memory block
1013 * before calling _fill_xrender_bitmap
1014 *
1015 * it also returns -1 in case of error (e.g. incompatible arguments,
1016 * like trying to convert a gray bitmap into a monochrome one)
1017 */
1018static int
1019_compute_xrender_bitmap_size(FT_Bitmap *target,
1020 FT_GlyphSlot slot,
1021 FT_Render_Mode mode)
1022{
1023 FT_Bitmap *ftbit;
1024 int width, height, pitch;
1025
1026 if (slot->format != FT_GLYPH_FORMAT_BITMAP)
1027 return -1;
1028
1029 /* compute the size of the final bitmap */
1030 ftbit = &slot->bitmap;
1031
1032 width = ftbit->width;
1033 height = ftbit->rows;
1034
1035 /* Reject absurd glyph dimensions to avoid overflow below. */
1036 if (width < 0 || width > INT_MAX2147483647 / 4 || height < 0)
1037 return -1;
1038
1039 pitch = (width + 3) & ~3;
1040
1041 switch (ftbit->pixel_mode) {
1042 case FT_PIXEL_MODE_MONO:
1043 if (mode == FT_RENDER_MODE_MONO) {
1044 pitch = (((width + 31) & ~31) >> 3);
1045 break;
1046 }
1047 /* fall-through */
1048
1049 case FT_PIXEL_MODE_GRAY:
1050 if (mode == FT_RENDER_MODE_LCD ||
1051 mode == FT_RENDER_MODE_LCD_V)
1052 {
1053 /* each pixel is replicated into a 32-bit ARGB value */
1054 pitch = width * 4;
1055 }
1056 break;
1057
1058 case FT_PIXEL_MODE_LCD:
1059 if (mode != FT_RENDER_MODE_LCD)
1060 return -1;
1061
1062 /* horz pixel triplets are packed into 32-bit ARGB values */
1063 width /= 3;
1064 pitch = width * 4;
1065 break;
1066
1067 case FT_PIXEL_MODE_LCD_V:
1068 if (mode != FT_RENDER_MODE_LCD_V)
1069 return -1;
1070
1071 /* vert pixel triplets are packed into 32-bit ARGB values */
1072 height /= 3;
1073 pitch = width * 4;
1074 break;
1075
1076 case FT_PIXEL_MODE_BGRA:
1077 /* each pixel is replicated into a 32-bit ARGB value */
1078 pitch = width * 4;
1079 break;
1080
1081 default: /* unsupported source format */
1082 return -1;
1083 }
1084
1085 target->width = width;
1086 target->rows = height;
1087 target->pitch = pitch;
1088 target->buffer = NULL((void*)0);
1089
1090 /* Reject this size if the multiplication overflows. */
1091 if ((cairo_int64_t) pitch * height > INT_MAX2147483647)
1092 return -1;
1093
1094 return pitch * height;
1095}
1096
1097/* this functions converts the glyph bitmap found in a FT_GlyphSlot
1098 * into a different format (see _compute_xrender_bitmap_size)
1099 *
1100 * you should call this function after _compute_xrender_bitmap_size
1101 *
1102 * target :: target bitmap descriptor. Note that its 'buffer' pointer
1103 * must point to memory allocated by the caller
1104 *
1105 * slot :: the glyph slot containing the source bitmap
1106 *
1107 * mode :: the requested final rendering mode
1108 *
1109 * bgr :: boolean, set if BGR or VBGR pixel ordering is needed
1110 */
1111static void
1112_fill_xrender_bitmap(FT_Bitmap *target,
1113 FT_GlyphSlot slot,
1114 FT_Render_Mode mode,
1115 int bgr)
1116{
1117 FT_Bitmap *ftbit = &slot->bitmap;
1118 unsigned char *srcLine = ftbit->buffer;
1119 unsigned char *dstLine = target->buffer;
1120 int src_pitch = ftbit->pitch;
1121 int width = target->width;
1122 int height = target->rows;
1123 int pitch = target->pitch;
1124 int subpixel;
1125 int h;
1126
1127 subpixel = (mode == FT_RENDER_MODE_LCD ||
1128 mode == FT_RENDER_MODE_LCD_V);
1129
1130 if (src_pitch < 0)
1131 srcLine -= src_pitch * (ftbit->rows - 1);
1132
1133 target->pixel_mode = ftbit->pixel_mode;
1134
1135 switch (ftbit->pixel_mode) {
1136 case FT_PIXEL_MODE_MONO:
1137 if (subpixel) {
1138 /* convert mono to ARGB32 values */
1139
1140 for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1141 int x;
1142
1143 for (x = 0; x < width; x++) {
1144 if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
1145 ((unsigned int *) dstLine)[x] = 0xffffffffU;
1146 }
1147 }
1148 target->pixel_mode = FT_PIXEL_MODE_LCD;
1149
1150 } else if (mode == FT_RENDER_MODE_NORMAL) {
1151 /* convert mono to 8-bit gray */
1152
1153 for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1154 int x;
1155
1156 for (x = 0; x < width; x++) {
1157 if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
1158 dstLine[x] = 0xff;
1159 }
1160 }
1161 target->pixel_mode = FT_PIXEL_MODE_GRAY;
1162
1163 } else {
1164 /* copy mono to mono */
1165
1166 int bytes = (width + 7) >> 3;
1167
1168 for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
1169 memcpy (dstLine, srcLine, bytes);
1170 }
1171 break;
1172
1173 case FT_PIXEL_MODE_GRAY:
1174 if (subpixel) {
1175 /* convert gray to ARGB32 values */
1176
1177 for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1178 int x;
1179 unsigned int *dst = (unsigned int *) dstLine;
1180
1181 for (x = 0; x < width; x++) {
1182 unsigned int pix = srcLine[x];
1183
1184 pix |= (pix << 8);
1185 pix |= (pix << 16);
1186
1187 dst[x] = pix;
1188 }
1189 }
1190 target->pixel_mode = FT_PIXEL_MODE_LCD;
1191 } else {
1192 /* copy gray into gray */
1193
1194 for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
1195 memcpy (dstLine, srcLine, width);
1196 }
1197 break;
1198
1199 case FT_PIXEL_MODE_LCD:
1200 if (!bgr) {
1201 /* convert horizontal RGB into ARGB32 */
1202
1203 for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1204 int x;
1205 unsigned char *src = srcLine;
1206 unsigned int *dst = (unsigned int *) dstLine;
1207
1208 for (x = 0; x < width; x++, src += 3) {
1209 unsigned int pix;
1210
1211 pix = ((unsigned int)src[0] << 16) |
1212 ((unsigned int)src[1] << 8) |
1213 ((unsigned int)src[2] ) |
1214 ((unsigned int)src[1] << 24) ;
1215
1216 dst[x] = pix;
1217 }
1218 }
1219 } else {
1220 /* convert horizontal BGR into ARGB32 */
1221
1222 for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1223
1224 int x;
1225 unsigned char *src = srcLine;
1226 unsigned int *dst = (unsigned int *) dstLine;
1227
1228 for (x = 0; x < width; x++, src += 3) {
1229 unsigned int pix;
1230
1231 pix = ((unsigned int)src[2] << 16) |
1232 ((unsigned int)src[1] << 8) |
1233 ((unsigned int)src[0] ) |
1234 ((unsigned int)src[1] << 24) ;
1235
1236 dst[x] = pix;
1237 }
1238 }
1239 }
1240 break;
1241
1242 case FT_PIXEL_MODE_LCD_V:
1243 /* convert vertical RGB into ARGB32 */
1244 if (!bgr) {
1245
1246 for (h = height; h > 0; h--, srcLine += 3 * src_pitch, dstLine += pitch) {
1247 int x;
1248 unsigned char* src = srcLine;
1249 unsigned int* dst = (unsigned int *) dstLine;
1250
1251 for (x = 0; x < width; x++, src += 1) {
1252 unsigned int pix;
1253 pix = ((unsigned int)src[0] << 16) |
1254 ((unsigned int)src[src_pitch] << 8) |
1255 ((unsigned int)src[src_pitch*2] ) |
1256 ((unsigned int)src[src_pitch] << 24) ;
1257 dst[x] = pix;
1258 }
1259 }
1260 } else {
1261
1262 for (h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch) {
1263 int x;
1264 unsigned char *src = srcLine;
1265 unsigned int *dst = (unsigned int *) dstLine;
1266
1267 for (x = 0; x < width; x++, src += 1) {
1268 unsigned int pix;
1269
1270 pix = ((unsigned int)src[src_pitch * 2] << 16) |
1271 ((unsigned int)src[src_pitch] << 8) |
1272 ((unsigned int)src[0] ) |
1273 ((unsigned int)src[src_pitch] << 24) ;
1274
1275 dst[x] = pix;
1276 }
1277 }
1278 }
1279 break;
1280
1281 case FT_PIXEL_MODE_BGRA:
1282 for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
1283 memcpy (dstLine, srcLine, (size_t)width * 4);
1284 break;
1285
1286 default:
1287 assert (0)((void) sizeof (__assert_single_arg (0)), __extension__ ({ if
(0) ; else __assert_fail ("0", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c"
, 1287, __extension__ __PRETTY_FUNCTION__); }))
;
1288 }
1289}
1290
1291
1292/* Fills in val->image with an image surface created from @bitmap
1293 */
1294static cairo_status_t
1295_get_bitmap_surface (FT_Bitmap *bitmap,
1296 FT_Library library,
1297 cairo_bool_t own_buffer,
1298 cairo_font_options_t *font_options,
1299 cairo_image_surface_t **surface)
1300{
1301 unsigned int width, height;
1302 unsigned char *data;
1303 int format = CAIRO_FORMAT_A8;
1304 int stride;
1305 cairo_image_surface_t *image;
1306 cairo_bool_t component_alpha = FALSE0;
1307
1308 width = bitmap->width;
1309 height = bitmap->rows;
1310
1311 if (width == 0 || height == 0) {
26
Assuming 'width' is not equal to 0
27
Assuming 'height' is not equal to 0
28
Taking false branch
1312 *surface = (cairo_image_surface_t *)
1313 cairo_image_surface_create_for_data_moz_cairo_image_surface_create_for_data (NULL((void*)0), format, 0, 0, 0);
1314 return (*surface)->base.status;
1315 }
1316
1317 switch (bitmap->pixel_mode) {
29
Control jumps to the 'default' case at line 1471
1318 case FT_PIXEL_MODE_MONO:
1319 stride = (((width + 31) & ~31) >> 3);
1320 if (own_buffer) {
1321 data = bitmap->buffer;
1322 assert (stride == bitmap->pitch)((void) sizeof (__assert_single_arg (stride == bitmap->pitch
)), __extension__ ({ if (stride == bitmap->pitch) ; else __assert_fail
("stride == bitmap->pitch", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c"
, 1322, __extension__ __PRETTY_FUNCTION__); }))
;
1323 } else {
1324 data = _cairo_malloc_ab (height, stride);
1325 if (!data)
1326 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1327
1328 if (stride == bitmap->pitch) {
1329 memcpy (data, bitmap->buffer, (size_t)stride * height);
1330 } else {
1331 int i;
1332 unsigned char *source, *dest;
1333 /* bitmap->pitch might exceed our computed row stride.
1334 * Copy only the (width+7)/8 payload bytes of each row,
1335 * which always fit in both buffers. */
1336 int row_bytes = (width + 7) >> 3;
1337
1338 if (bitmap->pitch < row_bytes) {
1339 free (data);
1340 return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
1341 }
1342
1343 source = bitmap->buffer;
1344 dest = data;
1345 for (i = height; i; i--) {
1346 memcpy (dest, source, row_bytes);
1347 memset (dest + row_bytes, '\0', stride - row_bytes);
1348
1349 source += bitmap->pitch;
1350 dest += stride;
1351 }
1352 }
1353 }
1354
1355#ifndef WORDS_BIGENDIAN
1356 {
1357 uint8_t *d = data;
1358 int count = stride * height;
1359
1360 while (count--) {
1361 *d = CAIRO_BITSWAP8 (*d)((((*d) * 0x0802LU & 0x22110LU) | ((*d) * 0x8020LU & 0x88440LU
)) * 0x10101LU >> 16)
;
1362 d++;
1363 }
1364 }
1365#endif
1366 format = CAIRO_FORMAT_A1;
1367 break;
1368
1369 case FT_PIXEL_MODE_LCD:
1370 case FT_PIXEL_MODE_LCD_V:
1371 case FT_PIXEL_MODE_GRAY:
1372 if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL ||
1373 bitmap->pixel_mode == FT_PIXEL_MODE_GRAY)
1374 {
1375 stride = bitmap->pitch;
1376
1377 /* We don't support stride not multiple of 4. */
1378 if (stride & 3)
1379 {
1380 assert (!own_buffer)((void) sizeof (__assert_single_arg (!own_buffer)), __extension__
({ if (!own_buffer) ; else __assert_fail ("!own_buffer", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c"
, 1380, __extension__ __PRETTY_FUNCTION__); }))
;
1381 goto convert;
1382 }
1383
1384 if (own_buffer) {
1385 data = bitmap->buffer;
1386 } else {
1387 data = _cairo_malloc_ab (height, stride);
1388 if (!data)
1389 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1390
1391 memcpy (data, bitmap->buffer, (size_t)stride * height);
1392 }
1393
1394 format = CAIRO_FORMAT_A8;
1395 } else {
1396 data = bitmap->buffer;
1397 stride = bitmap->pitch;
1398 format = CAIRO_FORMAT_ARGB32;
1399 component_alpha = TRUE1;
1400 }
1401 break;
1402 case FT_PIXEL_MODE_BGRA:
1403 stride = width * 4;
1404 if (own_buffer) {
1405 data = bitmap->buffer;
1406 } else {
1407 data = _cairo_malloc_ab (height, stride);
1408 if (!data)
1409 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1410
1411 memcpy (data, bitmap->buffer, (size_t)stride * height);
1412 }
1413
1414 if (!_cairo_is_little_endian ())
1415 {
1416 /* Byteswap. */
1417 unsigned int i, count = height * width;
1418 uint32_t *p = (uint32_t *) data;
1419 for (i = 0; i < count; i++)
1420 p[i] = bswap_32 (p[i])__bswap_32 (p[i]);
1421 }
1422 format = CAIRO_FORMAT_ARGB32;
1423 break;
1424 case FT_PIXEL_MODE_GRAY2:
1425 case FT_PIXEL_MODE_GRAY4:
1426 convert:
1427 if (!own_buffer && library)
1428 {
1429 /* This is pretty much the only case that we can get in here. */
1430 /* Convert to 8bit grayscale. */
1431
1432 FT_Bitmap tmp;
1433 FT_Int align;
1434 FT_Error error;
1435
1436 format = CAIRO_FORMAT_A8;
1437
1438 align = cairo_format_stride_for_width_moz_cairo_format_stride_for_width (format, bitmap->width);
1439
1440 FT_Bitmap_New( &tmp );
1441
1442 error = FT_Bitmap_Convert( library, bitmap, &tmp, align );
1443 if (error)
1444 return _cairo_error (_cairo_ft_to_cairo_error (error));
1445
1446 FT_Bitmap_Done( library, bitmap );
1447 *bitmap = tmp;
1448
1449 stride = bitmap->pitch;
1450 data = _cairo_malloc_ab (height, stride);
1451 if (!data)
1452 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1453
1454 if (bitmap->num_grays != 256)
1455 {
1456 unsigned int x, y;
1457 unsigned int mul = 255 / (bitmap->num_grays - 1);
1458 FT_Byte *p = bitmap->buffer;
1459 for (y = 0; y < height; y++) {
1460 for (x = 0; x < width; x++)
1461 p[x] *= mul;
1462 p += bitmap->pitch;
1463 }
1464 }
1465
1466 memcpy (data, bitmap->buffer, (size_t)stride * height);
1467 break;
1468 }
1469 /* fall through */
1470 /* These could be triggered by very rare types of TrueType fonts */
1471 default:
1472 if (own_buffer
29.1
'own_buffer' is 0
)
30
Taking false branch
1473 free (bitmap->buffer);
1474 return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
1475 }
1476
1477 /* XXX */
1478 *surface = image = (cairo_image_surface_t *)
1479 cairo_image_surface_create_for_data_moz_cairo_image_surface_create_for_data (data,
1480 format,
1481 width, height, stride);
1482 if (image->base.status) {
1483 free (data);
1484 return (*surface)->base.status;
1485 }
1486
1487 if (component_alpha)
1488 pixman_image_set_component_alpha_moz_pixman_image_set_component_alpha (image->pixman_image, TRUE1);
1489
1490 _cairo_image_surface_assume_ownership_of_data (image);
1491
1492 _cairo_debug_check_image_surface_is_defined (&image->base);
1493
1494 return CAIRO_STATUS_SUCCESS;
1495}
1496
1497/* Converts an outline FT_GlyphSlot into an image
1498 *
1499 * This could go through _render_glyph_bitmap as well, letting
1500 * FreeType convert the outline to a bitmap, but doing it ourselves
1501 * has two minor advantages: first, we save a copy of the bitmap
1502 * buffer: we can directly use the buffer that FreeType renders
1503 * into.
1504 *
1505 * Second, it may help when we add support for subpixel
1506 * rendering: the Xft code does it this way. (Keith thinks that
1507 * it may also be possible to get the subpixel rendering with
1508 * FT_Render_Glyph: something worth looking into in more detail
1509 * when we add subpixel support. If so, we may want to eliminate
1510 * this version of the code path entirely.
1511 */
1512static cairo_status_t
1513_render_glyph_outline (FT_Face face,
1514 cairo_font_options_t *font_options,
1515 cairo_image_surface_t **surface)
1516{
1517 cairo_subpixel_order_t rgba = CAIRO_SUBPIXEL_ORDER_DEFAULT;
1518 int lcd_filter = FT_LCD_FILTER_DEFAULT;
1519 FT_GlyphSlot glyphslot = face->glyph;
1520 FT_Outline *outline = &glyphslot->outline;
1521 FT_Bitmap bitmap;
1522 FT_BBox cbox;
1523 unsigned int width, height;
1524 cairo_status_t status;
1525 FT_Error error;
1526 FT_Library library = glyphslot->library;
1527 FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
1528
1529 switch (font_options->antialias) {
1530 case CAIRO_ANTIALIAS_NONE:
1531 render_mode = FT_RENDER_MODE_MONO;
1532 break;
1533
1534 case CAIRO_ANTIALIAS_SUBPIXEL:
1535 case CAIRO_ANTIALIAS_BEST:
1536 switch (font_options->subpixel_order) {
1537 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1538 case CAIRO_SUBPIXEL_ORDER_RGB:
1539 case CAIRO_SUBPIXEL_ORDER_BGR:
1540 render_mode = FT_RENDER_MODE_LCD;
1541 break;
1542
1543 case CAIRO_SUBPIXEL_ORDER_VRGB:
1544 case CAIRO_SUBPIXEL_ORDER_VBGR:
1545 render_mode = FT_RENDER_MODE_LCD_V;
1546 break;
1547 }
1548
1549 switch (font_options->lcd_filter) {
1550 case CAIRO_LCD_FILTER_NONE:
1551 lcd_filter = FT_LCD_FILTER_NONE;
1552 break;
1553 case CAIRO_LCD_FILTER_INTRA_PIXEL:
1554 lcd_filter = FT_LCD_FILTER_LEGACY;
1555 break;
1556 case CAIRO_LCD_FILTER_FIR3:
1557 lcd_filter = FT_LCD_FILTER_LIGHT;
1558 break;
1559 case CAIRO_LCD_FILTER_DEFAULT:
1560 case CAIRO_LCD_FILTER_FIR5:
1561 lcd_filter = FT_LCD_FILTER_DEFAULT;
1562 break;
1563 }
1564
1565 break;
1566
1567 case CAIRO_ANTIALIAS_DEFAULT:
1568 case CAIRO_ANTIALIAS_GRAY:
1569 case CAIRO_ANTIALIAS_GOOD:
1570 case CAIRO_ANTIALIAS_FAST:
1571 render_mode = FT_RENDER_MODE_NORMAL;
1572 }
1573
1574 FT_Outline_Get_CBox (outline, &cbox);
1575
1576 cbox.xMin &= -64;
1577 cbox.yMin &= -64;
1578 cbox.xMax = (cbox.xMax + 63) & -64;
1579 cbox.yMax = (cbox.yMax + 63) & -64;
1580
1581 width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
1582 height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
1583
1584 if (width * height == 0) {
1585 cairo_format_t format;
1586 /* Looks like fb handles zero-sized images just fine */
1587 switch (render_mode) {
1588 case FT_RENDER_MODE_MONO:
1589 format = CAIRO_FORMAT_A1;
1590 break;
1591 case FT_RENDER_MODE_LCD:
1592 case FT_RENDER_MODE_LCD_V:
1593 format= CAIRO_FORMAT_ARGB32;
1594 break;
1595 case FT_RENDER_MODE_LIGHT:
1596 case FT_RENDER_MODE_NORMAL:
1597 case FT_RENDER_MODE_MAX:
1598#if HAVE_FT_RENDER_MODE_SDF1
1599 case FT_RENDER_MODE_SDF:
1600#endif
1601 default:
1602 format = CAIRO_FORMAT_A8;
1603 break;
1604 }
1605
1606 (*surface) = (cairo_image_surface_t *)
1607 cairo_image_surface_create_for_data_moz_cairo_image_surface_create_for_data (NULL((void*)0), format, 0, 0, 0);
1608 pixman_image_set_component_alpha_moz_pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE1);
1609 if ((*surface)->base.status)
1610 return (*surface)->base.status;
1611 } else {
1612
1613 int bitmap_size;
1614
1615 switch (render_mode) {
1616 case FT_RENDER_MODE_LCD:
1617 if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR)
1618 rgba = CAIRO_SUBPIXEL_ORDER_BGR;
1619 else
1620 rgba = CAIRO_SUBPIXEL_ORDER_RGB;
1621 break;
1622
1623 case FT_RENDER_MODE_LCD_V:
1624 if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR)
1625 rgba = CAIRO_SUBPIXEL_ORDER_VBGR;
1626 else
1627 rgba = CAIRO_SUBPIXEL_ORDER_VRGB;
1628 break;
1629
1630 case FT_RENDER_MODE_MONO:
1631 case FT_RENDER_MODE_LIGHT:
1632 case FT_RENDER_MODE_NORMAL:
1633 case FT_RENDER_MODE_MAX:
1634#if HAVE_FT_RENDER_MODE_SDF1
1635 case FT_RENDER_MODE_SDF:
1636#endif
1637 default:
1638 break;
1639 }
1640
1641 FT_Library_SetLcdFilter (library, lcd_filter);
1642 error = FT_Render_Glyph (face->glyph, render_mode);
1643
1644 FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE);
1645 if (error)
1646 return _cairo_error (_cairo_ft_to_cairo_error (error));
1647
1648 bitmap_size = _compute_xrender_bitmap_size (&bitmap,
1649 face->glyph,
1650 render_mode);
1651 if (bitmap_size < 0)
1652 return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
1653
1654 bitmap.buffer = _cairo_calloc (bitmap_size)((bitmap_size) != 0 ? calloc(1,bitmap_size) : ((void*)0));
1655 if (bitmap.buffer == NULL((void*)0))
1656 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1657
1658 _fill_xrender_bitmap (&bitmap, face->glyph, render_mode,
1659 (rgba == CAIRO_SUBPIXEL_ORDER_BGR || rgba == CAIRO_SUBPIXEL_ORDER_VBGR));
1660
1661 /* Note:
1662 * _get_bitmap_surface will free bitmap.buffer if there is an error
1663 */
1664 status = _get_bitmap_surface (&bitmap, NULL((void*)0), TRUE1, font_options, surface);
1665 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1666 return status;
1667
1668 /* Note: the font's coordinate system is upside down from ours, so the
1669 * Y coordinate of the control box needs to be negated. Moreover, device
1670 * offsets are position of glyph origin relative to top left while xMin
1671 * and yMax are offsets of top left relative to origin. Another negation.
1672 */
1673 cairo_surface_set_device_offset_moz_cairo_surface_set_device_offset (&(*surface)->base,
1674 (double)-glyphslot->bitmap_left,
1675 (double)+glyphslot->bitmap_top);
1676 }
1677
1678 return CAIRO_STATUS_SUCCESS;
1679}
1680
1681/* Converts a bitmap (or other) FT_GlyphSlot into an image */
1682static cairo_status_t
1683_render_glyph_bitmap (FT_Face face,
1684 cairo_font_options_t *font_options,
1685 cairo_image_surface_t **surface)
1686{
1687 FT_GlyphSlot glyphslot = face->glyph;
1688 cairo_status_t status;
1689 FT_Error error;
1690
1691 /* According to the FreeType docs, glyphslot->format could be
1692 * something other than FT_GLYPH_FORMAT_OUTLINE or
1693 * FT_GLYPH_FORMAT_BITMAP. Calling FT_Render_Glyph gives FreeType
1694 * the opportunity to convert such to
1695 * bitmap. FT_GLYPH_FORMAT_COMPOSITE will not be encountered since
1696 * we avoid the FT_LOAD_NO_RECURSE flag.
1697 */
1698 error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
1699 /* XXX ignoring all other errors for now. They are not fatal, typically
1700 * just a glyph-not-found. */
1701 if (error == FT_Err_Out_Of_Memory)
23
Assuming 'error' is not equal to FT_Err_Out_Of_Memory
24
Taking false branch
1702 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1703
1704 status = _get_bitmap_surface (&glyphslot->bitmap,
25
Calling '_get_bitmap_surface'
31
Returning from '_get_bitmap_surface'
1705 glyphslot->library,
1706 FALSE0, font_options,
1707 surface);
1708 if (unlikely (status)(__builtin_expect (!!(status), 0)))
32
Assuming 'status' is 0
33
Taking false branch
1709 return status;
1710
1711 /*
1712 * Note: the font's coordinate system is upside down from ours, so the
1713 * Y coordinate of the control box needs to be negated. Moreover, device
1714 * offsets are position of glyph origin relative to top left while
1715 * bitmap_left and bitmap_top are offsets of top left relative to origin.
1716 * Another negation.
1717 */
1718 cairo_surface_set_device_offset_moz_cairo_surface_set_device_offset (&(*surface)->base,
34
1st function call argument is an uninitialized value
1719 -glyphslot->bitmap_left,
1720 +glyphslot->bitmap_top);
1721
1722 return CAIRO_STATUS_SUCCESS;
1723}
1724
1725static cairo_status_t
1726_transform_glyph_bitmap (cairo_matrix_t * shape,
1727 cairo_image_surface_t ** surface)
1728{
1729 cairo_matrix_t original_to_transformed;
1730 cairo_matrix_t transformed_to_original;
1731 cairo_image_surface_t *old_image;
1732 cairo_surface_t *image;
1733 double x[4], y[4];
1734 double origin_x, origin_y;
1735 int orig_width, orig_height;
1736 int i;
1737 int x_min, y_min, x_max, y_max;
1738 int width, height;
1739 cairo_status_t status;
1740 cairo_surface_pattern_t pattern;
1741
1742 /* We want to compute a transform that takes the origin
1743 * (device_x_offset, device_y_offset) to 0,0, then applies
1744 * the "shape" portion of the font transform
1745 */
1746 original_to_transformed = *shape;
1747
1748 cairo_surface_get_device_offset_moz_cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y);
1749 orig_width = (*surface)->width;
1750 orig_height = (*surface)->height;
1751
1752 cairo_matrix_translate_moz_cairo_matrix_translate (&original_to_transformed,
1753 -origin_x, -origin_y);
1754
1755 /* Find the bounding box of the original bitmap under that
1756 * transform
1757 */
1758 x[0] = 0; y[0] = 0;
1759 x[1] = orig_width; y[1] = 0;
1760 x[2] = orig_width; y[2] = orig_height;
1761 x[3] = 0; y[3] = orig_height;
1762
1763 for (i = 0; i < 4; i++)
1764 cairo_matrix_transform_point_moz_cairo_matrix_transform_point (&original_to_transformed,
1765 &x[i], &y[i]);
1766
1767 x_min = floor (x[0]); y_min = floor (y[0]);
1768 x_max = ceil (x[0]); y_max = ceil (y[0]);
1769
1770 for (i = 1; i < 4; i++) {
1771 if (x[i] < x_min)
1772 x_min = floor (x[i]);
1773 else if (x[i] > x_max)
1774 x_max = ceil (x[i]);
1775 if (y[i] < y_min)
1776 y_min = floor (y[i]);
1777 else if (y[i] > y_max)
1778 y_max = ceil (y[i]);
1779 }
1780
1781 /* Adjust the transform so that the bounding box starts at 0,0 ...
1782 * this gives our final transform from original bitmap to transformed
1783 * bitmap.
1784 */
1785 original_to_transformed.x0 -= x_min;
1786 original_to_transformed.y0 -= y_min;
1787
1788 /* Create the transformed bitmap */
1789 width = x_max - x_min;
1790 height = y_max - y_min;
1791
1792 transformed_to_original = original_to_transformed;
1793 status = cairo_matrix_invert_moz_cairo_matrix_invert (&transformed_to_original);
1794 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1795 return status;
1796
1797 if ((*surface)->format == CAIRO_FORMAT_ARGB32 &&
1798 !pixman_image_get_component_alpha_moz_pixman_image_get_component_alpha ((*surface)->pixman_image))
1799 image = cairo_image_surface_create_moz_cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
1800 else
1801 image = cairo_image_surface_create_moz_cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
1802 if (unlikely (image->status)(__builtin_expect (!!(image->status), 0)))
1803 return image->status;
1804
1805 /* Draw the original bitmap transformed into the new bitmap
1806 */
1807 _cairo_pattern_init_for_surface (&pattern, &(*surface)->base);
1808 cairo_pattern_set_matrix_moz_cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
1809
1810 status = _cairo_surface_paint (image,
1811 CAIRO_OPERATOR_SOURCE,
1812 &pattern.base,
1813 NULL((void*)0));
1814
1815 _cairo_pattern_fini (&pattern.base);
1816
1817 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
1818 cairo_surface_destroy_moz_cairo_surface_destroy (image);
1819 return status;
1820 }
1821
1822 /* Now update the cache entry for the new bitmap, recomputing
1823 * the origin based on the final transform.
1824 */
1825 cairo_matrix_transform_point_moz_cairo_matrix_transform_point (&original_to_transformed,
1826 &origin_x, &origin_y);
1827
1828 old_image = (*surface);
1829 (*surface) = (cairo_image_surface_t *)image;
1830
1831 /* Note: we converted subpixel-rendered RGBA images to grayscale,
1832 * so, no need to copy component alpha to new image. */
1833
1834 cairo_surface_destroy_moz_cairo_surface_destroy (&old_image->base);
1835
1836 cairo_surface_set_device_offset_moz_cairo_surface_set_device_offset (&(*surface)->base,
1837 _cairo_lround (origin_x),
1838 _cairo_lround (origin_y));
1839 return CAIRO_STATUS_SUCCESS;
1840}
1841
1842static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = {
1843 _cairo_ft_unscaled_font_destroy,
1844#if 0
1845 _cairo_ft_unscaled_font_create_glyph
1846#endif
1847};
1848
1849/* #cairo_ft_scaled_font_t */
1850
1851typedef struct _cairo_ft_scaled_font {
1852 cairo_scaled_font_t base;
1853 cairo_ft_unscaled_font_t *unscaled;
1854 cairo_ft_options_t ft_options;
1855} cairo_ft_scaled_font_t;
1856
1857static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend;
1858
1859#if CAIRO_HAS_FC_FONT1
1860/* The load flags passed to FT_Load_Glyph control aspects like hinting and
1861 * antialiasing. Here we compute them from the fields of a FcPattern.
1862 */
1863static void
1864_get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
1865{
1866 FcBool antialias, vertical_layout, hinting, autohint, bitmap, embolden;
1867 cairo_ft_options_t ft_options;
1868 int rgba;
1869 int hintstyle;
1870 char *variations;
1871
1872 _cairo_font_options_init_default (&ft_options.base);
1873 ft_options.load_flags = FT_LOAD_DEFAULT0x0;
1874 ft_options.synth_flags = 0;
1875
1876 /* Check whether to force use of embedded bitmaps */
1877 if (FcPatternGetBool (pattern,
1878 FC_EMBEDDED_BITMAP"embeddedbitmap", 0, &bitmap) != FcResultMatch)
1879 bitmap = FcFalse0;
1880
1881 /* disable antialiasing if requested */
1882 if (FcPatternGetBool (pattern,
1883 FC_ANTIALIAS"antialias", 0, &antialias) != FcResultMatch)
1884 antialias = FcTrue1;
1885
1886 if (antialias) {
1887 cairo_subpixel_order_t subpixel_order;
1888 int lcd_filter;
1889
1890 /* disable hinting if requested */
1891 if (FcPatternGetBool (pattern,
1892 FC_HINTING"hinting", 0, &hinting) != FcResultMatch)
1893 hinting = FcTrue1;
1894
1895 if (FcPatternGetInteger (pattern,
1896 FC_RGBA"rgba", 0, &rgba) != FcResultMatch)
1897 rgba = FC_RGBA_UNKNOWN0;
1898
1899 switch (rgba) {
1900 case FC_RGBA_RGB1:
1901 subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
1902 break;
1903 case FC_RGBA_BGR2:
1904 subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
1905 break;
1906 case FC_RGBA_VRGB3:
1907 subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
1908 break;
1909 case FC_RGBA_VBGR4:
1910 subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
1911 break;
1912 case FC_RGBA_UNKNOWN0:
1913 case FC_RGBA_NONE5:
1914 default:
1915 subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
1916 break;
1917 }
1918
1919 if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) {
1920 ft_options.base.subpixel_order = subpixel_order;
1921 ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
1922 }
1923
1924 if (FcPatternGetInteger (pattern,
1925 FC_LCD_FILTER"lcdfilter", 0, &lcd_filter) == FcResultMatch)
1926 {
1927 switch (lcd_filter) {
1928 case FC_LCD_NONE0:
1929 ft_options.base.lcd_filter = CAIRO_LCD_FILTER_NONE;
1930 break;
1931 case FC_LCD_DEFAULT1:
1932 ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5;
1933 break;
1934 case FC_LCD_LIGHT2:
1935 ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3;
1936 break;
1937 case FC_LCD_LEGACY3:
1938 ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
1939 break;
1940 }
1941 }
1942
1943 if (FcPatternGetInteger (pattern,
1944 FC_HINT_STYLE"hintstyle", 0, &hintstyle) != FcResultMatch)
1945 hintstyle = FC_HINT_FULL3;
1946
1947 if (!hinting)
1948 hintstyle = FC_HINT_NONE0;
1949
1950 switch (hintstyle) {
1951 case FC_HINT_NONE0:
1952 ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
1953 break;
1954 case FC_HINT_SLIGHT1:
1955 ft_options.base.hint_style = CAIRO_HINT_STYLE_SLIGHT;
1956 break;
1957 case FC_HINT_MEDIUM2:
1958 default:
1959 ft_options.base.hint_style = CAIRO_HINT_STYLE_MEDIUM;
1960 break;
1961 case FC_HINT_FULL3:
1962 ft_options.base.hint_style = CAIRO_HINT_STYLE_FULL;
1963 break;
1964 }
1965
1966 /* Force embedded bitmaps off if no hinting requested */
1967 if (ft_options.base.hint_style == CAIRO_HINT_STYLE_NONE)
1968 bitmap = FcFalse0;
1969
1970 if (!bitmap)
1971 ft_options.load_flags |= FT_LOAD_NO_BITMAP( 1L << 3 );
1972
1973 } else {
1974 ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
1975 }
1976
1977 /* force autohinting if requested */
1978 if (FcPatternGetBool (pattern,
1979 FC_AUTOHINT"autohint", 0, &autohint) != FcResultMatch)
1980 autohint = FcFalse0;
1981
1982 if (autohint)
1983 ft_options.load_flags |= FT_LOAD_FORCE_AUTOHINT( 1L << 5 );
1984
1985 if (FcPatternGetBool (pattern,
1986 FC_VERTICAL_LAYOUT"verticallayout", 0, &vertical_layout) != FcResultMatch)
1987 vertical_layout = FcFalse0;
1988
1989 if (vertical_layout)
1990 ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT( 1L << 4 );
1991
1992 if (FcPatternGetBool (pattern,
1993 FC_EMBOLDEN"embolden", 0, &embolden) != FcResultMatch)
1994 embolden = FcFalse0;
1995
1996 if (embolden)
1997 ft_options.synth_flags |= CAIRO_FT_SYNTHESIZE_BOLD;
1998
1999#ifndef FC_FONT_VARIATIONS"fontvariations"
2000#define FC_FONT_VARIATIONS"fontvariations" "fontvariations"
2001#endif
2002 if (FcPatternGetString (pattern, FC_FONT_VARIATIONS"fontvariations", 0, (FcChar8 **) &variations) == FcResultMatch) {
2003 ft_options.base.variations = strdup (variations);
2004 }
2005
2006 *ret = ft_options;
2007}
2008#endif
2009
2010static void
2011_cairo_ft_options_merge (cairo_ft_options_t *options,
2012 cairo_ft_options_t *other)
2013{
2014 int load_flags = other->load_flags;
2015 int load_target = FT_LOAD_TARGET_NORMAL( (FT_Int32)((FT_RENDER_MODE_NORMAL) & 15) << 16 );
2016
2017 /* clear load target mode */
2018 load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(other->load_flags))( (FT_Int32)(((FT_Render_Mode)(( (other->load_flags) >>
16 ) & 15)) & 15) << 16 )
);
2019
2020 if (load_flags & FT_LOAD_NO_HINTING( 1L << 1 ))
2021 other->base.hint_style = CAIRO_HINT_STYLE_NONE;
2022
2023 if (other->base.antialias == CAIRO_ANTIALIAS_NONE ||
2024 options->base.antialias == CAIRO_ANTIALIAS_NONE) {
2025 options->base.antialias = CAIRO_ANTIALIAS_NONE;
2026 options->base.subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
2027 }
2028
2029 if (other->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL &&
2030 options->base.antialias == CAIRO_ANTIALIAS_DEFAULT) {
2031 options->base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
2032 options->base.subpixel_order = other->base.subpixel_order;
2033 }
2034
2035 if (options->base.hint_style == CAIRO_HINT_STYLE_DEFAULT)
2036 options->base.hint_style = other->base.hint_style;
2037
2038 if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
2039 options->base.hint_style = CAIRO_HINT_STYLE_NONE;
2040
2041 if (options->base.lcd_filter == CAIRO_LCD_FILTER_DEFAULT)
2042 options->base.lcd_filter = other->base.lcd_filter;
2043
2044 if (other->base.lcd_filter == CAIRO_LCD_FILTER_NONE)
2045 options->base.lcd_filter = CAIRO_LCD_FILTER_NONE;
2046
2047 if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
2048 if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
2049 load_flags |= FT_LOAD_NO_HINTING( 1L << 1 );
2050 else
2051 load_target = FT_LOAD_TARGET_MONO( (FT_Int32)((FT_RENDER_MODE_MONO) & 15) << 16 );
2052 load_flags |= FT_LOAD_MONOCHROME( 1L << 12 );
2053 } else {
2054 switch (options->base.hint_style) {
2055 case CAIRO_HINT_STYLE_NONE:
2056 load_flags |= FT_LOAD_NO_HINTING( 1L << 1 );
2057 break;
2058 case CAIRO_HINT_STYLE_SLIGHT:
2059 load_target = FT_LOAD_TARGET_LIGHT( (FT_Int32)((FT_RENDER_MODE_LIGHT) & 15) << 16 );
2060 break;
2061 case CAIRO_HINT_STYLE_MEDIUM:
2062 break;
2063 case CAIRO_HINT_STYLE_FULL:
2064 case CAIRO_HINT_STYLE_DEFAULT:
2065 if (options->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
2066 switch (options->base.subpixel_order) {
2067 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
2068 case CAIRO_SUBPIXEL_ORDER_RGB:
2069 case CAIRO_SUBPIXEL_ORDER_BGR:
2070 load_target = FT_LOAD_TARGET_LCD( (FT_Int32)((FT_RENDER_MODE_LCD) & 15) << 16 );
2071 break;
2072 case CAIRO_SUBPIXEL_ORDER_VRGB:
2073 case CAIRO_SUBPIXEL_ORDER_VBGR:
2074 load_target = FT_LOAD_TARGET_LCD_V( (FT_Int32)((FT_RENDER_MODE_LCD_V) & 15) << 16 );
2075 break;
2076 }
2077 }
2078 break;
2079 }
2080 }
2081
2082 if (other->base.variations) {
2083 if (options->base.variations) {
2084 char *p;
2085
2086 /* 'merge' variations by concatenating - later entries win */
2087 p = malloc (strlen (other->base.variations) + strlen (options->base.variations) + 2);
2088 p[0] = 0;
2089 strcat (p, other->base.variations);
2090 strcat (p, ",");
2091 strcat (p, options->base.variations);
2092 free (options->base.variations);
2093 options->base.variations = p;
2094 }
2095 else {
2096 options->base.variations = strdup (other->base.variations);
2097 }
2098 }
2099
2100 options->load_flags = load_flags | load_target;
2101 options->synth_flags = other->synth_flags;
2102}
2103
2104static cairo_status_t
2105_cairo_ft_font_face_scaled_font_create (void *abstract_font_face,
2106 const cairo_matrix_t *font_matrix,
2107 const cairo_matrix_t *ctm,
2108 const cairo_font_options_t *options,
2109 cairo_scaled_font_t **font_out)
2110{
2111 cairo_ft_font_face_t *font_face = abstract_font_face;
2112 cairo_ft_scaled_font_t *scaled_font;
2113 FT_Face face;
2114 FT_Size_Metrics *metrics;
2115 cairo_font_extents_t fs_metrics;
2116 cairo_status_t status;
2117 cairo_ft_unscaled_font_t *unscaled;
2118
2119 assert (font_face->unscaled)((void) sizeof (__assert_single_arg (font_face->unscaled))
, __extension__ ({ if (font_face->unscaled) ; else __assert_fail
("font_face->unscaled", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c"
, 2119, __extension__ __PRETTY_FUNCTION__); }))
;
2120
2121 face = _cairo_ft_unscaled_font_lock_face (font_face->unscaled);
2122 if (unlikely (face == NULL)(__builtin_expect (!!(face == ((void*)0)), 0))) /* backend error */
2123 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2124
2125 scaled_font = _cairo_calloc (sizeof (cairo_ft_scaled_font_t))((sizeof (cairo_ft_scaled_font_t)) != 0 ? calloc(1,sizeof (cairo_ft_scaled_font_t
)) : ((void*)0))
;
2126 if (unlikely (scaled_font == NULL)(__builtin_expect (!!(scaled_font == ((void*)0)), 0))) {
2127 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2128 goto FAIL;
2129 }
2130
2131 scaled_font->unscaled = unscaled = font_face->unscaled;
2132 _cairo_unscaled_font_reference (&unscaled->base);
2133
2134 _cairo_font_options_init_copy (&scaled_font->ft_options.base, options);
2135 _cairo_ft_options_merge (&scaled_font->ft_options, &font_face->ft_options);
2136
2137 status = _cairo_scaled_font_init (&scaled_font->base,
2138 &font_face->base,
2139 font_matrix, ctm, options,
2140 &_cairo_ft_scaled_font_backend);
2141 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2142 goto CLEANUP_SCALED_FONT;
2143
2144 status = _cairo_ft_unscaled_font_set_scale (unscaled,
2145 &scaled_font->base.scale);
2146 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
2147 /* This can only fail if we encounter an error with the underlying
2148 * font, so propagate the error back to the font-face. */
2149 _cairo_ft_unscaled_font_unlock_face (unscaled);
2150 _cairo_unscaled_font_destroy (&unscaled->base);
2151 free (scaled_font);
2152 return status;
2153 }
2154
2155
2156 metrics = &face->size->metrics;
2157
2158 /*
2159 * Get to unscaled metrics so that the upper level can get back to
2160 * user space
2161 *
2162 * Also use this path for bitmap-only fonts. The other branch uses
2163 * face members that are only relevant for scalable fonts. This is
2164 * detected by simply checking for units_per_EM==0.
2165 */
2166 if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF ||
2167 face->units_per_EM == 0) {
2168 fs_metrics.ascent = SCALE (DOUBLE_FROM_26_6 (metrics->ascender), unscaled->y_scale)((unscaled->y_scale) == 0 ? 0.0 : (((double)(metrics->ascender
) / 64.0)) / (unscaled->y_scale))
;
2169 fs_metrics.descent = SCALE (DOUBLE_FROM_26_6 (- metrics->descender), unscaled->y_scale)((unscaled->y_scale) == 0 ? 0.0 : (((double)(- metrics->
descender) / 64.0)) / (unscaled->y_scale))
;
2170 fs_metrics.height = SCALE (DOUBLE_FROM_26_6 (metrics->height), unscaled->y_scale)((unscaled->y_scale) == 0 ? 0.0 : (((double)(metrics->height
) / 64.0)) / (unscaled->y_scale))
;
2171 if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
2172 fs_metrics.max_x_advance = SCALE (DOUBLE_FROM_26_6 (metrics->max_advance), unscaled->x_scale)((unscaled->x_scale) == 0 ? 0.0 : (((double)(metrics->max_advance
) / 64.0)) / (unscaled->x_scale))
;
2173 fs_metrics.max_y_advance = 0;
2174 } else {
2175 fs_metrics.max_x_advance = 0;
2176 fs_metrics.max_y_advance = SCALE (DOUBLE_FROM_26_6 (metrics->max_advance), unscaled->y_scale)((unscaled->y_scale) == 0 ? 0.0 : (((double)(metrics->max_advance
) / 64.0)) / (unscaled->y_scale))
;
2177 }
2178 } else {
2179 double scale = face->units_per_EM;
2180
2181 fs_metrics.ascent = face->ascender / scale;
2182 fs_metrics.descent = - face->descender / scale;
2183 fs_metrics.height = face->height / scale;
2184 if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
2185 fs_metrics.max_x_advance = face->max_advance_width / scale;
2186 fs_metrics.max_y_advance = 0;
2187 } else {
2188 fs_metrics.max_x_advance = 0;
2189 fs_metrics.max_y_advance = face->max_advance_height / scale;
2190 }
2191 }
2192
2193 status = _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics);
2194 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2195 goto CLEANUP_SCALED_FONT;
2196
2197 _cairo_ft_unscaled_font_unlock_face (unscaled);
2198
2199 *font_out = &scaled_font->base;
2200 return CAIRO_STATUS_SUCCESS;
2201
2202 CLEANUP_SCALED_FONT:
2203 _cairo_unscaled_font_destroy (&unscaled->base);
2204 free (scaled_font);
2205 FAIL:
2206 _cairo_ft_unscaled_font_unlock_face (font_face->unscaled);
2207 *font_out = _cairo_scaled_font_create_in_error (status);
2208 return CAIRO_STATUS_SUCCESS; /* non-backend error */
2209}
2210
2211cairo_bool_t
2212_cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
2213{
2214 return scaled_font->backend == &_cairo_ft_scaled_font_backend;
2215}
2216
2217static void
2218_cairo_ft_scaled_font_fini (void *abstract_font)
2219{
2220 cairo_ft_scaled_font_t *scaled_font = abstract_font;
2221
2222 if (scaled_font == NULL((void*)0))
2223 return;
2224
2225 _cairo_font_options_fini (&scaled_font->ft_options.base);
2226 _cairo_unscaled_font_destroy (&scaled_font->unscaled->base);
2227}
2228
2229static int
2230_move_to (FT_Vector *to, void *closure)
2231{
2232 cairo_path_fixed_t *path = closure;
2233 cairo_fixed_t x, y;
2234
2235 x = _cairo_fixed_from_26_6 (to->x);
2236 y = _cairo_fixed_from_26_6 (to->y);
2237
2238 if (_cairo_path_fixed_close_path (path) != CAIRO_STATUS_SUCCESS)
2239 return 1;
2240 if (_cairo_path_fixed_move_to (path, x, y) != CAIRO_STATUS_SUCCESS)
2241 return 1;
2242
2243 return 0;
2244}
2245
2246static int
2247_line_to (FT_Vector *to, void *closure)
2248{
2249 cairo_path_fixed_t *path = closure;
2250 cairo_fixed_t x, y;
2251
2252 x = _cairo_fixed_from_26_6 (to->x);
2253 y = _cairo_fixed_from_26_6 (to->y);
2254
2255 if (_cairo_path_fixed_line_to (path, x, y) != CAIRO_STATUS_SUCCESS)
2256 return 1;
2257
2258 return 0;
2259}
2260
2261static int
2262_conic_to (FT_Vector *control, FT_Vector *to, void *closure)
2263{
2264 cairo_path_fixed_t *path = closure;
2265
2266 cairo_fixed_t x0, y0;
2267 cairo_fixed_t x1, y1;
2268 cairo_fixed_t x2, y2;
2269 cairo_fixed_t x3, y3;
2270 cairo_point_t conic;
2271
2272 if (! _cairo_path_fixed_get_current_point (path, &x0, &y0))
2273 return 1;
2274
2275 conic.x = _cairo_fixed_from_26_6 (control->x);
2276 conic.y = _cairo_fixed_from_26_6 (control->y);
2277
2278 x3 = _cairo_fixed_from_26_6 (to->x);
2279 y3 = _cairo_fixed_from_26_6 (to->y);
2280
2281 x1 = x0 + 2.0/3.0 * (conic.x - x0);
2282 y1 = y0 + 2.0/3.0 * (conic.y - y0);
2283
2284 x2 = x3 + 2.0/3.0 * (conic.x - x3);
2285 y2 = y3 + 2.0/3.0 * (conic.y - y3);
2286
2287 if (_cairo_path_fixed_curve_to (path,
2288 x1, y1,
2289 x2, y2,
2290 x3, y3) != CAIRO_STATUS_SUCCESS)
2291 return 1;
2292
2293 return 0;
2294}
2295
2296static int
2297_cubic_to (FT_Vector *control1, FT_Vector *control2,
2298 FT_Vector *to, void *closure)
2299{
2300 cairo_path_fixed_t *path = closure;
2301 cairo_fixed_t x0, y0;
2302 cairo_fixed_t x1, y1;
2303 cairo_fixed_t x2, y2;
2304
2305 x0 = _cairo_fixed_from_26_6 (control1->x);
2306 y0 = _cairo_fixed_from_26_6 (control1->y);
2307
2308 x1 = _cairo_fixed_from_26_6 (control2->x);
2309 y1 = _cairo_fixed_from_26_6 (control2->y);
2310
2311 x2 = _cairo_fixed_from_26_6 (to->x);
2312 y2 = _cairo_fixed_from_26_6 (to->y);
2313
2314 if (_cairo_path_fixed_curve_to (path,
2315 x0, y0,
2316 x1, y1,
2317 x2, y2) != CAIRO_STATUS_SUCCESS)
2318 return 1;
2319
2320 return 0;
2321}
2322
2323cairo_status_t
2324_cairo_ft_face_decompose_glyph_outline (FT_Face face,
2325 cairo_path_fixed_t **pathp)
2326{
2327 static const FT_Outline_Funcs outline_funcs = {
2328 (FT_Outline_MoveToFunc)_move_to,
2329 (FT_Outline_LineToFunc)_line_to,
2330 (FT_Outline_ConicToFunc)_conic_to,
2331 (FT_Outline_CubicToFunc)_cubic_to,
2332 0, /* shift */
2333 0, /* delta */
2334 };
2335 static const FT_Matrix invert_y = {
2336 DOUBLE_TO_16_16 (1.0)((FT_Fixed)((1.0) * 65536.0)), 0,
2337 0, DOUBLE_TO_16_16 (-1.0)((FT_Fixed)((-1.0) * 65536.0)),
2338 };
2339
2340 FT_GlyphSlot glyph;
2341 cairo_path_fixed_t *path;
2342 cairo_status_t status;
2343
2344 path = _cairo_path_fixed_create ();
2345 if (!path)
2346 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2347
2348 glyph = face->glyph;
2349
2350 /* Font glyphs have an inverted Y axis compared to cairo. */
2351 FT_Outline_Transform (&glyph->outline, &invert_y);
2352 if (FT_Outline_Decompose (&glyph->outline, &outline_funcs, path)) {
2353 _cairo_path_fixed_destroy (path);
2354 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2355 }
2356
2357 status = _cairo_path_fixed_close_path (path);
2358 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
2359 _cairo_path_fixed_destroy (path);
2360 return status;
2361 }
2362
2363 *pathp = path;
2364
2365 return CAIRO_STATUS_SUCCESS;
2366}
2367
2368/*
2369 * Translate glyph to match its metrics.
2370 */
2371static void
2372_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (void *abstract_font,
2373 FT_GlyphSlot glyph)
2374{
2375 cairo_ft_scaled_font_t *scaled_font = abstract_font;
2376 FT_Vector vector;
2377
2378 vector.x = glyph->metrics.vertBearingX - glyph->metrics.horiBearingX;
2379 vector.y = -glyph->metrics.vertBearingY - glyph->metrics.horiBearingY;
2380
2381 if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
2382 FT_Vector_Transform (&vector, &scaled_font->unscaled->Current_Shape);
2383 FT_Outline_Translate(&glyph->outline, vector.x, vector.y);
2384 } else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
2385 glyph->bitmap_left += vector.x / 64;
2386 glyph->bitmap_top += vector.y / 64;
2387 }
2388}
2389
2390static void
2391cairo_ft_apply_variations (FT_Face face,
2392 cairo_ft_scaled_font_t *scaled_font)
2393{
2394 FT_MM_Var *ft_mm_var;
2395 FT_Error ret;
2396 unsigned int instance_id = scaled_font->unscaled->id >> 16;
2397
2398 static GetVarFunc getVar;
2399 static DoneVarFunc doneVar;
2400 static GetVarDesignCoordsFunc getVarDesignCoords;
2401 static SetVarDesignCoordsFunc setVarDesignCoords;
2402
2403 static int firstTime = 1;
2404 if (firstTime) {
2405 getVar = (GetVarFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Get_MM_Var");
2406 doneVar = (DoneVarFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Done_MM_Var");
2407 getVarDesignCoords = (GetVarDesignCoordsFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Get_Var_Design_Coordinates");
2408 setVarDesignCoords = (SetVarDesignCoordsFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Set_Var_Design_Coordinates");
2409 firstTime = 0;
2410 }
2411
2412 if (!getVar || !setVarDesignCoords)
2413 return;
2414
2415 ret = (*getVar) (face, &ft_mm_var);
2416 if (ret == 0) {
2417 FT_Fixed *current_coords;
2418 FT_Fixed *coords;
2419 unsigned int i;
2420 const char *p;
2421
2422 coords = malloc (sizeof (FT_Fixed) * ft_mm_var->num_axis);
2423 /* FIXME check coords. */
2424
2425 if (scaled_font->unscaled->variations)
2426 {
2427 memcpy (coords, scaled_font->unscaled->variations, ft_mm_var->num_axis * sizeof (*coords));
2428 }
2429 else if (instance_id && instance_id <= ft_mm_var->num_namedstyles)
2430 {
2431 FT_Var_Named_Style *instance = &ft_mm_var->namedstyle[instance_id - 1];
2432 memcpy (coords, instance->coords, ft_mm_var->num_axis * sizeof (*coords));
2433 }
2434 else
2435 for (i = 0; i < ft_mm_var->num_axis; i++)
2436 coords[i] = ft_mm_var->axis[i].def;
2437
2438 p = scaled_font->ft_options.base.variations;
2439 while (p && *p) {
2440 const char *start;
2441 const char *end, *end2;
2442 FT_ULong tag;
2443 double value;
2444
2445 while (_cairo_isspace (*p)) p++;
2446
2447 start = p;
2448 end = strchr (p, ',')_Generic (0 ? (p) : (void *) 1, const void *: (const char *) (
strchr (p, ',')), default: strchr (p, ','))
;
2449 if (end && (end - p < 6))
2450 goto skip;
2451
2452 tag = FT_MAKE_TAG(p[0], p[1], p[2], p[3])( ( (FT_Tag)(unsigned char)(p[0]) << 24 ) | ( (FT_Tag)(
unsigned char)(p[1]) << 16 ) | ( (FT_Tag)(unsigned char
)(p[2]) << 8 ) | (FT_Tag)(unsigned char)(p[3]) )
;
2453
2454 p += 4;
2455 while (_cairo_isspace (*p)) p++;
2456 if (*p == '=') p++;
2457
2458 if (p - start < 5)
2459 goto skip;
2460
2461 value = _cairo_strtod (p, (char **) &end2);
2462
2463 while (end2 && _cairo_isspace (*end2)) end2++;
2464
2465 if (end2 && (*end2 != ',' && *end2 != '\0'))
2466 goto skip;
2467
2468 for (i = 0; i < ft_mm_var->num_axis; i++) {
2469 if (ft_mm_var->axis[i].tag == tag) {
2470 coords[i] = (FT_Fixed)(value*65536);
2471 break;
2472 }
2473 }
2474
2475skip:
2476 p = end ? end + 1 : NULL((void*)0);
2477 }
2478
2479 current_coords = malloc (sizeof (FT_Fixed) * ft_mm_var->num_axis);
2480
2481 if (getVarDesignCoords) {
2482 ret = (*getVarDesignCoords) (face, ft_mm_var->num_axis, current_coords);
2483 if (ret == 0) {
2484 for (i = 0; i < ft_mm_var->num_axis; i++) {
2485 if (coords[i] != current_coords[i])
2486 break;
2487 }
2488 if (i == ft_mm_var->num_axis)
2489 goto done;
2490 }
2491 }
2492
2493 (*setVarDesignCoords) (face, ft_mm_var->num_axis, coords);
2494done:
2495 free (coords);
2496 free (current_coords);
2497
2498 if (doneVar)
2499 (*doneVar) (face->glyph->library, ft_mm_var);
2500 else
2501 free (ft_mm_var);
2502 }
2503}
2504
2505typedef enum {
2506 CAIRO_FT_GLYPH_TYPE_BITMAP,
2507 CAIRO_FT_GLYPH_TYPE_OUTLINE,
2508 CAIRO_FT_GLYPH_TYPE_SVG,
2509 CAIRO_FT_GLYPH_TYPE_COLR_V0,
2510 CAIRO_FT_GLYPH_TYPE_COLR_V1,
2511} cairo_ft_glyph_format_t;
2512
2513typedef struct {
2514 cairo_scaled_glyph_private_t base;
2515
2516 cairo_ft_glyph_format_t format;
2517} cairo_ft_glyph_private_t;
2518
2519static const int ft_glyph_private_key;
2520
2521static cairo_int_status_t
2522_cairo_ft_scaled_glyph_load_glyph (cairo_ft_scaled_font_t *scaled_font,
2523 cairo_scaled_glyph_t *scaled_glyph,
2524 FT_Face face,
2525 int load_flags,
2526 cairo_bool_t use_em_size,
2527 cairo_bool_t vertical_layout)
2528{
2529 FT_Error error;
2530 cairo_status_t status;
2531 cairo_ft_glyph_private_t *glyph_priv;
2532
2533 glyph_priv = (cairo_ft_glyph_private_t *) _cairo_scaled_glyph_find_private (scaled_glyph,
2534 &ft_glyph_private_key);
2535 assert (glyph_priv != NULL)((void) sizeof (__assert_single_arg (glyph_priv != ((void*)0)
)), __extension__ ({ if (glyph_priv != ((void*)0)) ; else __assert_fail
("glyph_priv != NULL", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c"
, 2535, __extension__ __PRETTY_FUNCTION__); }))
;
2536
2537 if (use_em_size) {
2538 cairo_matrix_t em_size;
2539 cairo_matrix_init_scale_moz_cairo_matrix_init_scale (&em_size, face->units_per_EM, face->units_per_EM);
2540 status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, &em_size);
2541 } else {
2542 status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
2543 &scaled_font->base.scale);
2544 }
2545 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2546 return status;
2547
2548 cairo_ft_apply_variations (face, scaled_font);
2549
2550#if defined(HAVE_FT_LOAD_NO_SVG)
2551 if (load_flags & FT_LOAD_COLOR( 1L << 20 ) && glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1)
2552 load_flags |= FT_LOAD_NO_SVG( 1L << 24 );
2553#endif
2554
2555 error = FT_Load_Glyph (face,
2556 _cairo_scaled_glyph_index(scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
2557 load_flags);
2558 /* XXX ignoring all other errors for now. They are not fatal, typically
2559 * just a glyph-not-found. */
2560 if (error == FT_Err_Out_Of_Memory)
2561 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2562
2563 /*
2564 * synthesize glyphs if requested
2565 */
2566 if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD)
2567 FT_GlyphSlot_Embolden (face->glyph);
2568
2569 if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_OBLIQUE)
2570 FT_GlyphSlot_Oblique (face->glyph);
2571
2572 if (vertical_layout)
2573 _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, face->glyph);
2574
2575 if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
2576 FT_Pos xshift, yshift;
2577
2578 xshift = _cairo_scaled_glyph_xphase (scaled_glyph)(int)(((scaled_glyph)->hash_entry.hash >> 24) & 3
)
<< 4;
2579 yshift = _cairo_scaled_glyph_yphase (scaled_glyph)(int)(((scaled_glyph)->hash_entry.hash >> 26) & 3
)
<< 4;
2580
2581 FT_Outline_Translate (&face->glyph->outline, xshift, -yshift);
2582 }
2583
2584 return CAIRO_STATUS_SUCCESS;
2585}
2586
2587static void
2588_cairo_ft_glyph_fini (cairo_scaled_glyph_private_t *glyph_private,
2589 cairo_scaled_glyph_t *glyph,
2590 cairo_scaled_font_t *font)
2591{
2592 cairo_list_del (&glyph_private->link);
2593 free (glyph_private);
2594}
2595
2596
2597#ifdef FT_COLOR_H<freetype/ftcolor.h>
2598static void
2599_cairo_ft_scaled_glyph_set_palette (cairo_ft_scaled_font_t *scaled_font,
2600 FT_Face face,
2601 unsigned int *num_entries_ret,
2602 FT_Color **entries_ret)
2603{
2604 unsigned int num_entries = 0;
2605 FT_Color *entries = NULL((void*)0);
2606
2607 FT_Palette_Data palette_data;
2608
2609 if (FT_Palette_Data_Get (face, &palette_data) == 0 && palette_data.num_palettes > 0) {
2610 FT_UShort palette_index = CAIRO_COLOR_PALETTE_DEFAULT0;
2611 if (scaled_font->base.options.palette_index < palette_data.num_palettes)
2612 palette_index = scaled_font->base.options.palette_index;
2613
2614 if (FT_Palette_Select (face, palette_index, &entries) == 0) {
2615 num_entries = palette_data.num_palette_entries;
2616
2617 /* Overlay custom colors */
2618 for (unsigned int i = 0; i < scaled_font->base.options.custom_palette_size; i++) {
2619 cairo_palette_color_t *entry = &scaled_font->base.options.custom_palette[i];
2620 if (entry->index < num_entries) {
2621 entries[entry->index].red = 255 * entry->red;
2622 entries[entry->index].green = 255 * entry->green;
2623 entries[entry->index].blue = 255 * entry->blue;
2624 entries[entry->index].alpha = 255 * entry->alpha;
2625 }
2626 }
2627 }
2628 }
2629
2630 if (num_entries_ret)
2631 *num_entries_ret = num_entries;
2632
2633 if (entries_ret)
2634 *entries_ret = entries;
2635}
2636#else
2637static void
2638_cairo_ft_scaled_glyph_set_palette (cairo_ft_scaled_font_t *scaled_font,
2639 FT_Face face,
2640 unsigned int *num_entries_ret,
2641 void **entries_ret)
2642{
2643 if (num_entries_ret)
2644 *num_entries_ret = 0;
2645
2646 if (entries_ret)
2647 *entries_ret = NULL((void*)0);
2648}
2649#endif
2650
2651/* returns TRUE if foreground color used */
2652static cairo_bool_t
2653_cairo_ft_scaled_glyph_set_foreground_color (cairo_ft_scaled_font_t *scaled_font,
2654 cairo_scaled_glyph_t *scaled_glyph,
2655 FT_Face face,
2656 const cairo_color_t *foreground_color)
2657{
2658 cairo_bool_t uses_foreground_color = FALSE0;
2659#ifdef FT_COLOR_H<freetype/ftcolor.h>
2660 FT_LayerIterator iterator;
2661 FT_UInt layer_glyph_index;
2662 FT_UInt layer_color_index;
2663 FT_Color color;
2664
2665 /* Check if there is a layer that uses the foreground color */
2666 iterator.p = NULL((void*)0);
2667 while (FT_Get_Color_Glyph_Layer(face,
2668 _cairo_scaled_glyph_index (scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
2669 &layer_glyph_index,
2670 &layer_color_index,
2671 &iterator)) {
2672 if (layer_color_index == 0xFFFF) {
2673 uses_foreground_color = TRUE1;
2674 break;
2675 }
2676 }
2677
2678 if (uses_foreground_color) {
2679 color.red = (FT_Byte)(foreground_color->red * 0xFF);
2680 color.green = (FT_Byte)(foreground_color->green * 0xFF);
2681 color.blue = (FT_Byte)(foreground_color->blue * 0xFF);
2682 color.alpha = (FT_Byte)(foreground_color->alpha * 0xFF);
2683 FT_Palette_Set_Foreground_Color (face, color);
2684 }
2685#endif
2686 return uses_foreground_color;
2687}
2688
2689static cairo_int_status_t
2690_cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font,
2691 cairo_scaled_glyph_t *scaled_glyph,
2692 cairo_ft_glyph_private_t *glyph_priv,
2693 cairo_scaled_glyph_info_t info,
2694 FT_Face face,
2695 const cairo_color_t *foreground_color,
2696 cairo_bool_t vertical_layout,
2697 int load_flags)
2698{
2699 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
2700 FT_GlyphSlot glyph;
2701 cairo_status_t status;
2702 cairo_image_surface_t *surface;
15
'surface' declared without an initial value
2703 cairo_bool_t uses_foreground_color = FALSE0;
2704
2705 /* Only one info type at a time handled in this function */
2706 assert (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE || info == CAIRO_SCALED_GLYPH_INFO_SURFACE)((void) sizeof (__assert_single_arg (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE
|| info == CAIRO_SCALED_GLYPH_INFO_SURFACE)), __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-ft-font.c", 2706
, __extension__ __PRETTY_FUNCTION__); }))
;
16
Taking true branch
2707
2708 if (info
16.1
'info' is not equal to CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE
== CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
17
Taking false branch
2709 if (!unscaled->have_color) {
2710 scaled_glyph->color_glyph = FALSE0;
2711 scaled_glyph->color_glyph_set = TRUE1;
2712 return CAIRO_INT_STATUS_UNSUPPORTED;
2713 }
2714
2715 uses_foreground_color = _cairo_ft_scaled_glyph_set_foreground_color (scaled_font,
2716 scaled_glyph,
2717 face,
2718 foreground_color);
2719 _cairo_ft_scaled_glyph_set_palette (scaled_font, face, NULL((void*)0), NULL((void*)0));
2720
2721 load_flags &= ~FT_LOAD_MONOCHROME( 1L << 12 );
2722 /* clear load target mode */
2723 load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(load_flags))( (FT_Int32)(((FT_Render_Mode)(( (load_flags) >> 16 ) &
15)) & 15) << 16 )
);
2724 load_flags |= FT_LOAD_TARGET_NORMAL( (FT_Int32)((FT_RENDER_MODE_NORMAL) & 15) << 16 );
2725 load_flags |= FT_LOAD_COLOR( 1L << 20 );
2726 } else { /* info == CAIRO_SCALED_GLYPH_INFO_SURFACE */
2727 load_flags &= ~FT_LOAD_COLOR( 1L << 20 );
2728 }
2729
2730 status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
2731 scaled_glyph,
2732 face,
2733 load_flags,
2734 FALSE0,
2735 vertical_layout);
2736 if (unlikely (status)(__builtin_expect (!!(status), 0)))
18
Assuming 'status' is 0
19
Taking false branch
2737 return status;
2738
2739 glyph = face->glyph;
2740
2741 if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_OUTLINE) {
20
Assuming field 'format' is not equal to CAIRO_FT_GLYPH_TYPE_OUTLINE
21
Taking false branch
2742
2743 status = _render_glyph_outline (face, &scaled_font->ft_options.base,
2744 &surface);
2745 } else {
2746 status = _render_glyph_bitmap (face, &scaled_font->ft_options.base,
22
Calling '_render_glyph_bitmap'
2747 &surface);
2748 if (likely (status == CAIRO_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_STATUS_SUCCESS), 1)) && unscaled->have_shape) {
2749 status = _transform_glyph_bitmap (&unscaled->current_shape,
2750 &surface);
2751 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2752 cairo_surface_destroy_moz_cairo_surface_destroy (&surface->base);
2753 }
2754 }
2755
2756 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2757 return status;
2758
2759 if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
2760 /* We tried loading a color glyph and can now check if we got
2761 * a color glyph and set scaled_glyph->color_glyph
2762 * accordingly */
2763 if (pixman_image_get_format_moz_pixman_image_get_format (surface->pixman_image) == PIXMAN_a8r8g8b8 &&
2764 !pixman_image_get_component_alpha_moz_pixman_image_get_component_alpha (surface->pixman_image))
2765 {
2766 _cairo_scaled_glyph_set_color_surface (scaled_glyph,
2767 &scaled_font->base,
2768 surface,
2769 uses_foreground_color ? foreground_color : NULL((void*)0));
2770
2771 scaled_glyph->color_glyph = TRUE1;
2772 } else {
2773 /* We didn't ask for a non-color surface, but store it
2774 * anyway so we don't have to load it again. */
2775 _cairo_scaled_glyph_set_surface (scaled_glyph,
2776 &scaled_font->base,
2777 surface);
2778 scaled_glyph->color_glyph = FALSE0;
2779 status = CAIRO_INT_STATUS_UNSUPPORTED;
2780 }
2781 scaled_glyph->color_glyph_set = TRUE1;
2782 } else { /* info == CAIRO_SCALED_GLYPH_INFO_SURFACE */
2783 _cairo_scaled_glyph_set_surface (scaled_glyph,
2784 &scaled_font->base,
2785 surface);
2786 }
2787
2788 return status;
2789}
2790
2791static cairo_int_status_t
2792_cairo_ft_scaled_glyph_init_record_colr_v0_glyph (cairo_ft_scaled_font_t *scaled_font,
2793 cairo_scaled_glyph_t *scaled_glyph,
2794 FT_Face face,
2795 cairo_bool_t vertical_layout,
2796 int load_flags)
2797{
2798#ifdef FT_COLOR_H<freetype/ftcolor.h>
2799 cairo_surface_t *recording_surface;
2800 cairo_t *cr;
2801 cairo_status_t status;
2802 FT_Color *palette;
2803 unsigned int num_palette_entries;
2804 FT_LayerIterator iterator;
2805 FT_UInt layer_glyph_index;
2806 FT_UInt layer_color_index;
2807 cairo_path_fixed_t *path_fixed;
2808 cairo_path_t *path;
2809
2810 _cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette);
2811
2812 load_flags &= ~FT_LOAD_MONOCHROME( 1L << 12 );
2813 /* clear load target mode */
2814 load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(load_flags))( (FT_Int32)(((FT_Render_Mode)(( (load_flags) >> 16 ) &
15)) & 15) << 16 )
);
2815 load_flags |= FT_LOAD_TARGET_NORMAL( (FT_Int32)((FT_RENDER_MODE_NORMAL) & 15) << 16 );
2816 load_flags |= FT_LOAD_COLOR( 1L << 20 );
2817
2818 recording_surface =
2819 cairo_recording_surface_create_moz_cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL((void*)0));
2820
2821 cr = cairo_create_moz_cairo_create (recording_surface);
2822
2823 if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
2824 cairo_matrix_t scale;
2825 scale = scaled_font->base.scale;
2826 scale.x0 = scale.y0 = 0.;
2827 cairo_set_matrix_moz_cairo_set_matrix (cr, &scale);
2828 }
2829
2830 iterator.p = NULL((void*)0);
2831 while (FT_Get_Color_Glyph_Layer(face,
2832 _cairo_scaled_glyph_index (scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
2833 &layer_glyph_index,
2834 &layer_color_index,
2835 &iterator))
2836 {
2837 cairo_pattern_t *pattern;
2838 if (layer_color_index == 0xFFFF) {
2839 pattern = _cairo_pattern_create_foreground_marker ();
2840 } else {
2841 double r = 0, g = 0, b = 0, a = 1;
2842 if (layer_color_index < num_palette_entries) {
2843 FT_Color *color = &palette[layer_color_index];
2844 r = color->red / 255.0;
2845 g = color->green/ 255.0;
2846 b = color->blue / 255.0;
2847 a = color->alpha / 255.0;
2848 }
2849 pattern = cairo_pattern_create_rgba_moz_cairo_pattern_create_rgba (r, g, b, a);
2850 }
2851 cairo_set_source_moz_cairo_set_source (cr, pattern);
2852 cairo_pattern_destroy_moz_cairo_pattern_destroy (pattern);
2853
2854 if (FT_Load_Glyph (face, layer_glyph_index, load_flags) != 0) {
2855 status = CAIRO_INT_STATUS_UNSUPPORTED;
2856 goto cleanup;
2857 }
2858
2859 status = _cairo_ft_face_decompose_glyph_outline (face, &path_fixed);
2860 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2861 return status;
2862
2863 path = _cairo_path_create (path_fixed, cr);
2864 _cairo_path_fixed_destroy (path_fixed);
2865 cairo_append_path_moz_cairo_append_path(cr, path);
2866 cairo_path_destroy_moz_cairo_path_destroy (path);
2867 cairo_fill_moz_cairo_fill (cr);
2868 }
2869
2870 cleanup:
2871 cairo_destroy_moz_cairo_destroy (cr);
2872
2873 if (status) {
2874 cairo_surface_destroy_moz_cairo_surface_destroy (recording_surface);
2875 return status;
2876 }
2877
2878 _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
2879 &scaled_font->base,
2880 recording_surface,
2881 NULL((void*)0));
2882 return status;
2883#else
2884 return CAIRO_INT_STATUS_UNSUPPORTED;
2885#endif
2886}
2887
2888static cairo_int_status_t
2889_cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled_font,
2890 cairo_scaled_glyph_t *scaled_glyph,
2891 FT_Face face,
2892 const cairo_color_t *foreground_color,
2893 cairo_text_extents_t *extents)
2894{
2895#if HAVE_FT_COLR_V1
2896 cairo_status_t status = CAIRO_STATUS_SUCCESS;
2897 cairo_surface_t *recording_surface;
2898 cairo_t *cr;
2899 FT_Color *palette;
2900 unsigned int num_palette_entries;
2901 cairo_bool_t foreground_source_used = FALSE0;
2902
2903 recording_surface =
2904 cairo_recording_surface_create_moz_cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL((void*)0));
2905
2906 cairo_surface_set_device_scale (recording_surface, 1, -1);
2907
2908 cr = cairo_create_moz_cairo_create (recording_surface);
2909
2910 cairo_set_font_size_moz_cairo_set_font_size (cr, 1.0);
2911 cairo_set_font_options_moz_cairo_set_font_options (cr, &scaled_font->base.options);
2912
2913 extents->x_bearing = DOUBLE_FROM_26_6(face->bbox.xMin)((double)(face->bbox.xMin) / 64.0);
2914 extents->y_bearing = DOUBLE_FROM_26_6(face->bbox.yMin)((double)(face->bbox.yMin) / 64.0);
2915 extents->width = DOUBLE_FROM_26_6(face->bbox.xMax)((double)(face->bbox.xMax) / 64.0) - extents->x_bearing;
2916 extents->height = DOUBLE_FROM_26_6(face->bbox.yMax)((double)(face->bbox.yMax) / 64.0) - extents->y_bearing;
2917
2918 _cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette);
2919
2920 if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
2921 cairo_pattern_t *foreground_pattern = _cairo_pattern_create_solid (foreground_color);
2922 status = _cairo_render_colr_v1_glyph (face,
2923 _cairo_scaled_glyph_index (scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
2924 palette,
2925 num_palette_entries,
2926 cr,
2927 foreground_pattern,
2928 &foreground_source_used);
2929 cairo_pattern_destroy_moz_cairo_pattern_destroy (foreground_pattern);
2930 if (status == CAIRO_STATUS_SUCCESS)
2931 status = cairo_status_moz_cairo_status (cr);
2932 }
2933
2934 cairo_destroy_moz_cairo_destroy (cr);
2935
2936 if (status) {
2937 cairo_surface_destroy_moz_cairo_surface_destroy (recording_surface);
2938 scaled_glyph->color_glyph = FALSE0;
2939 scaled_glyph->color_glyph_set = TRUE1;
2940 return status;
2941 }
2942
2943 _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
2944 &scaled_font->base,
2945 recording_surface,
2946 foreground_source_used ? foreground_color : NULL((void*)0));
2947
2948 scaled_glyph->color_glyph = TRUE1;
2949 scaled_glyph->color_glyph_set = TRUE1;
2950
2951 /* get metrics */
2952
2953 /* Copied from cairo-user-font.c */
2954 cairo_matrix_t extent_scale;
2955 double extent_x_scale = 1.0;
2956 double extent_y_scale = 1.0;
2957 double snap_x_scale;
2958 double snap_y_scale;
2959 double fixed_scale, x_scale, y_scale;
2960
2961 extent_scale = scaled_font->base.scale_inverse;
2962 snap_x_scale = 1.0;
2963 snap_y_scale = 1.0;
2964 status = _cairo_matrix_compute_basis_scale_factors (&extent_scale,
2965 &x_scale, &y_scale,
2966 1);
2967 if (status == CAIRO_STATUS_SUCCESS) {
2968 if (x_scale == 0)
2969 x_scale = 1;
2970 if (y_scale == 0)
2971 y_scale = 1;
2972
2973 snap_x_scale = x_scale;
2974 snap_y_scale = y_scale;
2975
2976 /* since glyphs are pretty much 1.0x1.0, we can reduce error by
2977 * scaling to a larger square. say, 1024.x1024. */
2978 fixed_scale = 1024;
2979 x_scale /= fixed_scale;
2980 y_scale /= fixed_scale;
2981
2982 cairo_matrix_scale_moz_cairo_matrix_scale (&extent_scale, 1.0 / x_scale, 1.0 / y_scale);
2983
2984 extent_x_scale = x_scale;
2985 extent_y_scale = y_scale;
2986 }
2987
2988 {
2989 /* compute width / height */
2990 cairo_box_t bbox;
2991 double x1, y1, x2, y2;
2992 double x_scale, y_scale;
2993
2994 /* Compute extents.x/y/width/height from recording_surface,
2995 * in font space.
2996 */
2997 status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
2998 &bbox,
2999 &extent_scale);
3000 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3001 return status;
3002
3003 _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
3004
3005 x_scale = extent_x_scale;
3006 y_scale = extent_y_scale;
3007 extents->x_bearing = x1 * x_scale;
3008 extents->y_bearing = y1 * y_scale;
3009 extents->width = (x2 - x1) * x_scale;
3010 extents->height = (y2 - y1) * y_scale;
3011 }
3012
3013 if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
3014 extents->x_advance = _cairo_lround (extents->x_advance / snap_x_scale) * snap_x_scale;
3015 extents->y_advance = _cairo_lround (extents->y_advance / snap_y_scale) * snap_y_scale;
3016 }
3017
3018 return status;
3019#else
3020 return CAIRO_INT_STATUS_UNSUPPORTED;
3021#endif
3022}
3023
3024static cairo_int_status_t
3025_cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_font,
3026 cairo_scaled_glyph_t *scaled_glyph,
3027 FT_Face face,
3028 const cairo_color_t *foreground_color,
3029 cairo_text_extents_t *extents)
3030{
3031#if HAVE_FT_SVG_DOCUMENT
3032 cairo_status_t status = CAIRO_STATUS_SUCCESS;
3033 cairo_surface_t *recording_surface;
3034 cairo_t *cr;
3035 FT_SVG_Document svg_doc = face->glyph->other;
3036 char *svg_document;
3037 FT_Color *palette;
3038 unsigned int num_palette_entries;
3039 cairo_bool_t foreground_source_used = FALSE0;
3040
3041 /* Create NULL terminated SVG document */
3042 svg_document = _cairo_strndupstrndup ((const char*)svg_doc->svg_document, svg_doc->svg_document_length);
3043
3044 recording_surface =
3045 cairo_recording_surface_create_moz_cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL((void*)0));
3046
3047 cr = cairo_create_moz_cairo_create (recording_surface);
3048
3049 if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
3050 cairo_matrix_t scale;
3051 scale = scaled_font->base.scale;
3052 scale.x0 = scale.y0 = 0.;
3053 cairo_set_matrix_moz_cairo_set_matrix (cr, &scale);
3054 }
3055
3056 cairo_set_font_size_moz_cairo_set_font_size (cr, 1.0);
3057 cairo_set_font_options_moz_cairo_set_font_options (cr, &scaled_font->base.options);
3058
3059 extents->x_bearing = DOUBLE_FROM_26_6(face->bbox.xMin)((double)(face->bbox.xMin) / 64.0);
3060 extents->y_bearing = DOUBLE_FROM_26_6(face->bbox.yMin)((double)(face->bbox.yMin) / 64.0);
3061 extents->width = DOUBLE_FROM_26_6(face->bbox.xMax)((double)(face->bbox.xMax) / 64.0) - extents->x_bearing;
3062 extents->height = DOUBLE_FROM_26_6(face->bbox.yMax)((double)(face->bbox.yMax) / 64.0) - extents->y_bearing;
3063
3064 _cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette);
3065
3066 if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
3067 cairo_pattern_t *foreground_pattern = _cairo_pattern_create_solid (foreground_color);
3068 status = _cairo_render_svg_glyph (svg_document,
3069 svg_doc->start_glyph_id,
3070 svg_doc->end_glyph_id,
3071 _cairo_scaled_glyph_index(scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
3072 svg_doc->units_per_EM,
3073 palette,
3074 num_palette_entries,
3075 cr,
3076 foreground_pattern,
3077 &foreground_source_used);
3078 cairo_pattern_destroy_moz_cairo_pattern_destroy (foreground_pattern);
3079 if (status == CAIRO_STATUS_SUCCESS)
3080 status = cairo_status_moz_cairo_status (cr);
3081 }
3082
3083 cairo_destroy_moz_cairo_destroy (cr);
3084 free (svg_document);
3085
3086 if (status) {
3087 cairo_surface_destroy_moz_cairo_surface_destroy (recording_surface);
3088 scaled_glyph->color_glyph = FALSE0;
3089 scaled_glyph->color_glyph_set = TRUE1;
3090 return status;
3091 }
3092
3093 _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
3094 &scaled_font->base,
3095 recording_surface,
3096 foreground_source_used ? foreground_color : NULL((void*)0));
3097
3098 scaled_glyph->color_glyph = TRUE1;
3099 scaled_glyph->color_glyph_set = TRUE1;
3100
3101 /* get metrics */
3102
3103 /* Copied from cairo-user-font.c */
3104 cairo_matrix_t extent_scale;
3105 double extent_x_scale;
3106 double extent_y_scale;
3107 double snap_x_scale;
3108 double snap_y_scale;
3109 double fixed_scale, x_scale, y_scale;
3110
3111 extent_scale = scaled_font->base.scale_inverse;
3112 snap_x_scale = 1.0;
3113 snap_y_scale = 1.0;
3114 status = _cairo_matrix_compute_basis_scale_factors (&extent_scale,
3115 &x_scale, &y_scale,
3116 1);
3117 if (status == CAIRO_STATUS_SUCCESS) {
3118 if (x_scale == 0)
3119 x_scale = 1;
3120 if (y_scale == 0)
3121 y_scale = 1;
3122
3123 snap_x_scale = x_scale;
3124 snap_y_scale = y_scale;
3125
3126 /* since glyphs are pretty much 1.0x1.0, we can reduce error by
3127 * scaling to a larger square. say, 1024.x1024. */
3128 fixed_scale = 1024;
3129 x_scale /= fixed_scale;
3130 y_scale /= fixed_scale;
3131
3132 cairo_matrix_scale_moz_cairo_matrix_scale (&extent_scale, 1.0 / x_scale, 1.0 / y_scale);
3133
3134 extent_x_scale = x_scale;
3135 extent_y_scale = y_scale;
3136 }
3137
3138 {
3139 /* compute width / height */
3140 cairo_box_t bbox;
3141 double x1, y1, x2, y2;
3142 double x_scale, y_scale;
3143
3144 /* Compute extents.x/y/width/height from recording_surface,
3145 * in font space.
3146 */
3147 status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
3148 &bbox,
3149 &extent_scale);
3150 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3151 return status;
3152
3153 _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
3154
3155 x_scale = extent_x_scale;
3156 y_scale = extent_y_scale;
3157 extents->x_bearing = x1 * x_scale;
3158 extents->y_bearing = y1 * y_scale;
3159 extents->width = (x2 - x1) * x_scale;
3160 extents->height = (y2 - y1) * y_scale;
3161 }
3162
3163 if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
3164 extents->x_advance = _cairo_lround (extents->x_advance / snap_x_scale) * snap_x_scale;
3165 extents->y_advance = _cairo_lround (extents->y_advance / snap_y_scale) * snap_y_scale;
3166 }
3167
3168 return status;
3169#else
3170 return CAIRO_INT_STATUS_UNSUPPORTED;
3171#endif
3172}
3173
3174static cairo_int_status_t
3175_cairo_ft_scaled_glyph_init_surface_for_recording_surface (cairo_ft_scaled_font_t *scaled_font,
3176 cairo_scaled_glyph_t *scaled_glyph,
3177 const cairo_color_t *foreground_color)
3178{
3179 cairo_surface_t *surface;
3180 int width, height;
3181 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
3182 cairo_bool_t foreground_used;
3183
3184 width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
3185 _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
3186 height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
3187 _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
3188
3189 surface = cairo_image_surface_create_moz_cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
3190
3191 cairo_surface_set_device_offset_moz_cairo_surface_set_device_offset (surface,
3192 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
3193 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
3194
3195 status = _cairo_recording_surface_replay_with_foreground_color (scaled_glyph->recording_surface,
3196 surface,
3197 foreground_color,
3198 &foreground_used);
3199 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
3200 cairo_surface_destroy_moz_cairo_surface_destroy(surface);
3201 return status;
3202 }
3203
3204 _cairo_scaled_glyph_set_color_surface (scaled_glyph,
3205 &scaled_font->base,
3206 (cairo_image_surface_t *)surface,
3207 foreground_used ? foreground_color : NULL((void*)0));
3208 surface = NULL((void*)0);
3209
3210 if (surface)
3211 cairo_surface_destroy_moz_cairo_surface_destroy (surface);
3212
3213 return status;
3214}
3215
3216static void
3217_cairo_ft_scaled_glyph_get_metrics (cairo_ft_scaled_font_t *scaled_font,
3218 FT_Face face,
3219 cairo_bool_t vertical_layout,
3220 int load_flags,
3221 cairo_text_extents_t *fs_metrics)
3222{
3223 FT_Glyph_Metrics *metrics;
3224 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3225 cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF;
3226 FT_GlyphSlot glyph = face->glyph;
3227
3228 /*
3229 * Compute font-space metrics
3230 */
3231 metrics = &glyph->metrics;
3232
3233 /*
3234 * Note: Y coordinates of the horizontal bearing need to be negated.
3235 *
3236 * Scale metrics back to glyph space from the scaled glyph space returned
3237 * by FreeType
3238 *
3239 * If we want hinted metrics but aren't asking for hinted glyphs from
3240 * FreeType, then we need to do the metric hinting ourselves.
3241 */
3242
3243 if (hint_metrics && (load_flags & FT_LOAD_NO_HINTING( 1L << 1 )))
3244 {
3245 FT_Pos x1, x2;
3246 FT_Pos y1, y2;
3247 FT_Pos advance;
3248
3249 if (!vertical_layout) {
3250 x1 = (metrics->horiBearingX) & -64;
3251 x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
3252 y1 = (-metrics->horiBearingY) & -64;
3253 y2 = (-metrics->horiBearingY + metrics->height + 63) & -64;
3254
3255 advance = ((metrics->horiAdvance + 32) & -64);
3256
3257 fs_metrics->x_bearing = SCALE (DOUBLE_FROM_26_6 (x1), unscaled->x_scale)((unscaled->x_scale) == 0 ? 0.0 : (((double)(x1) / 64.0)) /
(unscaled->x_scale))
;
3258 fs_metrics->y_bearing = SCALE (DOUBLE_FROM_26_6 (y1), unscaled->y_scale)((unscaled->y_scale) == 0 ? 0.0 : (((double)(y1) / 64.0)) /
(unscaled->y_scale))
;
3259
3260 fs_metrics->width = SCALE (DOUBLE_FROM_26_6 (x2 - x1), unscaled->x_scale)((unscaled->x_scale) == 0 ? 0.0 : (((double)(x2 - x1) / 64.0
)) / (unscaled->x_scale))
;
3261 fs_metrics->height = SCALE (DOUBLE_FROM_26_6 (y2 - y1), unscaled->y_scale)((unscaled->y_scale) == 0 ? 0.0 : (((double)(y2 - y1) / 64.0
)) / (unscaled->y_scale))
;
3262
3263 fs_metrics->x_advance = SCALE (DOUBLE_FROM_26_6 (advance), unscaled->x_scale)((unscaled->x_scale) == 0 ? 0.0 : (((double)(advance) / 64.0
)) / (unscaled->x_scale))
;
3264 fs_metrics->y_advance = 0;
3265 } else {
3266 x1 = (metrics->vertBearingX) & -64;
3267 x2 = (metrics->vertBearingX + metrics->width + 63) & -64;
3268 y1 = (metrics->vertBearingY) & -64;
3269 y2 = (metrics->vertBearingY + metrics->height + 63) & -64;
3270
3271 advance = ((metrics->vertAdvance + 32) & -64);
3272
3273 fs_metrics->x_bearing = SCALE (DOUBLE_FROM_26_6 (x1), unscaled->x_scale)((unscaled->x_scale) == 0 ? 0.0 : (((double)(x1) / 64.0)) /
(unscaled->x_scale))
;
3274 fs_metrics->y_bearing = SCALE (DOUBLE_FROM_26_6 (y1), unscaled->y_scale)((unscaled->y_scale) == 0 ? 0.0 : (((double)(y1) / 64.0)) /
(unscaled->y_scale))
;
3275
3276 fs_metrics->width = SCALE (DOUBLE_FROM_26_6 (x2 - x1), unscaled->x_scale)((unscaled->x_scale) == 0 ? 0.0 : (((double)(x2 - x1) / 64.0
)) / (unscaled->x_scale))
;
3277 fs_metrics->height = SCALE (DOUBLE_FROM_26_6 (y2 - y1), unscaled->y_scale)((unscaled->y_scale) == 0 ? 0.0 : (((double)(y2 - y1) / 64.0
)) / (unscaled->y_scale))
;
3278
3279 fs_metrics->x_advance = 0;
3280 fs_metrics->y_advance = SCALE (DOUBLE_FROM_26_6 (advance), unscaled->y_scale)((unscaled->y_scale) == 0 ? 0.0 : (((double)(advance) / 64.0
)) / (unscaled->y_scale))
;
3281 }
3282 } else {
3283 fs_metrics->width = SCALE (DOUBLE_FROM_26_6 (metrics->width), unscaled->x_scale)((unscaled->x_scale) == 0 ? 0.0 : (((double)(metrics->width
) / 64.0)) / (unscaled->x_scale))
;
3284 fs_metrics->height = SCALE (DOUBLE_FROM_26_6 (metrics->height), unscaled->y_scale)((unscaled->y_scale) == 0 ? 0.0 : (((double)(metrics->height
) / 64.0)) / (unscaled->y_scale))
;
3285
3286 if (!vertical_layout) {
3287 fs_metrics->x_bearing = SCALE (DOUBLE_FROM_26_6 (metrics->horiBearingX), unscaled->x_scale)((unscaled->x_scale) == 0 ? 0.0 : (((double)(metrics->horiBearingX
) / 64.0)) / (unscaled->x_scale))
;
3288 fs_metrics->y_bearing = SCALE (DOUBLE_FROM_26_6 (-metrics->horiBearingY), unscaled->y_scale)((unscaled->y_scale) == 0 ? 0.0 : (((double)(-metrics->
horiBearingY) / 64.0)) / (unscaled->y_scale))
;
3289
3290 if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
3291 fs_metrics->x_advance = SCALE (DOUBLE_FROM_26_6 (metrics->horiAdvance), unscaled->x_scale)((unscaled->x_scale) == 0 ? 0.0 : (((double)(metrics->horiAdvance
) / 64.0)) / (unscaled->x_scale))
;
3292 else
3293 fs_metrics->x_advance = SCALE (DOUBLE_FROM_16_16 (glyph->linearHoriAdvance), unscaled->x_scale)((unscaled->x_scale) == 0 ? 0.0 : (((double)(glyph->linearHoriAdvance
) / 65536.0)) / (unscaled->x_scale))
;
3294 fs_metrics->y_advance = 0;
3295 } else {
3296 fs_metrics->x_bearing = SCALE (DOUBLE_FROM_26_6 (metrics->vertBearingX), unscaled->x_scale)((unscaled->x_scale) == 0 ? 0.0 : (((double)(metrics->vertBearingX
) / 64.0)) / (unscaled->x_scale))
;
3297 fs_metrics->y_bearing = SCALE (DOUBLE_FROM_26_6 (metrics->vertBearingY), unscaled->y_scale)((unscaled->y_scale) == 0 ? 0.0 : (((double)(metrics->vertBearingY
) / 64.0)) / (unscaled->y_scale))
;
3298
3299 fs_metrics->x_advance = 0;
3300 if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
3301 fs_metrics->y_advance = SCALE (DOUBLE_FROM_26_6 (metrics->vertAdvance), unscaled->y_scale)((unscaled->y_scale) == 0 ? 0.0 : (((double)(metrics->vertAdvance
) / 64.0)) / (unscaled->y_scale))
;
3302 else
3303 fs_metrics->y_advance = SCALE (DOUBLE_FROM_16_16 (glyph->linearVertAdvance), unscaled->y_scale)((unscaled->y_scale) == 0 ? 0.0 : (((double)(glyph->linearVertAdvance
) / 65536.0)) / (unscaled->y_scale))
;
3304 }
3305 }
3306}
3307
3308static cairo_bool_t
3309_cairo_ft_scaled_glyph_is_colr_v0 (cairo_ft_scaled_font_t *scaled_font,
3310 cairo_scaled_glyph_t *scaled_glyph,
3311 FT_Face face)
3312{
3313#ifdef FT_COLOR_H<freetype/ftcolor.h>
3314 FT_LayerIterator iterator;
3315 FT_UInt layer_glyph_index;
3316 FT_UInt layer_color_index;
3317
3318 iterator.p = NULL((void*)0);
3319 if (FT_Get_Color_Glyph_Layer(face,
3320 _cairo_scaled_glyph_index (scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
3321 &layer_glyph_index,
3322 &layer_color_index,
3323 &iterator) == 1)
3324 {
3325 return TRUE1;
3326 }
3327#endif
3328 return FALSE0;
3329}
3330
3331static cairo_bool_t
3332_cairo_ft_scaled_glyph_is_colr_v1 (cairo_ft_scaled_font_t *scaled_font,
3333 cairo_scaled_glyph_t *scaled_glyph,
3334 FT_Face face)
3335{
3336#if HAVE_FT_COLR_V1
3337 FT_OpaquePaint paint = { NULL((void*)0), 0 };
3338
3339 if (FT_Get_Color_Glyph_Paint (face,
3340 _cairo_scaled_glyph_index (scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
3341 FT_COLOR_INCLUDE_ROOT_TRANSFORM,
3342 &paint) == 1)
3343 {
3344 return TRUE1;
3345 }
3346#endif
3347 return FALSE0;
3348}
3349
3350static cairo_int_status_t
3351_cairo_ft_scaled_glyph_init_metrics (cairo_ft_scaled_font_t *scaled_font,
3352 cairo_scaled_glyph_t *scaled_glyph,
3353 FT_Face face,
3354 cairo_bool_t vertical_layout,
3355 int load_flags,
3356 const cairo_color_t *foreground_color)
3357{
3358 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
3359 cairo_text_extents_t fs_metrics;
3360 cairo_ft_glyph_private_t *glyph_priv;
3361
3362 cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF;
3363
3364 /* _cairo_ft_scaled_glyph_init_metrics() is called once the first
3365 * time a cairo_scaled_glyph_t is created. We first allocate the
3366 * cairo_ft_glyph_private_t struct and determine the glyph type.
3367 */
3368
3369 glyph_priv = _cairo_calloc (sizeof (*glyph_priv))((sizeof (*glyph_priv)) != 0 ? calloc(1,sizeof (*glyph_priv))
: ((void*)0))
;
3370 if (unlikely (glyph_priv == NULL)(__builtin_expect (!!(glyph_priv == ((void*)0)), 0)))
3371 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3372
3373 _cairo_scaled_glyph_attach_private (scaled_glyph, &glyph_priv->base,
3374 &ft_glyph_private_key,
3375 _cairo_ft_glyph_fini);
3376
3377 /* We need to load color to determine if this is a color format. */
3378 int color_flag = 0;
3379
3380 if (scaled_font->unscaled->have_color && scaled_font->base.options.color_mode != CAIRO_COLOR_MODE_NO_COLOR)
3381 color_flag = FT_LOAD_COLOR( 1L << 20 );
3382
3383 /* Ensure use_em_size = FALSE as the format (bitmap or outline)
3384 * may change with the size. */
3385 status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3386 scaled_glyph,
3387 face,
3388 load_flags | color_flag,
3389 FALSE0,
3390 vertical_layout);
3391 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3392 return status;
3393
3394 cairo_bool_t is_svg_format = FALSE0;
3395#if HAVE_FT_SVG_DOCUMENT
3396 if (face->glyph->format == FT_GLYPH_FORMAT_SVG)
3397 is_svg_format = TRUE1;
3398#endif
3399
3400 if (is_svg_format) {
3401 glyph_priv->format = CAIRO_FT_GLYPH_TYPE_SVG;
3402
3403#if defined(HAVE_FT_COLR_V1) && defined(HAVE_FT_LOAD_NO_SVG)
3404 /* Prefer COLRv1 table over SVG table due to performance reasons for now */
3405 if (_cairo_ft_scaled_glyph_is_colr_v1 (scaled_font, scaled_glyph, face)) {
3406 glyph_priv->format = CAIRO_FT_GLYPH_TYPE_COLR_V1;
3407 }
3408#endif
3409
3410 } else if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
3411 glyph_priv->format = CAIRO_FT_GLYPH_TYPE_OUTLINE;
3412 if (color_flag) {
3413 if (_cairo_ft_scaled_glyph_is_colr_v1 (scaled_font, scaled_glyph, face))
3414 glyph_priv->format = CAIRO_FT_GLYPH_TYPE_COLR_V1;
3415 else if (_cairo_ft_scaled_glyph_is_colr_v0 (scaled_font, scaled_glyph, face))
3416 glyph_priv->format = CAIRO_FT_GLYPH_TYPE_COLR_V0;
3417 }
3418 } else {
3419 /* For anything else we let FreeType render a bitmap. */
3420 glyph_priv->format = CAIRO_FT_GLYPH_TYPE_BITMAP;
3421 }
3422
3423 /* If hinting is off, load the glyph with font size set the the em size. */
3424 if (!hint_metrics) {
3425 status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3426 scaled_glyph,
3427 face,
3428 load_flags | color_flag,
3429 TRUE1,
3430 vertical_layout);
3431 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3432 return status;
3433 }
3434
3435 _cairo_ft_scaled_glyph_get_metrics (scaled_font,
3436 face,
3437 vertical_layout,
3438 load_flags,
3439 &fs_metrics);
3440
3441
3442 /* SVG and COLRv1 glyphs require the bounding box to be obtained
3443 * from the ink extents of the rendering. We need to render glyph
3444 * to a recording surface to obtain these extents. But we also
3445 * need the advance from _cairo_ft_scaled_glyph_get_metrics()
3446 * before calling this function.
3447 */
3448
3449 if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG) {
3450 status = (cairo_int_status_t)_cairo_ft_scaled_glyph_init_record_svg_glyph (scaled_font,
3451 scaled_glyph,
3452 face,
3453 foreground_color,
3454 &fs_metrics);
3455 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3456 return status;
3457 }
3458
3459 if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) {
3460 /* Restore font size if previously loaded at em_size. */
3461 if (!hint_metrics) {
3462 status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3463 scaled_glyph,
3464 face,
3465 load_flags | color_flag,
3466 FALSE0,
3467 vertical_layout);
3468 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3469 return status;
3470 }
3471
3472 status = (cairo_int_status_t)_cairo_ft_scaled_glyph_init_record_colr_v1_glyph (scaled_font,
3473 scaled_glyph,
3474 face,
3475 foreground_color,
3476 &fs_metrics);
3477 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3478 return status;
3479 }
3480
3481 _cairo_scaled_glyph_set_metrics (scaled_glyph,
3482 &scaled_font->base,
3483 &fs_metrics);
3484
3485 return status;
3486}
3487
3488static cairo_int_status_t
3489_cairo_ft_scaled_glyph_init (void *abstract_font,
3490 cairo_scaled_glyph_t *scaled_glyph,
3491 cairo_scaled_glyph_info_t info,
3492 const cairo_color_t *foreground_color)
3493{
3494 cairo_ft_scaled_font_t *scaled_font = abstract_font;
3495 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3496 FT_Face face;
3497 int load_flags = scaled_font->ft_options.load_flags;
3498 cairo_bool_t vertical_layout = FALSE0;
3499 cairo_status_t status = CAIRO_STATUS_SUCCESS;
3500 cairo_ft_glyph_private_t *glyph_priv;
3501
3502 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3503 if (!face)
1
Assuming 'face' is non-null
2
Taking false branch
3504 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3505
3506 /* Ignore global advance unconditionally */
3507 load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH( 1L << 9 );
3508
3509 if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
3
Assuming the condition is false
3510 (info & (CAIRO_SCALED_GLYPH_INFO_SURFACE |
3511 CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) == 0) {
3512 load_flags |= FT_LOAD_NO_BITMAP( 1L << 3 );
3513 }
3514
3515 /*
3516 * Don't pass FT_LOAD_VERTICAL_LAYOUT to FT_Load_Glyph here as
3517 * suggested by freetype people.
3518 */
3519 if (load_flags & FT_LOAD_VERTICAL_LAYOUT( 1L << 4 )) {
4
Assuming the condition is false
5
Taking false branch
3520 load_flags &= ~FT_LOAD_VERTICAL_LAYOUT( 1L << 4 );
3521 vertical_layout = TRUE1;
3522 }
3523
3524 /* Metrics will always be requested when a scaled glyph is created */
3525 if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
6
Assuming the condition is false
7
Taking false branch
3526 status = _cairo_ft_scaled_glyph_init_metrics (scaled_font,
3527 scaled_glyph,
3528 face,
3529 vertical_layout,
3530 load_flags,
3531 foreground_color);
3532 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3533 goto FAIL;
3534 }
3535
3536 glyph_priv = (cairo_ft_glyph_private_t *) _cairo_scaled_glyph_find_private (scaled_glyph,
3537 &ft_glyph_private_key);
3538 assert (glyph_priv != NULL)((void) sizeof (__assert_single_arg (glyph_priv != ((void*)0)
)), __extension__ ({ if (glyph_priv != ((void*)0)) ; else __assert_fail
("glyph_priv != NULL", "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c"
, 3538, __extension__ __PRETTY_FUNCTION__); }))
;
8
Assuming 'glyph_priv' is not equal to null
9
Taking true branch
3539
3540 if (info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE) {
10
Assuming the condition is false
3541 status = CAIRO_INT_STATUS_UNSUPPORTED;
3542 if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG ||
3543 glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V0 ||
3544 glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1)
3545 {
3546 status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3547 scaled_glyph,
3548 face,
3549 load_flags | FT_LOAD_COLOR( 1L << 20 ),
3550 FALSE0,
3551 vertical_layout);
3552 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3553 goto FAIL;
3554
3555 if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG) {
3556 status = _cairo_ft_scaled_glyph_init_record_svg_glyph (scaled_font,
3557 scaled_glyph,
3558 face,
3559 foreground_color,
3560 &scaled_glyph->fs_metrics);
3561 } else if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) {
3562 status = _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (scaled_font,
3563 scaled_glyph,
3564 face,
3565 foreground_color,
3566 &scaled_glyph->fs_metrics);
3567 } else if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V0) {
3568 status = _cairo_ft_scaled_glyph_init_record_colr_v0_glyph (scaled_font,
3569 scaled_glyph,
3570 face,
3571 vertical_layout,
3572 load_flags);
3573 }
3574 }
3575 if (status)
3576 goto FAIL;
3577 }
3578
3579 if ((info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) && scaled_font->base.options.color_mode != CAIRO_COLOR_MODE_NO_COLOR) {
11
Assuming the condition is false
3580 if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG ||
3581 glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1)
3582 {
3583 status = _cairo_ft_scaled_glyph_init_surface_for_recording_surface (scaled_font,
3584 scaled_glyph,
3585 foreground_color);
3586 } else {
3587 status = _cairo_ft_scaled_glyph_init_surface (scaled_font,
3588 scaled_glyph,
3589 glyph_priv,
3590 CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
3591 face,
3592 foreground_color,
3593 vertical_layout,
3594 load_flags);
3595 }
3596 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3597 goto FAIL;
3598 }
3599
3600 if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
12
Assuming the condition is true
13
Taking true branch
3601 status = _cairo_ft_scaled_glyph_init_surface (scaled_font,
14
Calling '_cairo_ft_scaled_glyph_init_surface'
3602 scaled_glyph,
3603 glyph_priv,
3604 CAIRO_SCALED_GLYPH_INFO_SURFACE,
3605 face,
3606 NULL((void*)0), /* foreground color */
3607 vertical_layout,
3608 load_flags);
3609 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3610 goto FAIL;
3611 }
3612
3613 if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
3614 cairo_path_fixed_t *path = NULL((void*)0); /* hide compiler warning */
3615
3616 /* Load non-color glyph */
3617 status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3618 scaled_glyph,
3619 face,
3620 load_flags,
3621 FALSE0,
3622 vertical_layout);
3623 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3624 goto FAIL;
3625
3626 if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
3627 status = _cairo_ft_face_decompose_glyph_outline (face, &path);
3628 else
3629 status = CAIRO_INT_STATUS_UNSUPPORTED;
3630
3631 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3632 goto FAIL;
3633
3634 _cairo_scaled_glyph_set_path (scaled_glyph,
3635 &scaled_font->base,
3636 path);
3637 }
3638 FAIL:
3639 _cairo_ft_unscaled_font_unlock_face (unscaled);
3640
3641 return status;
3642}
3643
3644static unsigned long
3645_cairo_ft_ucs4_to_index (void *abstract_font,
3646 uint32_t ucs4)
3647{
3648 cairo_ft_scaled_font_t *scaled_font = abstract_font;
3649 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3650 FT_Face face;
3651 FT_UInt index;
3652
3653 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3654 if (!face)
3655 return 0;
3656
3657#if CAIRO_HAS_FC_FONT1
3658 index = FcFreeTypeCharIndex (face, ucs4);
3659#else
3660 index = FT_Get_Char_Index (face, ucs4);
3661#endif
3662
3663 _cairo_ft_unscaled_font_unlock_face (unscaled);
3664 return index;
3665}
3666
3667static cairo_int_status_t
3668_cairo_ft_load_truetype_table (void *abstract_font,
3669 unsigned long tag,
3670 long offset,
3671 unsigned char *buffer,
3672 unsigned long *length)
3673{
3674 cairo_ft_scaled_font_t *scaled_font = abstract_font;
3675 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3676 FT_Face face;
3677 cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
3678
3679 /* We don't support the FreeType feature of loading a table
3680 * without specifying the size since this may overflow our
3681 * buffer. */
3682 assert (length != NULL)((void) sizeof (__assert_single_arg (length != ((void*)0))), __extension__
({ if (length != ((void*)0)) ; else __assert_fail ("length != NULL"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c", 3682
, __extension__ __PRETTY_FUNCTION__); }))
;
3683
3684 if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base))
3685 return CAIRO_INT_STATUS_UNSUPPORTED;
3686
3687 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3688 if (!face)
3689 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3690
3691 if (FT_IS_SFNT (face)( !!( (face)->face_flags & ( 1L << 3 ) ) )) {
3692 if (buffer == NULL((void*)0))
3693 *length = 0;
3694
3695 if (FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0)
3696 status = CAIRO_STATUS_SUCCESS;
3697 }
3698
3699 _cairo_ft_unscaled_font_unlock_face (unscaled);
3700
3701 return status;
3702}
3703
3704static cairo_int_status_t
3705_cairo_ft_index_to_ucs4(void *abstract_font,
3706 unsigned long index,
3707 uint32_t *ucs4)
3708{
3709 cairo_ft_scaled_font_t *scaled_font = abstract_font;
3710 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3711 FT_Face face;
3712 FT_ULong charcode;
3713 FT_UInt gindex;
3714
3715 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3716 if (!face)
3717 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3718
3719 *ucs4 = (uint32_t) -1;
3720 charcode = FT_Get_First_Char(face, &gindex);
3721 while (gindex != 0) {
3722 if (gindex == index) {
3723 *ucs4 = charcode;
3724 break;
3725 }
3726 charcode = FT_Get_Next_Char (face, charcode, &gindex);
3727 }
3728
3729 _cairo_ft_unscaled_font_unlock_face (unscaled);
3730
3731 return CAIRO_STATUS_SUCCESS;
3732}
3733
3734static cairo_int_status_t
3735_cairo_ft_is_synthetic (void *abstract_font,
3736 cairo_bool_t *is_synthetic)
3737{
3738 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
3739 cairo_ft_scaled_font_t *scaled_font = abstract_font;
3740 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3741 FT_Face face;
3742 FT_Error error;
3743
3744 static GetVarFunc getVar;
3745 static DoneVarFunc doneVar;
3746 static GetVarBlendCoordsFunc getVarBlendCoords;
3747
3748 static int firstTime = 1;
3749 if (firstTime) {
3750 getVar = (GetVarFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Get_MM_Var");
3751 doneVar = (DoneVarFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Done_MM_Var");
3752 getVarBlendCoords = (GetVarBlendCoordsFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Get_Var_Blend_Coordinates");
3753 firstTime = 0;
3754 }
3755
3756 if (scaled_font->ft_options.synth_flags != 0) {
3757 *is_synthetic = TRUE1;
3758 return status;
3759 }
3760
3761 *is_synthetic = FALSE0;
3762 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3763 if (!face)
3764 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3765
3766 if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS( 1L << 8 )) {
3767 FT_MM_Var *mm_var = NULL((void*)0);
3768 FT_Fixed *coords = NULL((void*)0);
3769 int num_axis;
3770 int i;
3771
3772 /* If this is an MM or variable font we can't assume the current outlines
3773 * are the same as the font tables */
3774 *is_synthetic = TRUE1;
3775
3776 error = getVar ? (*getVar) (face, &mm_var) : -1;
3777 if (error) {
3778 status = _cairo_error (_cairo_ft_to_cairo_error (error));
3779 goto cleanup;
3780 }
3781
3782 num_axis = mm_var->num_axis;
3783 coords = _cairo_malloc_ab (num_axis, sizeof(FT_Fixed));
3784 if (!coords) {
3785 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3786 goto cleanup;
3787 }
3788
3789 /* Check if the current design coordinates are the default
3790 * coordinates. In this case the current outlines match the
3791 * font tables.
3792 */
3793 if (getVarBlendCoords) {
3794 (*getVarBlendCoords) (face, num_axis, coords);
3795 *is_synthetic = FALSE0;
3796 for (i = 0; i < num_axis; i++) {
3797 if (coords[i]) {
3798 *is_synthetic = TRUE1;
3799 break;
3800 }
3801 }
3802 }
3803
3804 cleanup:
3805 free (coords);
3806 if (doneVar)
3807 (*doneVar) (face->glyph->library, mm_var);
3808 else
3809 free (mm_var);
3810 }
3811
3812 _cairo_ft_unscaled_font_unlock_face (unscaled);
3813
3814 return status;
3815}
3816
3817static cairo_int_status_t
3818_cairo_index_to_glyph_name (void *abstract_font,
3819 char **glyph_names,
3820 int num_glyph_names,
3821 unsigned long glyph_index,
3822 unsigned long *glyph_array_index)
3823{
3824 cairo_ft_scaled_font_t *scaled_font = abstract_font;
3825 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3826 FT_Face face;
3827 char buffer[256]; /* PLRM specifies max name length of 127 */
3828 FT_Error error;
3829 int i;
3830
3831 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3832 if (!face)
3833 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3834
3835 error = FT_Get_Glyph_Name (face, glyph_index, buffer, sizeof buffer);
3836
3837 _cairo_ft_unscaled_font_unlock_face (unscaled);
3838
3839 if (error != FT_Err_Ok) {
3840 /* propagate fatal errors from FreeType */
3841 if (error == FT_Err_Out_Of_Memory)
3842 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3843
3844 return CAIRO_INT_STATUS_UNSUPPORTED;
3845 }
3846
3847 /* FT first numbers the glyphs in the order they are read from the
3848 * Type 1 font. Then if .notdef is not the first glyph, the first
3849 * glyph is swapped with .notdef to ensure that .notdef is at
3850 * glyph index 0.
3851 *
3852 * As all but two glyphs in glyph_names already have the same
3853 * index as the FT glyph index, we first check if
3854 * glyph_names[glyph_index] is the name we are looking for. If not
3855 * we fall back to searching the entire array.
3856 */
3857
3858 if ((long)glyph_index < num_glyph_names &&
3859 strcmp (glyph_names[glyph_index], buffer) == 0)
3860 {
3861 *glyph_array_index = glyph_index;
3862
3863 return CAIRO_STATUS_SUCCESS;
3864 }
3865
3866 for (i = 0; i < num_glyph_names; i++) {
3867 if (strcmp (glyph_names[i], buffer) == 0) {
3868 *glyph_array_index = i;
3869
3870 return CAIRO_STATUS_SUCCESS;
3871 }
3872 }
3873
3874 return CAIRO_INT_STATUS_UNSUPPORTED;
3875}
3876
3877static cairo_bool_t
3878_ft_is_type1 (FT_Face face)
3879{
3880 const char *font_format = FT_Get_Font_Format (face);
3881 if (font_format &&
3882 (strcmp (font_format, "Type 1") == 0 ||
3883 strcmp (font_format, "CFF") == 0))
3884 {
3885 return TRUE1;
3886 }
3887
3888 return FALSE0;
3889}
3890
3891static cairo_int_status_t
3892_cairo_ft_load_type1_data (void *abstract_font,
3893 long offset,
3894 unsigned char *buffer,
3895 unsigned long *length)
3896{
3897 cairo_ft_scaled_font_t *scaled_font = abstract_font;
3898 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3899 FT_Face face;
3900 cairo_status_t status = CAIRO_STATUS_SUCCESS;
3901 unsigned long available_length;
3902 unsigned long ret;
3903
3904 assert (length != NULL)((void) sizeof (__assert_single_arg (length != ((void*)0))), __extension__
({ if (length != ((void*)0)) ; else __assert_fail ("length != NULL"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c", 3904
, __extension__ __PRETTY_FUNCTION__); }))
;
3905
3906 if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base))
3907 return CAIRO_INT_STATUS_UNSUPPORTED;
3908
3909 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3910 if (!face)
3911 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3912
3913 if (FT_IS_SFNT (face)( !!( (face)->face_flags & ( 1L << 3 ) ) )) {
3914 status = CAIRO_INT_STATUS_UNSUPPORTED;
3915 goto unlock;
3916 }
3917
3918 if (! _ft_is_type1 (face)) {
3919 status = CAIRO_INT_STATUS_UNSUPPORTED;
3920 goto unlock;
3921 }
3922
3923 available_length = MAX (face->stream->size - offset, 0)((face->stream->size - offset) > (0) ? (face->stream
->size - offset) : (0))
;
3924 if (!buffer) {
3925 *length = available_length;
3926 } else {
3927 if (*length > available_length) {
3928 status = CAIRO_INT_STATUS_UNSUPPORTED;
3929 } else if (face->stream->read != NULL((void*)0)) {
3930 /* Note that read() may be implemented as a macro, thanks POSIX!, so we
3931 * need to wrap the following usage in parentheses in order to
3932 * disambiguate it for the pre-processor - using the verbose function
3933 * pointer dereference for clarity.
3934 */
3935 ret = (* face->stream->read) (face->stream,
3936 offset,
3937 buffer,
3938 *length);
3939 if (ret != *length)
3940 status = _cairo_error (CAIRO_STATUS_READ_ERROR);
3941 } else {
3942 memcpy (buffer, face->stream->base + offset, *length);
3943 }
3944 }
3945
3946 unlock:
3947 _cairo_ft_unscaled_font_unlock_face (unscaled);
3948
3949 return status;
3950}
3951
3952static cairo_bool_t
3953_cairo_ft_has_color_glyphs (void *scaled)
3954{
3955 cairo_ft_unscaled_font_t *unscaled = ((cairo_ft_scaled_font_t *)scaled)->unscaled;
3956
3957 if (!unscaled->have_color_set) {
3958 FT_Face face;
3959 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3960 if (unlikely (face == NULL)(__builtin_expect (!!(face == ((void*)0)), 0)))
3961 return FALSE0;
3962 _cairo_ft_unscaled_font_unlock_face (unscaled);
3963 }
3964
3965 return unscaled->have_color;
3966}
3967
3968static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
3969 CAIRO_FONT_TYPE_FT,
3970 _cairo_ft_scaled_font_fini,
3971 _cairo_ft_scaled_glyph_init,
3972 NULL((void*)0), /* text_to_glyphs */
3973 _cairo_ft_ucs4_to_index,
3974 _cairo_ft_load_truetype_table,
3975 _cairo_ft_index_to_ucs4,
3976 _cairo_ft_is_synthetic,
3977 _cairo_index_to_glyph_name,
3978 _cairo_ft_load_type1_data,
3979 _cairo_ft_has_color_glyphs
3980};
3981
3982/* #cairo_ft_font_face_t */
3983
3984#if CAIRO_HAS_FC_FONT1
3985static cairo_font_face_t *
3986_cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
3987
3988static cairo_status_t
3989_cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
3990 cairo_font_face_t **font_face_out)
3991{
3992 cairo_font_face_t *font_face = (cairo_font_face_t *) &_cairo_font_face_nil;
3993 FcPattern *pattern;
3994 int fcslant;
3995 int fcweight;
3996
3997 pattern = FcPatternCreate ();
3998 if (!pattern) {
3999 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4000 return font_face->status;
4001 }
4002
4003 if (!FcPatternAddString (pattern,
4004 FC_FAMILY"family", (unsigned char *) toy_face->family))
4005 {
4006 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4007 goto FREE_PATTERN;
4008 }
4009
4010 switch (toy_face->slant)
4011 {
4012 case CAIRO_FONT_SLANT_ITALIC:
4013 fcslant = FC_SLANT_ITALIC100;
4014 break;
4015 case CAIRO_FONT_SLANT_OBLIQUE:
4016 fcslant = FC_SLANT_OBLIQUE110;
4017 break;
4018 case CAIRO_FONT_SLANT_NORMAL:
4019 default:
4020 fcslant = FC_SLANT_ROMAN0;
4021 break;
4022 }
4023
4024 if (!FcPatternAddInteger (pattern, FC_SLANT"slant", fcslant)) {
4025 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4026 goto FREE_PATTERN;
4027 }
4028
4029 switch (toy_face->weight)
4030 {
4031 case CAIRO_FONT_WEIGHT_BOLD:
4032 fcweight = FC_WEIGHT_BOLD200;
4033 break;
4034 case CAIRO_FONT_WEIGHT_NORMAL:
4035 default:
4036 fcweight = FC_WEIGHT_MEDIUM100;
4037 break;
4038 }
4039
4040 if (!FcPatternAddInteger (pattern, FC_WEIGHT"weight", fcweight)) {
4041 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4042 goto FREE_PATTERN;
4043 }
4044
4045 font_face = _cairo_ft_font_face_create_for_pattern (pattern);
4046
4047 FREE_PATTERN:
4048 FcPatternDestroy (pattern);
4049
4050 *font_face_out = font_face;
4051 return font_face->status;
4052}
4053#endif
4054
4055static cairo_bool_t
4056_cairo_ft_font_face_destroy (void *abstract_face)
4057{
4058 cairo_ft_font_face_t *font_face = abstract_face;
4059
4060 /* When destroying a face created by cairo_ft_font_face_create_for_ft_face,
4061 * we have a special "zombie" state for the face when the unscaled font
4062 * is still alive but there are no other references to a font face with
4063 * the same FT_Face.
4064 *
4065 * We go from:
4066 *
4067 * font_face ------> unscaled
4068 * <-....weak....../
4069 *
4070 * To:
4071 *
4072 * font_face <------- unscaled
4073 */
4074
4075 if (font_face->unscaled) {
4076 CAIRO_FT_LOCK (font_face->unscaled)((font_face->unscaled)->face_context ? (void)mozilla_LockSharedFTFace
((font_face->unscaled)->face_context, ((void*)0)) : (void
)pthread_mutex_lock (&((font_face->unscaled)->mutex
)))
;
4077
4078 if (font_face->unscaled->from_face &&
4079 font_face->next == NULL((void*)0) &&
4080 font_face->unscaled->faces == font_face &&
4081 CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count)_cairo_atomic_int_get (&(&font_face->unscaled->
base.ref_count)->ref_count)
> 1)
4082 {
4083 CAIRO_FT_UNLOCK (font_face->unscaled)((font_face->unscaled)->face_context ? mozilla_UnlockSharedFTFace
((font_face->unscaled)->face_context) : (void)pthread_mutex_unlock
(&((font_face->unscaled)->mutex)))
;
4084 _cairo_unscaled_font_destroy (&font_face->unscaled->base);
4085 font_face->unscaled = NULL((void*)0);
4086
4087 return FALSE0;
4088 }
4089
4090 cairo_ft_font_face_t *tmp_face = NULL((void*)0);
4091 cairo_ft_font_face_t *last_face = NULL((void*)0);
4092
4093 /* Remove face from linked list */
4094 for (tmp_face = font_face->unscaled->faces;
4095 tmp_face;
4096 tmp_face = tmp_face->next)
4097 {
4098 if (tmp_face == font_face) {
4099 if (last_face)
4100 last_face->next = tmp_face->next;
4101 else
4102 font_face->unscaled->faces = tmp_face->next;
4103 }
4104
4105 last_face = tmp_face;
4106 }
4107
4108 CAIRO_FT_UNLOCK (font_face->unscaled)((font_face->unscaled)->face_context ? mozilla_UnlockSharedFTFace
((font_face->unscaled)->face_context) : (void)pthread_mutex_unlock
(&((font_face->unscaled)->mutex)))
;
4109 _cairo_unscaled_font_destroy (&font_face->unscaled->base);
4110 font_face->unscaled = NULL((void*)0);
4111 }
4112
4113 _cairo_ft_options_fini (&font_face->ft_options);
4114
4115#if CAIRO_HAS_FC_FONT1
4116 if (font_face->pattern) {
4117 FcPatternDestroy (font_face->pattern);
4118 cairo_font_face_destroy_moz_cairo_font_face_destroy (font_face->resolved_font_face);
4119 }
4120#endif
4121
4122 return TRUE1;
4123}
4124
4125static cairo_font_face_t *
4126_cairo_ft_font_face_get_implementation (void *abstract_face,
4127 const cairo_matrix_t *font_matrix,
4128 const cairo_matrix_t *ctm,
4129 const cairo_font_options_t *options)
4130{
4131 /* The handling of font options is different depending on how the
4132 * font face was created. When the user creates a font face with
4133 * cairo_ft_font_face_create_for_ft_face(), then the load flags
4134 * passed in augment the load flags for the options. But for
4135 * cairo_ft_font_face_create_for_pattern(), the load flags are
4136 * derived from a pattern where the user has called
4137 * cairo_ft_font_options_substitute(), so *just* use those load
4138 * flags and ignore the options.
4139 */
4140
4141#if CAIRO_HAS_FC_FONT1
4142 cairo_ft_font_face_t *font_face = abstract_face;
4143
4144 /* If we have an unresolved pattern, resolve it and create
4145 * unscaled font. Otherwise, use the ones stored in font_face.
4146 */
4147 if (font_face->pattern) {
4148 cairo_font_face_t *resolved;
4149
4150 /* Cache the resolved font whilst the FcConfig remains consistent. */
4151 resolved = font_face->resolved_font_face;
4152 if (resolved != NULL((void*)0)) {
4153 if (! FcInitBringUptoDate ()) {
4154 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4155 return (cairo_font_face_t *) &_cairo_font_face_nil;
4156 }
4157
4158 if (font_face->resolved_config == FcConfigGetCurrent ())
4159 return cairo_font_face_reference_moz_cairo_font_face_reference (resolved);
4160
4161 cairo_font_face_destroy_moz_cairo_font_face_destroy (resolved);
4162 font_face->resolved_font_face = NULL((void*)0);
4163 }
4164
4165 resolved = _cairo_ft_resolve_pattern (font_face->pattern,
4166 font_matrix,
4167 ctm,
4168 options);
4169 if (unlikely (resolved->status)(__builtin_expect (!!(resolved->status), 0)))
4170 return resolved;
4171
4172 font_face->resolved_font_face = cairo_font_face_reference_moz_cairo_font_face_reference (resolved);
4173 font_face->resolved_config = FcConfigGetCurrent ();
4174
4175 return resolved;
4176 }
4177#endif
4178
4179 return abstract_face;
4180}
4181
4182static void
4183_cairo_ft_font_face_lock (void *abstract_face)
4184{
4185 cairo_ft_font_face_t *font_face = abstract_face;
4186 if (font_face->unscaled) {
4187 CAIRO_FT_LOCK (font_face->unscaled)((font_face->unscaled)->face_context ? (void)mozilla_LockSharedFTFace
((font_face->unscaled)->face_context, ((void*)0)) : (void
)pthread_mutex_lock (&((font_face->unscaled)->mutex
)))
;
4188 }
4189}
4190
4191static void
4192_cairo_ft_font_face_unlock (void *abstract_face)
4193{
4194 cairo_ft_font_face_t *font_face = abstract_face;
4195 if (font_face->unscaled) {
4196 CAIRO_FT_UNLOCK (font_face->unscaled)((font_face->unscaled)->face_context ? mozilla_UnlockSharedFTFace
((font_face->unscaled)->face_context) : (void)pthread_mutex_unlock
(&((font_face->unscaled)->mutex)))
;
4197 }
4198}
4199
4200const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
4201 CAIRO_FONT_TYPE_FT,
4202#if CAIRO_HAS_FC_FONT1
4203 _cairo_ft_font_face_create_for_toy,
4204#else
4205 NULL((void*)0),
4206#endif
4207 _cairo_ft_font_face_destroy,
4208 _cairo_ft_font_face_scaled_font_create,
4209 _cairo_ft_font_face_get_implementation,
4210/*
4211 _cairo_ft_font_face_lock,
4212 _cairo_ft_font_face_unlock
4213*/
4214};
4215
4216#if CAIRO_HAS_FC_FONT1
4217static cairo_font_face_t *
4218_cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
4219{
4220 cairo_ft_font_face_t *font_face;
4221
4222 font_face = _cairo_calloc (sizeof (cairo_ft_font_face_t))((sizeof (cairo_ft_font_face_t)) != 0 ? calloc(1,sizeof (cairo_ft_font_face_t
)) : ((void*)0))
;
4223 if (unlikely (font_face == NULL)(__builtin_expect (!!(font_face == ((void*)0)), 0))) {
4224 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4225 return (cairo_font_face_t *) &_cairo_font_face_nil;
4226 }
4227
4228 font_face->unscaled = NULL((void*)0);
4229
4230 _get_pattern_ft_options (pattern, &font_face->ft_options);
4231
4232 font_face->next = NULL((void*)0);
4233
4234 font_face->pattern = FcPatternDuplicate (pattern);
4235 if (unlikely (font_face->pattern == NULL)(__builtin_expect (!!(font_face->pattern == ((void*)0)), 0
))
) {
4236 free (font_face);
4237 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4238 return (cairo_font_face_t *) &_cairo_font_face_nil;
4239 }
4240
4241 font_face->resolved_font_face = NULL((void*)0);
4242 font_face->resolved_config = NULL((void*)0);
4243
4244 _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
4245
4246 return &font_face->base;
4247}
4248#endif
4249
4250static cairo_font_face_t *
4251_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
4252 cairo_ft_options_t *ft_options)
4253{
4254 cairo_ft_font_face_t *font_face, **prev_font_face;
4255
4256 CAIRO_FT_LOCK (unscaled)((unscaled)->face_context ? (void)mozilla_LockSharedFTFace
((unscaled)->face_context, ((void*)0)) : (void)pthread_mutex_lock
(&((unscaled)->mutex)))
;
4257
4258 /* Looked for an existing matching font face */
4259 for (font_face = unscaled->faces, prev_font_face = &unscaled->faces;
4260 font_face;
4261 prev_font_face = &font_face->next, font_face = font_face->next)
4262 {
4263 if (font_face->ft_options.load_flags == ft_options->load_flags &&
4264 font_face->ft_options.synth_flags == ft_options->synth_flags &&
4265 cairo_font_options_equal_moz_cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
4266 {
4267 if (font_face->base.status) {
4268 /* The font_face has been left in an error state, abandon it. */
4269 *prev_font_face = font_face->next;
4270 break;
4271 }
4272
4273 if (font_face->unscaled == NULL((void*)0)) {
4274 /* Resurrect this "zombie" font_face (from
4275 * _cairo_ft_font_face_destroy), switching its unscaled_font
4276 * from owner to ownee. */
4277 font_face->unscaled = unscaled;
4278 _cairo_unscaled_font_reference (&unscaled->base);
4279 } else {
4280 cairo_font_face_reference_moz_cairo_font_face_reference (&font_face->base);
4281 }
4282
4283 CAIRO_FT_UNLOCK (unscaled)((unscaled)->face_context ? mozilla_UnlockSharedFTFace((unscaled
)->face_context) : (void)pthread_mutex_unlock (&((unscaled
)->mutex)))
;
4284 return &font_face->base;
4285 }
4286 }
4287
4288 /* No match found, create a new one */
4289 font_face = _cairo_calloc (sizeof (cairo_ft_font_face_t))((sizeof (cairo_ft_font_face_t)) != 0 ? calloc(1,sizeof (cairo_ft_font_face_t
)) : ((void*)0))
;
4290 if (unlikely (!font_face)(__builtin_expect (!!(!font_face), 0))) {
4291 CAIRO_FT_UNLOCK (unscaled)((unscaled)->face_context ? mozilla_UnlockSharedFTFace((unscaled
)->face_context) : (void)pthread_mutex_unlock (&((unscaled
)->mutex)))
;
4292 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4293 return (cairo_font_face_t *)&_cairo_font_face_nil;
4294 }
4295
4296 font_face->unscaled = unscaled;
4297 _cairo_unscaled_font_reference (&unscaled->base);
4298
4299 _cairo_ft_options_init_copy (&font_face->ft_options, ft_options);
4300
4301 if (unscaled->faces && unscaled->faces->unscaled == NULL((void*)0)) {
4302 /* This "zombie" font_face (from _cairo_ft_font_face_destroy)
4303 * is no longer needed. */
4304 assert (unscaled->from_face && unscaled->faces->next == NULL)((void) sizeof (__assert_single_arg (unscaled->from_face &&
unscaled->faces->next == ((void*)0))), __extension__ (
{ if (unscaled->from_face && unscaled->faces->
next == ((void*)0)) ; else __assert_fail ("unscaled->from_face && unscaled->faces->next == NULL"
, "/root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c", 4304
, __extension__ __PRETTY_FUNCTION__); }))
;
4305 cairo_font_face_destroy_moz_cairo_font_face_destroy (&unscaled->faces->base);
4306 unscaled->faces = NULL((void*)0);
4307 }
4308
4309 font_face->next = unscaled->faces;
4310 unscaled->faces = font_face;
4311
4312#if CAIRO_HAS_FC_FONT1
4313 font_face->pattern = NULL((void*)0);
4314#endif
4315
4316 _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
4317
4318 CAIRO_FT_UNLOCK (unscaled)((unscaled)->face_context ? mozilla_UnlockSharedFTFace((unscaled
)->face_context) : (void)pthread_mutex_unlock (&((unscaled
)->mutex)))
;
4319 return &font_face->base;
4320}
4321
4322/* implement the platform-specific interface */
4323
4324#if CAIRO_HAS_FC_FONT1
4325static cairo_status_t
4326_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
4327 FcPattern *pattern)
4328{
4329 FcValue v;
4330
4331 if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
4332 {
4333 if (FcPatternGet (pattern, FC_ANTIALIAS"antialias", 0, &v) == FcResultNoMatch)
4334 {
4335 if (! FcPatternAddBool (pattern,
4336 FC_ANTIALIAS"antialias",
4337 options->antialias != CAIRO_ANTIALIAS_NONE))
4338 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4339
4340 if (options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
4341 FcPatternDel (pattern, FC_RGBA"rgba");
4342 if (! FcPatternAddInteger (pattern, FC_RGBA"rgba", FC_RGBA_NONE5))
4343 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4344 }
4345 }
4346 }
4347
4348 if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
4349 {
4350 if (FcPatternGet (pattern, FC_RGBA"rgba", 0, &v) == FcResultNoMatch)
4351 {
4352 int rgba;
4353
4354 if (options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
4355 switch (options->subpixel_order) {
4356 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
4357 case CAIRO_SUBPIXEL_ORDER_RGB:
4358 default:
4359 rgba = FC_RGBA_RGB1;
4360 break;
4361 case CAIRO_SUBPIXEL_ORDER_BGR:
4362 rgba = FC_RGBA_BGR2;
4363 break;
4364 case CAIRO_SUBPIXEL_ORDER_VRGB:
4365 rgba = FC_RGBA_VRGB3;
4366 break;
4367 case CAIRO_SUBPIXEL_ORDER_VBGR:
4368 rgba = FC_RGBA_VBGR4;
4369 break;
4370 }
4371 } else {
4372 rgba = FC_RGBA_NONE5;
4373 }
4374
4375 if (! FcPatternAddInteger (pattern, FC_RGBA"rgba", rgba))
4376 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4377 }
4378 }
4379
4380 if (options->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
4381 {
4382 if (FcPatternGet (pattern, FC_LCD_FILTER"lcdfilter", 0, &v) == FcResultNoMatch)
4383 {
4384 int lcd_filter;
4385
4386 switch (options->lcd_filter) {
4387 case CAIRO_LCD_FILTER_NONE:
4388 lcd_filter = FT_LCD_FILTER_NONE;
4389 break;
4390 case CAIRO_LCD_FILTER_INTRA_PIXEL:
4391 lcd_filter = FT_LCD_FILTER_LEGACY;
4392 break;
4393 case CAIRO_LCD_FILTER_FIR3:
4394 lcd_filter = FT_LCD_FILTER_LIGHT;
4395 break;
4396 default:
4397 case CAIRO_LCD_FILTER_DEFAULT:
4398 case CAIRO_LCD_FILTER_FIR5:
4399 lcd_filter = FT_LCD_FILTER_DEFAULT;
4400 break;
4401 }
4402
4403 if (! FcPatternAddInteger (pattern, FC_LCD_FILTER"lcdfilter", lcd_filter))
4404 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4405 }
4406 }
4407
4408 if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
4409 {
4410 if (FcPatternGet (pattern, FC_HINTING"hinting", 0, &v) == FcResultNoMatch)
4411 {
4412 if (! FcPatternAddBool (pattern,
4413 FC_HINTING"hinting",
4414 options->hint_style != CAIRO_HINT_STYLE_NONE))
4415 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4416 }
4417
4418 if (FcPatternGet (pattern, FC_HINT_STYLE"hintstyle", 0, &v) == FcResultNoMatch)
4419 {
4420 int hint_style;
4421
4422 switch (options->hint_style) {
4423 case CAIRO_HINT_STYLE_NONE:
4424 hint_style = FC_HINT_NONE0;
4425 break;
4426 case CAIRO_HINT_STYLE_SLIGHT:
4427 hint_style = FC_HINT_SLIGHT1;
4428 break;
4429 case CAIRO_HINT_STYLE_MEDIUM:
4430 hint_style = FC_HINT_MEDIUM2;
4431 break;
4432 case CAIRO_HINT_STYLE_FULL:
4433 case CAIRO_HINT_STYLE_DEFAULT:
4434 default:
4435 hint_style = FC_HINT_FULL3;
4436 break;
4437 }
4438
4439 if (! FcPatternAddInteger (pattern, FC_HINT_STYLE"hintstyle", hint_style))
4440 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4441 }
4442 }
4443
4444 return CAIRO_STATUS_SUCCESS;
4445}
4446
4447/**
4448 * cairo_ft_font_options_substitute:
4449 * @options: a #cairo_font_options_t object
4450 * @pattern: an existing #FcPattern
4451 *
4452 * Add options to a #FcPattern based on a #cairo_font_options_t font
4453 * options object. Options that are already in the pattern, are not overridden,
4454 * so you should call this function after calling FcConfigSubstitute() (the
4455 * user's settings should override options based on the surface type), but
4456 * before calling FcDefaultSubstitute().
4457 *
4458 * Since: 1.0
4459 **/
4460void
4461cairo_ft_font_options_substitute_moz_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
4462 FcPattern *pattern)
4463{
4464 if (cairo_font_options_status_moz_cairo_font_options_status ((cairo_font_options_t *) options))
4465 return;
4466
4467 _cairo_ft_font_options_substitute (options, pattern);
4468}
4469
4470static cairo_font_face_t *
4471_cairo_ft_resolve_pattern (FcPattern *pattern,
4472 const cairo_matrix_t *font_matrix,
4473 const cairo_matrix_t *ctm,
4474 const cairo_font_options_t *font_options)
4475{
4476 cairo_status_t status;
4477
4478 cairo_matrix_t scale;
4479 FcPattern *resolved;
4480 cairo_ft_font_transform_t sf;
4481 FcResult result;
4482 cairo_ft_unscaled_font_t *unscaled;
4483 cairo_ft_options_t ft_options;
4484 cairo_font_face_t *font_face;
4485
4486 scale = *ctm;
4487 scale.x0 = scale.y0 = 0;
4488 cairo_matrix_multiply_moz_cairo_matrix_multiply (&scale,
4489 font_matrix,
4490 &scale);
4491
4492 status = _compute_transform (&sf, &scale, NULL((void*)0));
4493 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4494 return (cairo_font_face_t *)&_cairo_font_face_nil;
4495
4496 pattern = FcPatternDuplicate (pattern);
4497 if (pattern == NULL((void*)0))
4498 return (cairo_font_face_t *)&_cairo_font_face_nil;
4499
4500 if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE"pixelsize", sf.y_scale)) {
4501 font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4502 goto FREE_PATTERN;
4503 }
4504
4505 if (! FcConfigSubstitute (NULL((void*)0), pattern, FcMatchPattern)) {
4506 font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4507 goto FREE_PATTERN;
4508 }
4509
4510 status = _cairo_ft_font_options_substitute (font_options, pattern);
4511 if (status) {
4512 font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4513 goto FREE_PATTERN;
4514 }
4515
4516 FcDefaultSubstitute (pattern);
4517
4518 status = _cairo_ft_unscaled_font_create_for_pattern (pattern, &unscaled);
4519 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
4520 font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4521 goto FREE_PATTERN;
4522 }
4523
4524 if (unscaled == NULL((void*)0)) {
4525 resolved = FcFontMatch (NULL((void*)0), pattern, &result);
4526 if (!resolved) {
4527 /* We failed to find any font. Substitute twin so that the user can
4528 * see something (and hopefully recognise that the font is missing)
4529 * and not just receive a NO_MEMORY error during rendering.
4530 */
4531 font_face = _cairo_font_face_twin_create_fallback ();
4532 goto FREE_PATTERN;
4533 }
4534
4535 status = _cairo_ft_unscaled_font_create_for_pattern (resolved, &unscaled);
4536 if (unlikely (status || unscaled == NULL)(__builtin_expect (!!(status || unscaled == ((void*)0)), 0))) {
4537 font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4538 goto FREE_RESOLVED;
4539 }
4540 } else
4541 resolved = pattern;
4542
4543 _get_pattern_ft_options (resolved, &ft_options);
4544 font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
4545 _cairo_ft_options_fini (&ft_options);
4546 _cairo_unscaled_font_destroy (&unscaled->base);
4547
4548FREE_RESOLVED:
4549 if (resolved != pattern)
4550 FcPatternDestroy (resolved);
4551
4552FREE_PATTERN:
4553 FcPatternDestroy (pattern);
4554
4555 return font_face;
4556}
4557
4558/**
4559 * cairo_ft_font_face_create_for_pattern:
4560 * @pattern: A fontconfig pattern. Cairo makes a copy of the pattern
4561 * if it needs to. You are free to modify or free @pattern after this call.
4562 *
4563 * Creates a new font face for the FreeType font backend based on a
4564 * fontconfig pattern. This font can then be used with
4565 * cairo_set_font_face() or cairo_scaled_font_create(). The
4566 * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
4567 * also for the FreeType backend and can be used with functions such
4568 * as cairo_ft_scaled_font_lock_face().
4569 *
4570 * Font rendering options are represented both here and when you
4571 * call cairo_scaled_font_create(). Font options that have a representation
4572 * in a #FcPattern must be passed in here; to modify #FcPattern
4573 * appropriately to reflect the options in a #cairo_font_options_t, call
4574 * cairo_ft_font_options_substitute().
4575 *
4576 * The pattern's FC_FT_FACE element is inspected first and if that is set,
4577 * that will be the FreeType font face associated with the returned cairo
4578 * font face. Otherwise the FC_FILE element is checked. If it's set,
4579 * that and the value of the FC_INDEX element (defaults to zero) of @pattern
4580 * are used to load a font face from file.
4581 *
4582 * If both steps from the previous paragraph fails, @pattern will be passed
4583 * to FcConfigSubstitute, FcDefaultSubstitute, and finally FcFontMatch,
4584 * and the resulting font pattern is used.
4585 *
4586 * If the FC_FT_FACE element of @pattern is set, the user is responsible
4587 * for making sure that the referenced FT_Face remains valid for the life
4588 * time of the returned #cairo_font_face_t. See
4589 * cairo_ft_font_face_create_for_ft_face() for an example of how to couple
4590 * the life time of the FT_Face to that of the cairo font-face.
4591 *
4592 * Return value: a newly created #cairo_font_face_t. Free with
4593 * cairo_font_face_destroy() when you are done using it.
4594 *
4595 * Since: 1.0
4596 **/
4597cairo_font_face_t *
4598cairo_ft_font_face_create_for_pattern_moz_cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
4599{
4600 cairo_ft_unscaled_font_t *unscaled;
4601 cairo_font_face_t *font_face;
4602 cairo_ft_options_t ft_options;
4603 cairo_status_t status;
4604
4605 status = _cairo_ft_unscaled_font_create_for_pattern (pattern, &unscaled);
4606 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
4607 if (status == CAIRO_STATUS_FILE_NOT_FOUND)
4608 return (cairo_font_face_t *) &_cairo_font_face_nil_file_not_found;
4609 else
4610 return (cairo_font_face_t *) &_cairo_font_face_nil;
4611 }
4612 if (unlikely (unscaled == NULL)(__builtin_expect (!!(unscaled == ((void*)0)), 0))) {
4613 /* Store the pattern. We will resolve it and create unscaled
4614 * font when creating scaled fonts */
4615 return _cairo_ft_font_face_create_for_pattern (pattern);
4616 }
4617
4618 _get_pattern_ft_options (pattern, &ft_options);
4619 font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
4620 _cairo_ft_options_fini (&ft_options);
4621 _cairo_unscaled_font_destroy (&unscaled->base);
4622
4623 return font_face;
4624}
4625#endif
4626
4627/**
4628 * cairo_ft_font_face_create_for_ft_face:
4629 * @face: A FreeType face object, already opened. This must
4630 * be kept around until the face's ref_count drops to
4631 * zero and it is freed. Since the face may be referenced
4632 * internally to Cairo, the best way to determine when it
4633 * is safe to free the face is to pass a
4634 * #cairo_destroy_func_t to cairo_font_face_set_user_data()
4635 * @load_flags: flags to pass to FT_Load_Glyph when loading
4636 * glyphs from the font. These flags are OR'ed together with
4637 * the flags derived from the #cairo_font_options_t passed
4638 * to cairo_scaled_font_create(), so only a few values such
4639 * as %FT_LOAD_VERTICAL_LAYOUT, and %FT_LOAD_FORCE_AUTOHINT
4640 * are useful. You should not pass any of the flags affecting
4641 * the load target, such as %FT_LOAD_TARGET_LIGHT.
4642 *
4643 * Creates a new font face for the FreeType font backend from a
4644 * pre-opened FreeType face. This font can then be used with
4645 * cairo_set_font_face() or cairo_scaled_font_create(). The
4646 * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
4647 * also for the FreeType backend and can be used with functions such
4648 * as cairo_ft_scaled_font_lock_face(). Note that Cairo may keep a reference
4649 * to the FT_Face alive in a font-cache and the exact lifetime of the reference
4650 * depends highly upon the exact usage pattern and is subject to external
4651 * factors. You must not call FT_Done_Face() before the last reference to the
4652 * #cairo_font_face_t has been dropped.
4653 *
4654 * As an example, below is how one might correctly couple the lifetime of
4655 * the FreeType face object to the #cairo_font_face_t.
4656 *
4657 * <informalexample><programlisting>
4658 * static const cairo_user_data_key_t key;
4659 *
4660 * font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
4661 * status = cairo_font_face_set_user_data (font_face, &key,
4662 * ft_face, (cairo_destroy_func_t) FT_Done_Face);
4663 * if (status) {
4664 * cairo_font_face_destroy (font_face);
4665 * FT_Done_Face (ft_face);
4666 * return ERROR;
4667 * }
4668 * </programlisting></informalexample>
4669 *
4670 * Return value: a newly created #cairo_font_face_t. Free with
4671 * cairo_font_face_destroy() when you are done using it.
4672 *
4673 * Since: 1.0
4674 **/
4675cairo_font_face_t *
4676cairo_ft_font_face_create_for_ft_face_moz_cairo_ft_font_face_create_for_ft_face (FT_Face face,
4677 int load_flags,
4678 unsigned int synth_flags,
4679 void *face_context)
4680{
4681 cairo_ft_unscaled_font_t *unscaled;
4682 cairo_font_face_t *font_face;
4683 cairo_ft_options_t ft_options;
4684 cairo_status_t status;
4685
4686 status = _cairo_ft_unscaled_font_create_from_face (face, face_context,
4687 &unscaled);
4688 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4689 return (cairo_font_face_t *)&_cairo_font_face_nil;
4690
4691 ft_options.load_flags = load_flags;
4692 ft_options.synth_flags = synth_flags;
4693 _cairo_font_options_init_default (&ft_options.base);
4694
4695 font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
4696 _cairo_unscaled_font_destroy (&unscaled->base);
4697
4698 return font_face;
4699}
4700
4701/**
4702 * cairo_ft_font_face_set_synthesize:
4703 * @font_face: The #cairo_ft_font_face_t object to modify
4704 * @synth_flags: the set of synthesis options to enable
4705 *
4706 * FreeType provides the ability to synthesize different glyphs from a base
4707 * font, which is useful if you lack those glyphs from a true bold or oblique
4708 * font. See also #cairo_ft_synthesize_t.
4709 *
4710 * Since: 1.12
4711 **/
4712void
4713cairo_ft_font_face_set_synthesize_moz_cairo_ft_font_face_set_synthesize (cairo_font_face_t *font_face,
4714 unsigned int synth_flags)
4715{
4716 cairo_ft_font_face_t *ft;
4717
4718 if (font_face->backend->type != CAIRO_FONT_TYPE_FT)
4719 return;
4720
4721 ft = (cairo_ft_font_face_t *) font_face;
4722 ft->ft_options.synth_flags |= synth_flags;
4723}
4724
4725/**
4726 * cairo_ft_font_face_unset_synthesize:
4727 * @font_face: The #cairo_ft_font_face_t object to modify
4728 * @synth_flags: the set of synthesis options to disable
4729 *
4730 * See cairo_ft_font_face_set_synthesize().
4731 *
4732 * Since: 1.12
4733 **/
4734void
4735cairo_ft_font_face_unset_synthesize (cairo_font_face_t *font_face,
4736 unsigned int synth_flags)
4737{
4738 cairo_ft_font_face_t *ft;
4739
4740 if (font_face->backend->type != CAIRO_FONT_TYPE_FT)
4741 return;
4742
4743 ft = (cairo_ft_font_face_t *) font_face;
4744 ft->ft_options.synth_flags &= ~synth_flags;
4745}
4746
4747/**
4748 * cairo_ft_font_face_get_synthesize:
4749 * @font_face: The #cairo_ft_font_face_t object to query
4750 *
4751 * See #cairo_ft_synthesize_t.
4752 *
4753 * Returns: the current set of synthesis options.
4754 *
4755 * Since: 1.12
4756 **/
4757unsigned int
4758cairo_ft_font_face_get_synthesize (cairo_font_face_t *font_face)
4759{
4760 cairo_ft_font_face_t *ft;
4761
4762 if (font_face->backend->type != CAIRO_FONT_TYPE_FT)
4763 return 0;
4764
4765 ft = (cairo_ft_font_face_t *) font_face;
4766 return ft->ft_options.synth_flags;
4767}
4768
4769/**
4770 * cairo_ft_scaled_font_lock_face:
4771 * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
4772 * object can be created by calling cairo_scaled_font_create() on a
4773 * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
4774 * cairo_ft_font_face_create_for_ft_face()).
4775 *
4776 * cairo_ft_scaled_font_lock_face() gets the #FT_Face object from a FreeType
4777 * backend font and scales it appropriately for the font and applies OpenType
4778 * font variations if applicable. You must
4779 * release the face with cairo_ft_scaled_font_unlock_face()
4780 * when you are done using it. Since the #FT_Face object can be
4781 * shared between multiple #cairo_scaled_font_t objects, you must not
4782 * lock any other font objects until you unlock this one. A count is
4783 * kept of the number of times cairo_ft_scaled_font_lock_face() is
4784 * called. cairo_ft_scaled_font_unlock_face() must be called the same number
4785 * of times.
4786 *
4787 * You must be careful when using this function in a library or in a
4788 * threaded application, because freetype's design makes it unsafe to
4789 * call freetype functions simultaneously from multiple threads, (even
4790 * if using distinct FT_Face objects). Because of this, application
4791 * code that acquires an FT_Face object with this call must add its
4792 * own locking to protect any use of that object, (and which also must
4793 * protect any other calls into cairo as almost any cairo function
4794 * might result in a call into the freetype library).
4795 *
4796 * Return value: The #FT_Face object for @font, scaled appropriately,
4797 * or %NULL if @scaled_font is in an error state (see
4798 * cairo_scaled_font_status()) or there is insufficient memory.
4799 *
4800 * Since: 1.0
4801 **/
4802FT_Face
4803cairo_ft_scaled_font_lock_face_moz_cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
4804{
4805 cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
4806 FT_Face face;
4807 cairo_status_t status;
4808
4809 if (! _cairo_scaled_font_is_ft (abstract_font)) {
4810 _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_FONT_TYPE_MISMATCH
); (void) status__; } while (0)
;
4811 return NULL((void*)0);
4812 }
4813
4814 if (scaled_font->base.status)
4815 return NULL((void*)0);
4816
4817 face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
4818 if (unlikely (face == NULL)(__builtin_expect (!!(face == ((void*)0)), 0))) {
4819 status = _cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
4820 return NULL((void*)0);
4821 }
4822
4823 status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
4824 &scaled_font->base.scale);
4825 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
4826 _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
4827 status = _cairo_scaled_font_set_error (&scaled_font->base, status);
4828 return NULL((void*)0);
4829 }
4830
4831 cairo_ft_apply_variations (face, scaled_font);
4832
4833 /* Note: We deliberately release the unscaled font's mutex here,
4834 * so that we are not holding a lock across two separate calls to
4835 * cairo function, (which would give the application some
4836 * opportunity for creating deadlock. This is obviously unsafe,
4837 * but as documented, the user must add manual locking when using
4838 * this function. */
4839 CAIRO_FT_UNLOCK (scaled_font->unscaled)((scaled_font->unscaled)->face_context ? mozilla_UnlockSharedFTFace
((scaled_font->unscaled)->face_context) : (void)pthread_mutex_unlock
(&((scaled_font->unscaled)->mutex)))
;
4840
4841 return face;
4842}
4843
4844/**
4845 * cairo_ft_scaled_font_unlock_face:
4846 * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
4847 * object can be created by calling cairo_scaled_font_create() on a
4848 * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
4849 * cairo_ft_font_face_create_for_ft_face()).
4850 *
4851 * Releases a face obtained with cairo_ft_scaled_font_lock_face().
4852 *
4853 * Since: 1.0
4854 **/
4855void
4856cairo_ft_scaled_font_unlock_face_moz_cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
4857{
4858 cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
4859
4860 if (! _cairo_scaled_font_is_ft (abstract_font)) {
4861 _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_FONT_TYPE_MISMATCH
); (void) status__; } while (0)
;
4862 return;
4863 }
4864
4865 if (scaled_font->base.status)
4866 return;
4867
4868 /* Note: We released the unscaled font's mutex at the end of
4869 * cairo_ft_scaled_font_lock_face, so we have to acquire it again
4870 * as _cairo_ft_unscaled_font_unlock_face expects it to be held
4871 * when we call into it. */
4872 CAIRO_FT_LOCK (scaled_font->unscaled)((scaled_font->unscaled)->face_context ? (void)mozilla_LockSharedFTFace
((scaled_font->unscaled)->face_context, ((void*)0)) : (
void)pthread_mutex_lock (&((scaled_font->unscaled)->
mutex)))
;
4873
4874 _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
4875}
4876
4877static cairo_bool_t
4878_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font)
4879{
4880 cairo_ft_scaled_font_t *ft_scaled_font;
4881
4882 if (!_cairo_scaled_font_is_ft (scaled_font))
4883 return FALSE0;
4884
4885 ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
4886 if (ft_scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT( 1L << 4 ))
4887 return TRUE1;
4888 return FALSE0;
4889}
4890
4891unsigned int
4892_cairo_ft_scaled_font_get_load_flags (cairo_scaled_font_t *scaled_font)
4893{
4894 cairo_ft_scaled_font_t *ft_scaled_font;
4895
4896 if (! _cairo_scaled_font_is_ft (scaled_font))
4897 return 0;
4898
4899 ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
4900 return ft_scaled_font->ft_options.load_flags;
4901}
4902
4903void
4904_cairo_ft_font_reset_static_data (void)
4905{
4906 _cairo_ft_unscaled_font_map_destroy ();
4907}