Bug Summary

File:root/firefox-clang/gfx/cairo/cairo/src/cairo-ft-font.c
Warning:line 4614, column 9
The left operand of '==' is a garbage 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 -U NDEBUG -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-10-17-231001-351276-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)
3
Assuming 'ret' is not equal to FcResultMatch
4
Taking false branch
690 goto DONE;
691 if (ret == FcResultOutOfMemory)
5
Assuming 'ret' is equal to FcResultOutOfMemory
6
Taking true branch
692 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
7
Returning without writing to '*out'
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) {
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) {
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 /* tmp is our locally-managed view of bitmap, which belongs to
1447 * the glyph slot. Only access and free tmp. */
1448 stride = tmp.pitch;
1449 data = _cairo_malloc_ab (height, stride);
1450 if (!data) {
1451 FT_Bitmap_Done( library, &tmp );
1452 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1453 }
1454
1455 if (tmp.num_grays != 256)
1456 {
1457 unsigned int x, y;
1458 unsigned int mul = 255 / (tmp.num_grays - 1);
1459 FT_Byte *p = tmp.buffer;
1460 for (y = 0; y < height; y++) {
1461 for (x = 0; x < width; x++)
1462 p[x] *= mul;
1463 p += tmp.pitch;
1464 }
1465 }
1466
1467 memcpy (data, tmp.buffer, (size_t)stride * height);
1468 FT_Bitmap_Done( library, &tmp );
1469 break;
1470 }
1471 /* fall through */
1472 /* These could be triggered by very rare types of TrueType fonts */
1473 default:
1474 if (own_buffer)
1475 free (bitmap->buffer);
1476 return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
1477 }
1478
1479 /* XXX */
1480 *surface = image = (cairo_image_surface_t *)
1481 cairo_image_surface_create_for_data_moz_cairo_image_surface_create_for_data (data,
1482 format,
1483 width, height, stride);
1484 if (image->base.status) {
1485 free (data);
1486 return (*surface)->base.status;
1487 }
1488
1489 if (component_alpha)
1490 pixman_image_set_component_alpha_moz_pixman_image_set_component_alpha (image->pixman_image, TRUE1);
1491
1492 _cairo_image_surface_assume_ownership_of_data (image);
1493
1494 _cairo_debug_check_image_surface_is_defined (&image->base);
1495
1496 return CAIRO_STATUS_SUCCESS;
1497}
1498
1499/* Converts an outline FT_GlyphSlot into an image
1500 *
1501 * This could go through _render_glyph_bitmap as well, letting
1502 * FreeType convert the outline to a bitmap, but doing it ourselves
1503 * has two minor advantages: first, we save a copy of the bitmap
1504 * buffer: we can directly use the buffer that FreeType renders
1505 * into.
1506 *
1507 * Second, it may help when we add support for subpixel
1508 * rendering: the Xft code does it this way. (Keith thinks that
1509 * it may also be possible to get the subpixel rendering with
1510 * FT_Render_Glyph: something worth looking into in more detail
1511 * when we add subpixel support. If so, we may want to eliminate
1512 * this version of the code path entirely.
1513 */
1514static cairo_status_t
1515_render_glyph_outline (FT_Face face,
1516 cairo_font_options_t *font_options,
1517 cairo_image_surface_t **surface)
1518{
1519 cairo_subpixel_order_t rgba = CAIRO_SUBPIXEL_ORDER_DEFAULT;
1520 int lcd_filter = FT_LCD_FILTER_DEFAULT;
1521 FT_GlyphSlot glyphslot = face->glyph;
1522 FT_Outline *outline = &glyphslot->outline;
1523 FT_Bitmap bitmap;
1524 FT_BBox cbox;
1525 unsigned int width, height;
1526 cairo_status_t status;
1527 FT_Error error;
1528 FT_Library library = glyphslot->library;
1529 FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
1530
1531 switch (font_options->antialias) {
1532 case CAIRO_ANTIALIAS_NONE:
1533 render_mode = FT_RENDER_MODE_MONO;
1534 break;
1535
1536 case CAIRO_ANTIALIAS_SUBPIXEL:
1537 case CAIRO_ANTIALIAS_BEST:
1538 switch (font_options->subpixel_order) {
1539 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1540 case CAIRO_SUBPIXEL_ORDER_RGB:
1541 case CAIRO_SUBPIXEL_ORDER_BGR:
1542 render_mode = FT_RENDER_MODE_LCD;
1543 break;
1544
1545 case CAIRO_SUBPIXEL_ORDER_VRGB:
1546 case CAIRO_SUBPIXEL_ORDER_VBGR:
1547 render_mode = FT_RENDER_MODE_LCD_V;
1548 break;
1549 }
1550
1551 switch (font_options->lcd_filter) {
1552 case CAIRO_LCD_FILTER_NONE:
1553 lcd_filter = FT_LCD_FILTER_NONE;
1554 break;
1555 case CAIRO_LCD_FILTER_INTRA_PIXEL:
1556 lcd_filter = FT_LCD_FILTER_LEGACY;
1557 break;
1558 case CAIRO_LCD_FILTER_FIR3:
1559 lcd_filter = FT_LCD_FILTER_LIGHT;
1560 break;
1561 case CAIRO_LCD_FILTER_DEFAULT:
1562 case CAIRO_LCD_FILTER_FIR5:
1563 lcd_filter = FT_LCD_FILTER_DEFAULT;
1564 break;
1565 }
1566
1567 break;
1568
1569 case CAIRO_ANTIALIAS_DEFAULT:
1570 case CAIRO_ANTIALIAS_GRAY:
1571 case CAIRO_ANTIALIAS_GOOD:
1572 case CAIRO_ANTIALIAS_FAST:
1573 render_mode = FT_RENDER_MODE_NORMAL;
1574 }
1575
1576 FT_Outline_Get_CBox (outline, &cbox);
1577
1578 cbox.xMin &= -64;
1579 cbox.yMin &= -64;
1580 cbox.xMax = (cbox.xMax + 63) & -64;
1581 cbox.yMax = (cbox.yMax + 63) & -64;
1582
1583 width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
1584 height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
1585
1586 if (width * height == 0) {
1587 cairo_format_t format;
1588 /* Looks like fb handles zero-sized images just fine */
1589 switch (render_mode) {
1590 case FT_RENDER_MODE_MONO:
1591 format = CAIRO_FORMAT_A1;
1592 break;
1593 case FT_RENDER_MODE_LCD:
1594 case FT_RENDER_MODE_LCD_V:
1595 format= CAIRO_FORMAT_ARGB32;
1596 break;
1597 case FT_RENDER_MODE_LIGHT:
1598 case FT_RENDER_MODE_NORMAL:
1599 case FT_RENDER_MODE_MAX:
1600#if HAVE_FT_RENDER_MODE_SDF1
1601 case FT_RENDER_MODE_SDF:
1602#endif
1603 default:
1604 format = CAIRO_FORMAT_A8;
1605 break;
1606 }
1607
1608 (*surface) = (cairo_image_surface_t *)
1609 cairo_image_surface_create_for_data_moz_cairo_image_surface_create_for_data (NULL((void*)0), format, 0, 0, 0);
1610 pixman_image_set_component_alpha_moz_pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE1);
1611 if ((*surface)->base.status)
1612 return (*surface)->base.status;
1613 } else {
1614
1615 int bitmap_size;
1616
1617 switch (render_mode) {
1618 case FT_RENDER_MODE_LCD:
1619 if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR)
1620 rgba = CAIRO_SUBPIXEL_ORDER_BGR;
1621 else
1622 rgba = CAIRO_SUBPIXEL_ORDER_RGB;
1623 break;
1624
1625 case FT_RENDER_MODE_LCD_V:
1626 if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR)
1627 rgba = CAIRO_SUBPIXEL_ORDER_VBGR;
1628 else
1629 rgba = CAIRO_SUBPIXEL_ORDER_VRGB;
1630 break;
1631
1632 case FT_RENDER_MODE_MONO:
1633 case FT_RENDER_MODE_LIGHT:
1634 case FT_RENDER_MODE_NORMAL:
1635 case FT_RENDER_MODE_MAX:
1636#if HAVE_FT_RENDER_MODE_SDF1
1637 case FT_RENDER_MODE_SDF:
1638#endif
1639 default:
1640 break;
1641 }
1642
1643 FT_Library_SetLcdFilter (library, lcd_filter);
1644 error = FT_Render_Glyph (face->glyph, render_mode);
1645
1646 FT_Library_SetLcdFilter (library, FT_LCD_FILTER_NONE);
1647 if (error)
1648 return _cairo_error (_cairo_ft_to_cairo_error (error));
1649
1650 bitmap_size = _compute_xrender_bitmap_size (&bitmap,
1651 face->glyph,
1652 render_mode);
1653 if (bitmap_size < 0)
1654 return _cairo_error (CAIRO_STATUS_INVALID_FORMAT);
1655
1656 bitmap.buffer = _cairo_calloc (bitmap_size)((bitmap_size) != 0 ? calloc(1,bitmap_size) : ((void*)0));
1657 if (bitmap.buffer == NULL((void*)0))
1658 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1659
1660 _fill_xrender_bitmap (&bitmap, face->glyph, render_mode,
1661 (rgba == CAIRO_SUBPIXEL_ORDER_BGR || rgba == CAIRO_SUBPIXEL_ORDER_VBGR));
1662
1663 /* Note:
1664 * _get_bitmap_surface will free bitmap.buffer if there is an error
1665 */
1666 status = _get_bitmap_surface (&bitmap, NULL((void*)0), TRUE1, font_options, surface);
1667 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1668 return status;
1669
1670 /* Note: the font's coordinate system is upside down from ours, so the
1671 * Y coordinate of the control box needs to be negated. Moreover, device
1672 * offsets are position of glyph origin relative to top left while xMin
1673 * and yMax are offsets of top left relative to origin. Another negation.
1674 */
1675 cairo_surface_set_device_offset_moz_cairo_surface_set_device_offset (&(*surface)->base,
1676 (double)-glyphslot->bitmap_left,
1677 (double)+glyphslot->bitmap_top);
1678 }
1679
1680 return CAIRO_STATUS_SUCCESS;
1681}
1682
1683/* Converts a bitmap (or other) FT_GlyphSlot into an image */
1684static cairo_status_t
1685_render_glyph_bitmap (FT_Face face,
1686 cairo_font_options_t *font_options,
1687 cairo_image_surface_t **surface)
1688{
1689 FT_GlyphSlot glyphslot = face->glyph;
1690 cairo_status_t status;
1691 FT_Error error;
1692
1693 /* According to the FreeType docs, glyphslot->format could be
1694 * something other than FT_GLYPH_FORMAT_OUTLINE or
1695 * FT_GLYPH_FORMAT_BITMAP. Calling FT_Render_Glyph gives FreeType
1696 * the opportunity to convert such to
1697 * bitmap. FT_GLYPH_FORMAT_COMPOSITE will not be encountered since
1698 * we avoid the FT_LOAD_NO_RECURSE flag.
1699 */
1700 error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
1701 /* XXX ignoring all other errors for now. They are not fatal, typically
1702 * just a glyph-not-found. */
1703 if (error == FT_Err_Out_Of_Memory)
1704 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1705
1706 status = _get_bitmap_surface (&glyphslot->bitmap,
1707 glyphslot->library,
1708 FALSE0, font_options,
1709 surface);
1710 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1711 return status;
1712
1713 /*
1714 * Note: the font's coordinate system is upside down from ours, so the
1715 * Y coordinate of the control box needs to be negated. Moreover, device
1716 * offsets are position of glyph origin relative to top left while
1717 * bitmap_left and bitmap_top are offsets of top left relative to origin.
1718 * Another negation.
1719 */
1720 cairo_surface_set_device_offset_moz_cairo_surface_set_device_offset (&(*surface)->base,
1721 -glyphslot->bitmap_left,
1722 +glyphslot->bitmap_top);
1723
1724 return CAIRO_STATUS_SUCCESS;
1725}
1726
1727static cairo_status_t
1728_transform_glyph_bitmap (cairo_matrix_t * shape,
1729 cairo_image_surface_t ** surface)
1730{
1731 cairo_matrix_t original_to_transformed;
1732 cairo_matrix_t transformed_to_original;
1733 cairo_image_surface_t *old_image;
1734 cairo_surface_t *image;
1735 double x[4], y[4];
1736 double origin_x, origin_y;
1737 int orig_width, orig_height;
1738 int i;
1739 int x_min, y_min, x_max, y_max;
1740 int width, height;
1741 cairo_status_t status;
1742 cairo_surface_pattern_t pattern;
1743
1744 /* We want to compute a transform that takes the origin
1745 * (device_x_offset, device_y_offset) to 0,0, then applies
1746 * the "shape" portion of the font transform
1747 */
1748 original_to_transformed = *shape;
1749
1750 cairo_surface_get_device_offset_moz_cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y);
1751 orig_width = (*surface)->width;
1752 orig_height = (*surface)->height;
1753
1754 cairo_matrix_translate_moz_cairo_matrix_translate (&original_to_transformed,
1755 -origin_x, -origin_y);
1756
1757 /* Find the bounding box of the original bitmap under that
1758 * transform
1759 */
1760 x[0] = 0; y[0] = 0;
1761 x[1] = orig_width; y[1] = 0;
1762 x[2] = orig_width; y[2] = orig_height;
1763 x[3] = 0; y[3] = orig_height;
1764
1765 for (i = 0; i < 4; i++)
1766 cairo_matrix_transform_point_moz_cairo_matrix_transform_point (&original_to_transformed,
1767 &x[i], &y[i]);
1768
1769 x_min = floor (x[0]); y_min = floor (y[0]);
1770 x_max = ceil (x[0]); y_max = ceil (y[0]);
1771
1772 for (i = 1; i < 4; i++) {
1773 if (x[i] < x_min)
1774 x_min = floor (x[i]);
1775 else if (x[i] > x_max)
1776 x_max = ceil (x[i]);
1777 if (y[i] < y_min)
1778 y_min = floor (y[i]);
1779 else if (y[i] > y_max)
1780 y_max = ceil (y[i]);
1781 }
1782
1783 /* Adjust the transform so that the bounding box starts at 0,0 ...
1784 * this gives our final transform from original bitmap to transformed
1785 * bitmap.
1786 */
1787 original_to_transformed.x0 -= x_min;
1788 original_to_transformed.y0 -= y_min;
1789
1790 /* Create the transformed bitmap */
1791 width = x_max - x_min;
1792 height = y_max - y_min;
1793
1794 transformed_to_original = original_to_transformed;
1795 status = cairo_matrix_invert_moz_cairo_matrix_invert (&transformed_to_original);
1796 if (unlikely (status)(__builtin_expect (!!(status), 0)))
1797 return status;
1798
1799 if ((*surface)->format == CAIRO_FORMAT_ARGB32 &&
1800 !pixman_image_get_component_alpha_moz_pixman_image_get_component_alpha ((*surface)->pixman_image))
1801 image = cairo_image_surface_create_moz_cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
1802 else
1803 image = cairo_image_surface_create_moz_cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
1804 if (unlikely (image->status)(__builtin_expect (!!(image->status), 0)))
1805 return image->status;
1806
1807 /* Draw the original bitmap transformed into the new bitmap
1808 */
1809 _cairo_pattern_init_for_surface (&pattern, &(*surface)->base);
1810 cairo_pattern_set_matrix_moz_cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
1811
1812 status = _cairo_surface_paint (image,
1813 CAIRO_OPERATOR_SOURCE,
1814 &pattern.base,
1815 NULL((void*)0));
1816
1817 _cairo_pattern_fini (&pattern.base);
1818
1819 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
1820 cairo_surface_destroy_moz_cairo_surface_destroy (image);
1821 return status;
1822 }
1823
1824 /* Now update the cache entry for the new bitmap, recomputing
1825 * the origin based on the final transform.
1826 */
1827 cairo_matrix_transform_point_moz_cairo_matrix_transform_point (&original_to_transformed,
1828 &origin_x, &origin_y);
1829
1830 old_image = (*surface);
1831 (*surface) = (cairo_image_surface_t *)image;
1832
1833 /* Note: we converted subpixel-rendered RGBA images to grayscale,
1834 * so, no need to copy component alpha to new image. */
1835
1836 cairo_surface_destroy_moz_cairo_surface_destroy (&old_image->base);
1837
1838 cairo_surface_set_device_offset_moz_cairo_surface_set_device_offset (&(*surface)->base,
1839 _cairo_lround (origin_x),
1840 _cairo_lround (origin_y));
1841 return CAIRO_STATUS_SUCCESS;
1842}
1843
1844static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = {
1845 _cairo_ft_unscaled_font_destroy,
1846#if 0
1847 _cairo_ft_unscaled_font_create_glyph
1848#endif
1849};
1850
1851/* #cairo_ft_scaled_font_t */
1852
1853typedef struct _cairo_ft_scaled_font {
1854 cairo_scaled_font_t base;
1855 cairo_ft_unscaled_font_t *unscaled;
1856 cairo_ft_options_t ft_options;
1857} cairo_ft_scaled_font_t;
1858
1859static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend;
1860
1861#if CAIRO_HAS_FC_FONT1
1862/* The load flags passed to FT_Load_Glyph control aspects like hinting and
1863 * antialiasing. Here we compute them from the fields of a FcPattern.
1864 */
1865static void
1866_get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
1867{
1868 FcBool antialias, vertical_layout, hinting, autohint, bitmap, embolden;
1869 cairo_ft_options_t ft_options;
1870 int rgba;
1871 int hintstyle;
1872 char *variations;
1873
1874 _cairo_font_options_init_default (&ft_options.base);
1875 ft_options.load_flags = FT_LOAD_DEFAULT0x0;
1876 ft_options.synth_flags = 0;
1877
1878 /* Check whether to force use of embedded bitmaps */
1879 if (FcPatternGetBool (pattern,
1880 FC_EMBEDDED_BITMAP"embeddedbitmap", 0, &bitmap) != FcResultMatch)
1881 bitmap = FcFalse0;
1882
1883 /* disable antialiasing if requested */
1884 if (FcPatternGetBool (pattern,
1885 FC_ANTIALIAS"antialias", 0, &antialias) != FcResultMatch)
1886 antialias = FcTrue1;
1887
1888 if (antialias) {
1889 cairo_subpixel_order_t subpixel_order;
1890 int lcd_filter;
1891
1892 /* disable hinting if requested */
1893 if (FcPatternGetBool (pattern,
1894 FC_HINTING"hinting", 0, &hinting) != FcResultMatch)
1895 hinting = FcTrue1;
1896
1897 if (FcPatternGetInteger (pattern,
1898 FC_RGBA"rgba", 0, &rgba) != FcResultMatch)
1899 rgba = FC_RGBA_UNKNOWN0;
1900
1901 switch (rgba) {
1902 case FC_RGBA_RGB1:
1903 subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
1904 break;
1905 case FC_RGBA_BGR2:
1906 subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
1907 break;
1908 case FC_RGBA_VRGB3:
1909 subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
1910 break;
1911 case FC_RGBA_VBGR4:
1912 subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
1913 break;
1914 case FC_RGBA_UNKNOWN0:
1915 case FC_RGBA_NONE5:
1916 default:
1917 subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
1918 break;
1919 }
1920
1921 if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) {
1922 ft_options.base.subpixel_order = subpixel_order;
1923 ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
1924 }
1925
1926 if (FcPatternGetInteger (pattern,
1927 FC_LCD_FILTER"lcdfilter", 0, &lcd_filter) == FcResultMatch)
1928 {
1929 switch (lcd_filter) {
1930 case FC_LCD_NONE0:
1931 ft_options.base.lcd_filter = CAIRO_LCD_FILTER_NONE;
1932 break;
1933 case FC_LCD_DEFAULT1:
1934 ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5;
1935 break;
1936 case FC_LCD_LIGHT2:
1937 ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3;
1938 break;
1939 case FC_LCD_LEGACY3:
1940 ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
1941 break;
1942 }
1943 }
1944
1945 if (FcPatternGetInteger (pattern,
1946 FC_HINT_STYLE"hintstyle", 0, &hintstyle) != FcResultMatch)
1947 hintstyle = FC_HINT_FULL3;
1948
1949 if (!hinting)
1950 hintstyle = FC_HINT_NONE0;
1951
1952 switch (hintstyle) {
1953 case FC_HINT_NONE0:
1954 ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
1955 break;
1956 case FC_HINT_SLIGHT1:
1957 ft_options.base.hint_style = CAIRO_HINT_STYLE_SLIGHT;
1958 break;
1959 case FC_HINT_MEDIUM2:
1960 default:
1961 ft_options.base.hint_style = CAIRO_HINT_STYLE_MEDIUM;
1962 break;
1963 case FC_HINT_FULL3:
1964 ft_options.base.hint_style = CAIRO_HINT_STYLE_FULL;
1965 break;
1966 }
1967
1968 /* Force embedded bitmaps off if no hinting requested */
1969 if (ft_options.base.hint_style == CAIRO_HINT_STYLE_NONE)
1970 bitmap = FcFalse0;
1971
1972 if (!bitmap)
1973 ft_options.load_flags |= FT_LOAD_NO_BITMAP( 1L << 3 );
1974
1975 } else {
1976 ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
1977 }
1978
1979 /* force autohinting if requested */
1980 if (FcPatternGetBool (pattern,
1981 FC_AUTOHINT"autohint", 0, &autohint) != FcResultMatch)
1982 autohint = FcFalse0;
1983
1984 if (autohint)
1985 ft_options.load_flags |= FT_LOAD_FORCE_AUTOHINT( 1L << 5 );
1986
1987 if (FcPatternGetBool (pattern,
1988 FC_VERTICAL_LAYOUT"verticallayout", 0, &vertical_layout) != FcResultMatch)
1989 vertical_layout = FcFalse0;
1990
1991 if (vertical_layout)
1992 ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT( 1L << 4 );
1993
1994 if (FcPatternGetBool (pattern,
1995 FC_EMBOLDEN"embolden", 0, &embolden) != FcResultMatch)
1996 embolden = FcFalse0;
1997
1998 if (embolden)
1999 ft_options.synth_flags |= CAIRO_FT_SYNTHESIZE_BOLD;
2000
2001#ifndef FC_FONT_VARIATIONS"fontvariations"
2002#define FC_FONT_VARIATIONS"fontvariations" "fontvariations"
2003#endif
2004 if (FcPatternGetString (pattern, FC_FONT_VARIATIONS"fontvariations", 0, (FcChar8 **) &variations) == FcResultMatch) {
2005 ft_options.base.variations = strdup (variations);
2006 }
2007
2008 *ret = ft_options;
2009}
2010#endif
2011
2012static void
2013_cairo_ft_options_merge (cairo_ft_options_t *options,
2014 cairo_ft_options_t *other)
2015{
2016 int load_flags = other->load_flags;
2017 int load_target = FT_LOAD_TARGET_NORMAL( (FT_Int32)((FT_RENDER_MODE_NORMAL) & 15) << 16 );
2018
2019 /* clear load target mode */
2020 load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(other->load_flags))( (FT_Int32)(((FT_Render_Mode)(( (other->load_flags) >>
16 ) & 15)) & 15) << 16 )
);
2021
2022 if (load_flags & FT_LOAD_NO_HINTING( 1L << 1 ))
2023 other->base.hint_style = CAIRO_HINT_STYLE_NONE;
2024
2025 if (other->base.antialias == CAIRO_ANTIALIAS_NONE ||
2026 options->base.antialias == CAIRO_ANTIALIAS_NONE) {
2027 options->base.antialias = CAIRO_ANTIALIAS_NONE;
2028 options->base.subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
2029 }
2030
2031 if (other->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL &&
2032 options->base.antialias == CAIRO_ANTIALIAS_DEFAULT) {
2033 options->base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
2034 options->base.subpixel_order = other->base.subpixel_order;
2035 }
2036
2037 if (options->base.hint_style == CAIRO_HINT_STYLE_DEFAULT)
2038 options->base.hint_style = other->base.hint_style;
2039
2040 if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
2041 options->base.hint_style = CAIRO_HINT_STYLE_NONE;
2042
2043 if (options->base.lcd_filter == CAIRO_LCD_FILTER_DEFAULT)
2044 options->base.lcd_filter = other->base.lcd_filter;
2045
2046 if (other->base.lcd_filter == CAIRO_LCD_FILTER_NONE)
2047 options->base.lcd_filter = CAIRO_LCD_FILTER_NONE;
2048
2049 if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
2050 if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
2051 load_flags |= FT_LOAD_NO_HINTING( 1L << 1 );
2052 else
2053 load_target = FT_LOAD_TARGET_MONO( (FT_Int32)((FT_RENDER_MODE_MONO) & 15) << 16 );
2054 load_flags |= FT_LOAD_MONOCHROME( 1L << 12 );
2055 } else {
2056 switch (options->base.hint_style) {
2057 case CAIRO_HINT_STYLE_NONE:
2058 load_flags |= FT_LOAD_NO_HINTING( 1L << 1 );
2059 break;
2060 case CAIRO_HINT_STYLE_SLIGHT:
2061 load_target = FT_LOAD_TARGET_LIGHT( (FT_Int32)((FT_RENDER_MODE_LIGHT) & 15) << 16 );
2062 break;
2063 case CAIRO_HINT_STYLE_MEDIUM:
2064 break;
2065 case CAIRO_HINT_STYLE_FULL:
2066 case CAIRO_HINT_STYLE_DEFAULT:
2067 if (options->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
2068 switch (options->base.subpixel_order) {
2069 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
2070 case CAIRO_SUBPIXEL_ORDER_RGB:
2071 case CAIRO_SUBPIXEL_ORDER_BGR:
2072 load_target = FT_LOAD_TARGET_LCD( (FT_Int32)((FT_RENDER_MODE_LCD) & 15) << 16 );
2073 break;
2074 case CAIRO_SUBPIXEL_ORDER_VRGB:
2075 case CAIRO_SUBPIXEL_ORDER_VBGR:
2076 load_target = FT_LOAD_TARGET_LCD_V( (FT_Int32)((FT_RENDER_MODE_LCD_V) & 15) << 16 );
2077 break;
2078 }
2079 }
2080 break;
2081 }
2082 }
2083
2084 if (other->base.variations) {
2085 if (options->base.variations) {
2086 char *p;
2087
2088 /* 'merge' variations by concatenating - later entries win */
2089 p = malloc (strlen (other->base.variations) + strlen (options->base.variations) + 2);
2090 p[0] = 0;
2091 strcat (p, other->base.variations);
2092 strcat (p, ",");
2093 strcat (p, options->base.variations);
2094 free (options->base.variations);
2095 options->base.variations = p;
2096 }
2097 else {
2098 options->base.variations = strdup (other->base.variations);
2099 }
2100 }
2101
2102 options->load_flags = load_flags | load_target;
2103 options->synth_flags = other->synth_flags;
2104}
2105
2106static cairo_status_t
2107_cairo_ft_font_face_scaled_font_create (void *abstract_font_face,
2108 const cairo_matrix_t *font_matrix,
2109 const cairo_matrix_t *ctm,
2110 const cairo_font_options_t *options,
2111 cairo_scaled_font_t **font_out)
2112{
2113 cairo_ft_font_face_t *font_face = abstract_font_face;
2114 cairo_ft_scaled_font_t *scaled_font;
2115 FT_Face face;
2116 FT_Size_Metrics *metrics;
2117 cairo_font_extents_t fs_metrics;
2118 cairo_status_t status;
2119 cairo_ft_unscaled_font_t *unscaled;
2120
2121 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"
, 2121, __extension__ __PRETTY_FUNCTION__); }))
;
2122
2123 face = _cairo_ft_unscaled_font_lock_face (font_face->unscaled);
2124 if (unlikely (face == NULL)(__builtin_expect (!!(face == ((void*)0)), 0))) /* backend error */
2125 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2126
2127 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))
;
2128 if (unlikely (scaled_font == NULL)(__builtin_expect (!!(scaled_font == ((void*)0)), 0))) {
2129 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2130 goto FAIL;
2131 }
2132
2133 scaled_font->unscaled = unscaled = font_face->unscaled;
2134 _cairo_unscaled_font_reference (&unscaled->base);
2135
2136 _cairo_font_options_init_copy (&scaled_font->ft_options.base, options);
2137 _cairo_ft_options_merge (&scaled_font->ft_options, &font_face->ft_options);
2138
2139 status = _cairo_scaled_font_init (&scaled_font->base,
2140 &font_face->base,
2141 font_matrix, ctm, options,
2142 &_cairo_ft_scaled_font_backend);
2143 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2144 goto CLEANUP_SCALED_FONT;
2145
2146 status = _cairo_ft_unscaled_font_set_scale (unscaled,
2147 &scaled_font->base.scale);
2148 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
2149 /* This can only fail if we encounter an error with the underlying
2150 * font, so propagate the error back to the font-face. */
2151 _cairo_ft_unscaled_font_unlock_face (unscaled);
2152 _cairo_unscaled_font_destroy (&unscaled->base);
2153 free (scaled_font);
2154 return status;
2155 }
2156
2157
2158 metrics = &face->size->metrics;
2159
2160 /*
2161 * Get to unscaled metrics so that the upper level can get back to
2162 * user space
2163 *
2164 * Also use this path for bitmap-only fonts. The other branch uses
2165 * face members that are only relevant for scalable fonts. This is
2166 * detected by simply checking for units_per_EM==0.
2167 */
2168 if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF ||
2169 face->units_per_EM == 0) {
2170 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))
;
2171 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))
;
2172 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))
;
2173 if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
2174 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))
;
2175 fs_metrics.max_y_advance = 0;
2176 } else {
2177 fs_metrics.max_x_advance = 0;
2178 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))
;
2179 }
2180 } else {
2181 double scale = face->units_per_EM;
2182
2183 fs_metrics.ascent = face->ascender / scale;
2184 fs_metrics.descent = - face->descender / scale;
2185 fs_metrics.height = face->height / scale;
2186 if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
2187 fs_metrics.max_x_advance = face->max_advance_width / scale;
2188 fs_metrics.max_y_advance = 0;
2189 } else {
2190 fs_metrics.max_x_advance = 0;
2191 fs_metrics.max_y_advance = face->max_advance_height / scale;
2192 }
2193 }
2194
2195 status = _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics);
2196 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2197 goto CLEANUP_SCALED_FONT;
2198
2199 _cairo_ft_unscaled_font_unlock_face (unscaled);
2200
2201 *font_out = &scaled_font->base;
2202 return CAIRO_STATUS_SUCCESS;
2203
2204 CLEANUP_SCALED_FONT:
2205 _cairo_unscaled_font_destroy (&unscaled->base);
2206 free (scaled_font);
2207 FAIL:
2208 _cairo_ft_unscaled_font_unlock_face (font_face->unscaled);
2209 *font_out = _cairo_scaled_font_create_in_error (status);
2210 return CAIRO_STATUS_SUCCESS; /* non-backend error */
2211}
2212
2213cairo_bool_t
2214_cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
2215{
2216 return scaled_font->backend == &_cairo_ft_scaled_font_backend;
2217}
2218
2219static void
2220_cairo_ft_scaled_font_fini (void *abstract_font)
2221{
2222 cairo_ft_scaled_font_t *scaled_font = abstract_font;
2223
2224 if (scaled_font == NULL((void*)0))
2225 return;
2226
2227 _cairo_font_options_fini (&scaled_font->ft_options.base);
2228 _cairo_unscaled_font_destroy (&scaled_font->unscaled->base);
2229}
2230
2231static int
2232_move_to (FT_Vector *to, void *closure)
2233{
2234 cairo_path_fixed_t *path = closure;
2235 cairo_fixed_t x, y;
2236
2237 x = _cairo_fixed_from_26_6 (to->x);
2238 y = _cairo_fixed_from_26_6 (to->y);
2239
2240 if (_cairo_path_fixed_close_path (path) != CAIRO_STATUS_SUCCESS)
2241 return 1;
2242 if (_cairo_path_fixed_move_to (path, x, y) != CAIRO_STATUS_SUCCESS)
2243 return 1;
2244
2245 return 0;
2246}
2247
2248static int
2249_line_to (FT_Vector *to, void *closure)
2250{
2251 cairo_path_fixed_t *path = closure;
2252 cairo_fixed_t x, y;
2253
2254 x = _cairo_fixed_from_26_6 (to->x);
2255 y = _cairo_fixed_from_26_6 (to->y);
2256
2257 if (_cairo_path_fixed_line_to (path, x, y) != CAIRO_STATUS_SUCCESS)
2258 return 1;
2259
2260 return 0;
2261}
2262
2263static int
2264_conic_to (FT_Vector *control, FT_Vector *to, void *closure)
2265{
2266 cairo_path_fixed_t *path = closure;
2267
2268 cairo_fixed_t x0, y0;
2269 cairo_fixed_t x1, y1;
2270 cairo_fixed_t x2, y2;
2271 cairo_fixed_t x3, y3;
2272 cairo_point_t conic;
2273
2274 if (! _cairo_path_fixed_get_current_point (path, &x0, &y0))
2275 return 1;
2276
2277 conic.x = _cairo_fixed_from_26_6 (control->x);
2278 conic.y = _cairo_fixed_from_26_6 (control->y);
2279
2280 x3 = _cairo_fixed_from_26_6 (to->x);
2281 y3 = _cairo_fixed_from_26_6 (to->y);
2282
2283 x1 = x0 + 2.0/3.0 * (conic.x - x0);
2284 y1 = y0 + 2.0/3.0 * (conic.y - y0);
2285
2286 x2 = x3 + 2.0/3.0 * (conic.x - x3);
2287 y2 = y3 + 2.0/3.0 * (conic.y - y3);
2288
2289 if (_cairo_path_fixed_curve_to (path,
2290 x1, y1,
2291 x2, y2,
2292 x3, y3) != CAIRO_STATUS_SUCCESS)
2293 return 1;
2294
2295 return 0;
2296}
2297
2298static int
2299_cubic_to (FT_Vector *control1, FT_Vector *control2,
2300 FT_Vector *to, void *closure)
2301{
2302 cairo_path_fixed_t *path = closure;
2303 cairo_fixed_t x0, y0;
2304 cairo_fixed_t x1, y1;
2305 cairo_fixed_t x2, y2;
2306
2307 x0 = _cairo_fixed_from_26_6 (control1->x);
2308 y0 = _cairo_fixed_from_26_6 (control1->y);
2309
2310 x1 = _cairo_fixed_from_26_6 (control2->x);
2311 y1 = _cairo_fixed_from_26_6 (control2->y);
2312
2313 x2 = _cairo_fixed_from_26_6 (to->x);
2314 y2 = _cairo_fixed_from_26_6 (to->y);
2315
2316 if (_cairo_path_fixed_curve_to (path,
2317 x0, y0,
2318 x1, y1,
2319 x2, y2) != CAIRO_STATUS_SUCCESS)
2320 return 1;
2321
2322 return 0;
2323}
2324
2325cairo_status_t
2326_cairo_ft_face_decompose_glyph_outline (FT_Face face,
2327 cairo_path_fixed_t **pathp)
2328{
2329 static const FT_Outline_Funcs outline_funcs = {
2330 (FT_Outline_MoveToFunc)_move_to,
2331 (FT_Outline_LineToFunc)_line_to,
2332 (FT_Outline_ConicToFunc)_conic_to,
2333 (FT_Outline_CubicToFunc)_cubic_to,
2334 0, /* shift */
2335 0, /* delta */
2336 };
2337 static const FT_Matrix invert_y = {
2338 DOUBLE_TO_16_16 (1.0)((FT_Fixed)((1.0) * 65536.0)), 0,
2339 0, DOUBLE_TO_16_16 (-1.0)((FT_Fixed)((-1.0) * 65536.0)),
2340 };
2341
2342 FT_GlyphSlot glyph;
2343 cairo_path_fixed_t *path;
2344 cairo_status_t status;
2345
2346 path = _cairo_path_fixed_create ();
2347 if (!path)
2348 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2349
2350 glyph = face->glyph;
2351
2352 /* Font glyphs have an inverted Y axis compared to cairo. */
2353 FT_Outline_Transform (&glyph->outline, &invert_y);
2354 if (FT_Outline_Decompose (&glyph->outline, &outline_funcs, path)) {
2355 _cairo_path_fixed_destroy (path);
2356 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2357 }
2358
2359 status = _cairo_path_fixed_close_path (path);
2360 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
2361 _cairo_path_fixed_destroy (path);
2362 return status;
2363 }
2364
2365 *pathp = path;
2366
2367 return CAIRO_STATUS_SUCCESS;
2368}
2369
2370/*
2371 * Translate glyph to match its metrics.
2372 */
2373static void
2374_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (void *abstract_font,
2375 FT_GlyphSlot glyph)
2376{
2377 cairo_ft_scaled_font_t *scaled_font = abstract_font;
2378 FT_Vector vector;
2379
2380 vector.x = glyph->metrics.vertBearingX - glyph->metrics.horiBearingX;
2381 vector.y = -glyph->metrics.vertBearingY - glyph->metrics.horiBearingY;
2382
2383 if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
2384 FT_Vector_Transform (&vector, &scaled_font->unscaled->Current_Shape);
2385 FT_Outline_Translate(&glyph->outline, vector.x, vector.y);
2386 } else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
2387 glyph->bitmap_left += vector.x / 64;
2388 glyph->bitmap_top += vector.y / 64;
2389 }
2390}
2391
2392static void
2393cairo_ft_apply_variations (FT_Face face,
2394 cairo_ft_scaled_font_t *scaled_font)
2395{
2396 FT_MM_Var *ft_mm_var;
2397 FT_Error ret;
2398 unsigned int instance_id = scaled_font->unscaled->id >> 16;
2399
2400 static GetVarFunc getVar;
2401 static DoneVarFunc doneVar;
2402 static GetVarDesignCoordsFunc getVarDesignCoords;
2403 static SetVarDesignCoordsFunc setVarDesignCoords;
2404
2405 static int firstTime = 1;
2406 if (firstTime) {
2407 getVar = (GetVarFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Get_MM_Var");
2408 doneVar = (DoneVarFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Done_MM_Var");
2409 getVarDesignCoords = (GetVarDesignCoordsFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Get_Var_Design_Coordinates");
2410 setVarDesignCoords = (SetVarDesignCoordsFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Set_Var_Design_Coordinates");
2411 firstTime = 0;
2412 }
2413
2414 if (!getVar || !setVarDesignCoords)
2415 return;
2416
2417 ret = (*getVar) (face, &ft_mm_var);
2418 if (ret == 0) {
2419 FT_Fixed *current_coords;
2420 FT_Fixed *coords;
2421 unsigned int i;
2422 const char *p;
2423
2424 coords = malloc (sizeof (FT_Fixed) * ft_mm_var->num_axis);
2425 /* FIXME check coords. */
2426
2427 if (scaled_font->unscaled->variations)
2428 {
2429 memcpy (coords, scaled_font->unscaled->variations, ft_mm_var->num_axis * sizeof (*coords));
2430 }
2431 else if (instance_id && instance_id <= ft_mm_var->num_namedstyles)
2432 {
2433 FT_Var_Named_Style *instance = &ft_mm_var->namedstyle[instance_id - 1];
2434 memcpy (coords, instance->coords, ft_mm_var->num_axis * sizeof (*coords));
2435 }
2436 else
2437 for (i = 0; i < ft_mm_var->num_axis; i++)
2438 coords[i] = ft_mm_var->axis[i].def;
2439
2440 p = scaled_font->ft_options.base.variations;
2441 while (p && *p) {
2442 const char *start;
2443 const char *end, *end2;
2444 FT_ULong tag;
2445 double value;
2446
2447 while (_cairo_isspace (*p)) p++;
2448
2449 start = p;
2450 end = strchr (p, ',')_Generic (0 ? (p) : (void *) 1, const void *: (const char *) (
strchr (p, ',')), default: strchr (p, ','))
;
2451 if (end && (end - p < 6))
2452 goto skip;
2453
2454 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]) )
;
2455
2456 p += 4;
2457 while (_cairo_isspace (*p)) p++;
2458 if (*p == '=') p++;
2459
2460 if (p - start < 5)
2461 goto skip;
2462
2463 value = _cairo_strtod (p, (char **) &end2);
2464
2465 while (end2 && _cairo_isspace (*end2)) end2++;
2466
2467 if (end2 && (*end2 != ',' && *end2 != '\0'))
2468 goto skip;
2469
2470 for (i = 0; i < ft_mm_var->num_axis; i++) {
2471 if (ft_mm_var->axis[i].tag == tag) {
2472 coords[i] = (FT_Fixed)(value*65536);
2473 break;
2474 }
2475 }
2476
2477skip:
2478 p = end ? end + 1 : NULL((void*)0);
2479 }
2480
2481 current_coords = malloc (sizeof (FT_Fixed) * ft_mm_var->num_axis);
2482
2483 if (getVarDesignCoords) {
2484 ret = (*getVarDesignCoords) (face, ft_mm_var->num_axis, current_coords);
2485 if (ret == 0) {
2486 for (i = 0; i < ft_mm_var->num_axis; i++) {
2487 if (coords[i] != current_coords[i])
2488 break;
2489 }
2490 if (i == ft_mm_var->num_axis)
2491 goto done;
2492 }
2493 }
2494
2495 (*setVarDesignCoords) (face, ft_mm_var->num_axis, coords);
2496done:
2497 free (coords);
2498 free (current_coords);
2499
2500 if (doneVar)
2501 (*doneVar) (face->glyph->library, ft_mm_var);
2502 else
2503 free (ft_mm_var);
2504 }
2505}
2506
2507typedef enum {
2508 CAIRO_FT_GLYPH_TYPE_BITMAP,
2509 CAIRO_FT_GLYPH_TYPE_OUTLINE,
2510 CAIRO_FT_GLYPH_TYPE_SVG,
2511 CAIRO_FT_GLYPH_TYPE_COLR_V0,
2512 CAIRO_FT_GLYPH_TYPE_COLR_V1,
2513} cairo_ft_glyph_format_t;
2514
2515typedef struct {
2516 cairo_scaled_glyph_private_t base;
2517
2518 cairo_ft_glyph_format_t format;
2519} cairo_ft_glyph_private_t;
2520
2521static const int ft_glyph_private_key;
2522
2523static cairo_int_status_t
2524_cairo_ft_scaled_glyph_load_glyph (cairo_ft_scaled_font_t *scaled_font,
2525 cairo_scaled_glyph_t *scaled_glyph,
2526 FT_Face face,
2527 int load_flags,
2528 cairo_bool_t use_em_size,
2529 cairo_bool_t vertical_layout)
2530{
2531 FT_Error error;
2532 cairo_status_t status;
2533 cairo_ft_glyph_private_t *glyph_priv;
2534
2535 glyph_priv = (cairo_ft_glyph_private_t *) _cairo_scaled_glyph_find_private (scaled_glyph,
2536 &ft_glyph_private_key);
2537 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"
, 2537, __extension__ __PRETTY_FUNCTION__); }))
;
2538
2539 if (use_em_size) {
2540 cairo_matrix_t em_size;
2541 cairo_matrix_init_scale_moz_cairo_matrix_init_scale (&em_size, face->units_per_EM, face->units_per_EM);
2542 status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled, &em_size);
2543 } else {
2544 status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
2545 &scaled_font->base.scale);
2546 }
2547 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2548 return status;
2549
2550 cairo_ft_apply_variations (face, scaled_font);
2551
2552#if defined(HAVE_FT_LOAD_NO_SVG)
2553 if (load_flags & FT_LOAD_COLOR( 1L << 20 ) && glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1)
2554 load_flags |= FT_LOAD_NO_SVG( 1L << 24 );
2555#endif
2556
2557 error = FT_Load_Glyph (face,
2558 _cairo_scaled_glyph_index(scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
2559 load_flags);
2560 /* XXX ignoring all other errors for now. They are not fatal, typically
2561 * just a glyph-not-found. */
2562 if (error == FT_Err_Out_Of_Memory)
2563 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2564
2565 /*
2566 * synthesize glyphs if requested
2567 */
2568 if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_BOLD)
2569 FT_GlyphSlot_Embolden (face->glyph);
2570
2571 if (scaled_font->ft_options.synth_flags & CAIRO_FT_SYNTHESIZE_OBLIQUE)
2572 FT_GlyphSlot_Oblique (face->glyph);
2573
2574 if (vertical_layout)
2575 _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, face->glyph);
2576
2577 if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
2578 FT_Pos xshift, yshift;
2579
2580 xshift = _cairo_scaled_glyph_xphase (scaled_glyph)(int)(((scaled_glyph)->hash_entry.hash >> 24) & 3
)
<< 4;
2581 yshift = _cairo_scaled_glyph_yphase (scaled_glyph)(int)(((scaled_glyph)->hash_entry.hash >> 26) & 3
)
<< 4;
2582
2583 FT_Outline_Translate (&face->glyph->outline, xshift, -yshift);
2584 }
2585
2586 return CAIRO_STATUS_SUCCESS;
2587}
2588
2589static void
2590_cairo_ft_glyph_fini (cairo_scaled_glyph_private_t *glyph_private,
2591 cairo_scaled_glyph_t *glyph,
2592 cairo_scaled_font_t *font)
2593{
2594 cairo_list_del (&glyph_private->link);
2595 free (glyph_private);
2596}
2597
2598
2599#ifdef FT_COLOR_H<freetype/ftcolor.h>
2600static void
2601_cairo_ft_scaled_glyph_set_palette (cairo_ft_scaled_font_t *scaled_font,
2602 FT_Face face,
2603 unsigned int *num_entries_ret,
2604 FT_Color **entries_ret)
2605{
2606 unsigned int num_entries = 0;
2607 FT_Color *entries = NULL((void*)0);
2608
2609 FT_Palette_Data palette_data;
2610
2611 if (FT_Palette_Data_Get (face, &palette_data) == 0 && palette_data.num_palettes > 0) {
2612 FT_UShort palette_index = CAIRO_COLOR_PALETTE_DEFAULT0;
2613 if (scaled_font->base.options.palette_index < palette_data.num_palettes)
2614 palette_index = scaled_font->base.options.palette_index;
2615
2616 if (FT_Palette_Select (face, palette_index, &entries) == 0) {
2617 num_entries = palette_data.num_palette_entries;
2618
2619 /* Overlay custom colors */
2620 for (unsigned int i = 0; i < scaled_font->base.options.custom_palette_size; i++) {
2621 cairo_palette_color_t *entry = &scaled_font->base.options.custom_palette[i];
2622 if (entry->index < num_entries) {
2623 entries[entry->index].red = 255 * entry->red;
2624 entries[entry->index].green = 255 * entry->green;
2625 entries[entry->index].blue = 255 * entry->blue;
2626 entries[entry->index].alpha = 255 * entry->alpha;
2627 }
2628 }
2629 }
2630 }
2631
2632 if (num_entries_ret)
2633 *num_entries_ret = num_entries;
2634
2635 if (entries_ret)
2636 *entries_ret = entries;
2637}
2638#else
2639static void
2640_cairo_ft_scaled_glyph_set_palette (cairo_ft_scaled_font_t *scaled_font,
2641 FT_Face face,
2642 unsigned int *num_entries_ret,
2643 void **entries_ret)
2644{
2645 if (num_entries_ret)
2646 *num_entries_ret = 0;
2647
2648 if (entries_ret)
2649 *entries_ret = NULL((void*)0);
2650}
2651#endif
2652
2653/* returns TRUE if foreground color used */
2654static cairo_bool_t
2655_cairo_ft_scaled_glyph_set_foreground_color (cairo_ft_scaled_font_t *scaled_font,
2656 cairo_scaled_glyph_t *scaled_glyph,
2657 FT_Face face,
2658 const cairo_color_t *foreground_color)
2659{
2660 cairo_bool_t uses_foreground_color = FALSE0;
2661#ifdef FT_COLOR_H<freetype/ftcolor.h>
2662 FT_LayerIterator iterator;
2663 FT_UInt layer_glyph_index;
2664 FT_UInt layer_color_index;
2665 FT_Color color;
2666
2667 /* Check if there is a layer that uses the foreground color */
2668 iterator.p = NULL((void*)0);
2669 while (FT_Get_Color_Glyph_Layer(face,
2670 _cairo_scaled_glyph_index (scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
2671 &layer_glyph_index,
2672 &layer_color_index,
2673 &iterator)) {
2674 if (layer_color_index == 0xFFFF) {
2675 uses_foreground_color = TRUE1;
2676 break;
2677 }
2678 }
2679
2680 if (uses_foreground_color) {
2681 color.red = (FT_Byte)(foreground_color->red * 0xFF);
2682 color.green = (FT_Byte)(foreground_color->green * 0xFF);
2683 color.blue = (FT_Byte)(foreground_color->blue * 0xFF);
2684 color.alpha = (FT_Byte)(foreground_color->alpha * 0xFF);
2685 FT_Palette_Set_Foreground_Color (face, color);
2686 }
2687#endif
2688 return uses_foreground_color;
2689}
2690
2691static cairo_int_status_t
2692_cairo_ft_scaled_glyph_init_surface (cairo_ft_scaled_font_t *scaled_font,
2693 cairo_scaled_glyph_t *scaled_glyph,
2694 cairo_ft_glyph_private_t *glyph_priv,
2695 cairo_scaled_glyph_info_t info,
2696 FT_Face face,
2697 const cairo_color_t *foreground_color,
2698 cairo_bool_t vertical_layout,
2699 int load_flags)
2700{
2701 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
2702 FT_GlyphSlot glyph;
2703 cairo_status_t status;
2704 cairo_image_surface_t *surface;
2705 cairo_bool_t uses_foreground_color = FALSE0;
2706
2707 /* Only one info type at a time handled in this function */
2708 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", 2708
, __extension__ __PRETTY_FUNCTION__); }))
;
2709
2710 if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
2711 if (!unscaled->have_color) {
2712 scaled_glyph->color_glyph = FALSE0;
2713 scaled_glyph->color_glyph_set = TRUE1;
2714 return CAIRO_INT_STATUS_UNSUPPORTED;
2715 }
2716
2717 uses_foreground_color = _cairo_ft_scaled_glyph_set_foreground_color (scaled_font,
2718 scaled_glyph,
2719 face,
2720 foreground_color);
2721 _cairo_ft_scaled_glyph_set_palette (scaled_font, face, NULL((void*)0), NULL((void*)0));
2722
2723 load_flags &= ~FT_LOAD_MONOCHROME( 1L << 12 );
2724 /* clear load target mode */
2725 load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(load_flags))( (FT_Int32)(((FT_Render_Mode)(( (load_flags) >> 16 ) &
15)) & 15) << 16 )
);
2726 load_flags |= FT_LOAD_TARGET_NORMAL( (FT_Int32)((FT_RENDER_MODE_NORMAL) & 15) << 16 );
2727 load_flags |= FT_LOAD_COLOR( 1L << 20 );
2728 } else { /* info == CAIRO_SCALED_GLYPH_INFO_SURFACE */
2729 load_flags &= ~FT_LOAD_COLOR( 1L << 20 );
2730 }
2731
2732 status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
2733 scaled_glyph,
2734 face,
2735 load_flags,
2736 FALSE0,
2737 vertical_layout);
2738 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2739 return status;
2740
2741 glyph = face->glyph;
2742
2743 if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_OUTLINE) {
2744
2745 status = _render_glyph_outline (face, &scaled_font->ft_options.base,
2746 &surface);
2747 } else {
2748 status = _render_glyph_bitmap (face, &scaled_font->ft_options.base,
2749 &surface);
2750 if (likely (status == CAIRO_STATUS_SUCCESS)(__builtin_expect (!!(status == CAIRO_STATUS_SUCCESS), 1)) && unscaled->have_shape) {
2751 status = _transform_glyph_bitmap (&unscaled->current_shape,
2752 &surface);
2753 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2754 cairo_surface_destroy_moz_cairo_surface_destroy (&surface->base);
2755 }
2756 }
2757
2758 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2759 return status;
2760
2761 if (info == CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) {
2762 /* We tried loading a color glyph and can now check if we got
2763 * a color glyph and set scaled_glyph->color_glyph
2764 * accordingly */
2765 if (pixman_image_get_format_moz_pixman_image_get_format (surface->pixman_image) == PIXMAN_a8r8g8b8 &&
2766 !pixman_image_get_component_alpha_moz_pixman_image_get_component_alpha (surface->pixman_image))
2767 {
2768 _cairo_scaled_glyph_set_color_surface (scaled_glyph,
2769 &scaled_font->base,
2770 surface,
2771 uses_foreground_color ? foreground_color : NULL((void*)0));
2772
2773 scaled_glyph->color_glyph = TRUE1;
2774 } else {
2775 /* We didn't ask for a non-color surface, but store it
2776 * anyway so we don't have to load it again. */
2777 _cairo_scaled_glyph_set_surface (scaled_glyph,
2778 &scaled_font->base,
2779 surface);
2780 scaled_glyph->color_glyph = FALSE0;
2781 status = CAIRO_INT_STATUS_UNSUPPORTED;
2782 }
2783 scaled_glyph->color_glyph_set = TRUE1;
2784 } else { /* info == CAIRO_SCALED_GLYPH_INFO_SURFACE */
2785 _cairo_scaled_glyph_set_surface (scaled_glyph,
2786 &scaled_font->base,
2787 surface);
2788 }
2789
2790 return status;
2791}
2792
2793static cairo_int_status_t
2794_cairo_ft_scaled_glyph_init_record_colr_v0_glyph (cairo_ft_scaled_font_t *scaled_font,
2795 cairo_scaled_glyph_t *scaled_glyph,
2796 FT_Face face,
2797 cairo_bool_t vertical_layout,
2798 int load_flags)
2799{
2800#ifdef FT_COLOR_H<freetype/ftcolor.h>
2801 cairo_surface_t *recording_surface;
2802 cairo_t *cr;
2803 cairo_status_t status;
2804 FT_Color *palette;
2805 unsigned int num_palette_entries;
2806 FT_LayerIterator iterator;
2807 FT_UInt layer_glyph_index;
2808 FT_UInt layer_color_index;
2809 cairo_path_fixed_t *path_fixed;
2810 cairo_path_t *path;
2811
2812 _cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette);
2813
2814 load_flags &= ~FT_LOAD_MONOCHROME( 1L << 12 );
2815 /* clear load target mode */
2816 load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(load_flags))( (FT_Int32)(((FT_Render_Mode)(( (load_flags) >> 16 ) &
15)) & 15) << 16 )
);
2817 load_flags |= FT_LOAD_TARGET_NORMAL( (FT_Int32)((FT_RENDER_MODE_NORMAL) & 15) << 16 );
2818 load_flags |= FT_LOAD_COLOR( 1L << 20 );
2819
2820 recording_surface =
2821 cairo_recording_surface_create_moz_cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL((void*)0));
2822
2823 cr = cairo_create_moz_cairo_create (recording_surface);
2824
2825 if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
2826 cairo_matrix_t scale;
2827 scale = scaled_font->base.scale;
2828 scale.x0 = scale.y0 = 0.;
2829 cairo_set_matrix_moz_cairo_set_matrix (cr, &scale);
2830 }
2831
2832 iterator.p = NULL((void*)0);
2833 while (FT_Get_Color_Glyph_Layer(face,
2834 _cairo_scaled_glyph_index (scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
2835 &layer_glyph_index,
2836 &layer_color_index,
2837 &iterator))
2838 {
2839 cairo_pattern_t *pattern;
2840 if (layer_color_index == 0xFFFF) {
2841 pattern = _cairo_pattern_create_foreground_marker ();
2842 } else {
2843 double r = 0, g = 0, b = 0, a = 1;
2844 if (layer_color_index < num_palette_entries) {
2845 FT_Color *color = &palette[layer_color_index];
2846 r = color->red / 255.0;
2847 g = color->green/ 255.0;
2848 b = color->blue / 255.0;
2849 a = color->alpha / 255.0;
2850 }
2851 pattern = cairo_pattern_create_rgba_moz_cairo_pattern_create_rgba (r, g, b, a);
2852 }
2853 cairo_set_source_moz_cairo_set_source (cr, pattern);
2854 cairo_pattern_destroy_moz_cairo_pattern_destroy (pattern);
2855
2856 if (FT_Load_Glyph (face, layer_glyph_index, load_flags) != 0) {
2857 status = CAIRO_INT_STATUS_UNSUPPORTED;
2858 goto cleanup;
2859 }
2860
2861 status = _cairo_ft_face_decompose_glyph_outline (face, &path_fixed);
2862 if (unlikely (status)(__builtin_expect (!!(status), 0)))
2863 return status;
2864
2865 path = _cairo_path_create (path_fixed, cr);
2866 _cairo_path_fixed_destroy (path_fixed);
2867 cairo_append_path_moz_cairo_append_path(cr, path);
2868 cairo_path_destroy_moz_cairo_path_destroy (path);
2869 cairo_fill_moz_cairo_fill (cr);
2870 }
2871
2872 cleanup:
2873 cairo_destroy_moz_cairo_destroy (cr);
2874
2875 if (status) {
2876 cairo_surface_destroy_moz_cairo_surface_destroy (recording_surface);
2877 return status;
2878 }
2879
2880 _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
2881 &scaled_font->base,
2882 recording_surface,
2883 NULL((void*)0));
2884 return status;
2885#else
2886 return CAIRO_INT_STATUS_UNSUPPORTED;
2887#endif
2888}
2889
2890static cairo_int_status_t
2891_cairo_ft_scaled_glyph_init_record_colr_v1_glyph (cairo_ft_scaled_font_t *scaled_font,
2892 cairo_scaled_glyph_t *scaled_glyph,
2893 FT_Face face,
2894 const cairo_color_t *foreground_color,
2895 cairo_text_extents_t *extents)
2896{
2897#if HAVE_FT_COLR_V1
2898 cairo_status_t status = CAIRO_STATUS_SUCCESS;
2899 cairo_surface_t *recording_surface;
2900 cairo_t *cr;
2901 FT_Color *palette;
2902 unsigned int num_palette_entries;
2903 cairo_bool_t foreground_source_used = FALSE0;
2904
2905 recording_surface =
2906 cairo_recording_surface_create_moz_cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL((void*)0));
2907
2908 cairo_surface_set_device_scale (recording_surface, 1, -1);
2909
2910 cr = cairo_create_moz_cairo_create (recording_surface);
2911
2912 cairo_set_font_size_moz_cairo_set_font_size (cr, 1.0);
2913 cairo_set_font_options_moz_cairo_set_font_options (cr, &scaled_font->base.options);
2914
2915 extents->x_bearing = DOUBLE_FROM_26_6(face->bbox.xMin)((double)(face->bbox.xMin) / 64.0);
2916 extents->y_bearing = DOUBLE_FROM_26_6(face->bbox.yMin)((double)(face->bbox.yMin) / 64.0);
2917 extents->width = DOUBLE_FROM_26_6(face->bbox.xMax)((double)(face->bbox.xMax) / 64.0) - extents->x_bearing;
2918 extents->height = DOUBLE_FROM_26_6(face->bbox.yMax)((double)(face->bbox.yMax) / 64.0) - extents->y_bearing;
2919
2920 _cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette);
2921
2922 if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
2923 cairo_pattern_t *foreground_pattern = _cairo_pattern_create_solid (foreground_color);
2924 status = _cairo_render_colr_v1_glyph (face,
2925 _cairo_scaled_glyph_index (scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
2926 palette,
2927 num_palette_entries,
2928 cr,
2929 foreground_pattern,
2930 &foreground_source_used);
2931 cairo_pattern_destroy_moz_cairo_pattern_destroy (foreground_pattern);
2932 if (status == CAIRO_STATUS_SUCCESS)
2933 status = cairo_status_moz_cairo_status (cr);
2934 }
2935
2936 cairo_destroy_moz_cairo_destroy (cr);
2937
2938 if (status) {
2939 cairo_surface_destroy_moz_cairo_surface_destroy (recording_surface);
2940 scaled_glyph->color_glyph = FALSE0;
2941 scaled_glyph->color_glyph_set = TRUE1;
2942 return status;
2943 }
2944
2945 _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
2946 &scaled_font->base,
2947 recording_surface,
2948 foreground_source_used ? foreground_color : NULL((void*)0));
2949
2950 scaled_glyph->color_glyph = TRUE1;
2951 scaled_glyph->color_glyph_set = TRUE1;
2952
2953 /* get metrics */
2954
2955 /* Copied from cairo-user-font.c */
2956 cairo_matrix_t extent_scale;
2957 double extent_x_scale = 1.0;
2958 double extent_y_scale = 1.0;
2959 double snap_x_scale;
2960 double snap_y_scale;
2961 double fixed_scale, x_scale, y_scale;
2962
2963 extent_scale = scaled_font->base.scale_inverse;
2964 snap_x_scale = 1.0;
2965 snap_y_scale = 1.0;
2966 status = _cairo_matrix_compute_basis_scale_factors (&extent_scale,
2967 &x_scale, &y_scale,
2968 1);
2969 if (status == CAIRO_STATUS_SUCCESS) {
2970 if (x_scale == 0)
2971 x_scale = 1;
2972 if (y_scale == 0)
2973 y_scale = 1;
2974
2975 snap_x_scale = x_scale;
2976 snap_y_scale = y_scale;
2977
2978 /* since glyphs are pretty much 1.0x1.0, we can reduce error by
2979 * scaling to a larger square. say, 1024.x1024. */
2980 fixed_scale = 1024;
2981 x_scale /= fixed_scale;
2982 y_scale /= fixed_scale;
2983
2984 cairo_matrix_scale_moz_cairo_matrix_scale (&extent_scale, 1.0 / x_scale, 1.0 / y_scale);
2985
2986 extent_x_scale = x_scale;
2987 extent_y_scale = y_scale;
2988 }
2989
2990 {
2991 /* compute width / height */
2992 cairo_box_t bbox;
2993 double x1, y1, x2, y2;
2994 double x_scale, y_scale;
2995
2996 /* Compute extents.x/y/width/height from recording_surface,
2997 * in font space.
2998 */
2999 status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
3000 &bbox,
3001 &extent_scale);
3002 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3003 return status;
3004
3005 _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
3006
3007 x_scale = extent_x_scale;
3008 y_scale = extent_y_scale;
3009 extents->x_bearing = x1 * x_scale;
3010 extents->y_bearing = y1 * y_scale;
3011 extents->width = (x2 - x1) * x_scale;
3012 extents->height = (y2 - y1) * y_scale;
3013 }
3014
3015 if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
3016 extents->x_advance = _cairo_lround (extents->x_advance / snap_x_scale) * snap_x_scale;
3017 extents->y_advance = _cairo_lround (extents->y_advance / snap_y_scale) * snap_y_scale;
3018 }
3019
3020 return status;
3021#else
3022 return CAIRO_INT_STATUS_UNSUPPORTED;
3023#endif
3024}
3025
3026static cairo_int_status_t
3027_cairo_ft_scaled_glyph_init_record_svg_glyph (cairo_ft_scaled_font_t *scaled_font,
3028 cairo_scaled_glyph_t *scaled_glyph,
3029 FT_Face face,
3030 const cairo_color_t *foreground_color,
3031 cairo_text_extents_t *extents)
3032{
3033#if HAVE_FT_SVG_DOCUMENT
3034 cairo_status_t status = CAIRO_STATUS_SUCCESS;
3035 cairo_surface_t *recording_surface;
3036 cairo_t *cr;
3037 FT_SVG_Document svg_doc = face->glyph->other;
3038 char *svg_document;
3039 FT_Color *palette;
3040 unsigned int num_palette_entries;
3041 cairo_bool_t foreground_source_used = FALSE0;
3042
3043 /* Create NULL terminated SVG document */
3044 svg_document = _cairo_strndupstrndup ((const char*)svg_doc->svg_document, svg_doc->svg_document_length);
3045
3046 recording_surface =
3047 cairo_recording_surface_create_moz_cairo_recording_surface_create (CAIRO_CONTENT_COLOR_ALPHA, NULL((void*)0));
3048
3049 cr = cairo_create_moz_cairo_create (recording_surface);
3050
3051 if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
3052 cairo_matrix_t scale;
3053 scale = scaled_font->base.scale;
3054 scale.x0 = scale.y0 = 0.;
3055 cairo_set_matrix_moz_cairo_set_matrix (cr, &scale);
3056 }
3057
3058 cairo_set_font_size_moz_cairo_set_font_size (cr, 1.0);
3059 cairo_set_font_options_moz_cairo_set_font_options (cr, &scaled_font->base.options);
3060
3061 extents->x_bearing = DOUBLE_FROM_26_6(face->bbox.xMin)((double)(face->bbox.xMin) / 64.0);
3062 extents->y_bearing = DOUBLE_FROM_26_6(face->bbox.yMin)((double)(face->bbox.yMin) / 64.0);
3063 extents->width = DOUBLE_FROM_26_6(face->bbox.xMax)((double)(face->bbox.xMax) / 64.0) - extents->x_bearing;
3064 extents->height = DOUBLE_FROM_26_6(face->bbox.yMax)((double)(face->bbox.yMax) / 64.0) - extents->y_bearing;
3065
3066 _cairo_ft_scaled_glyph_set_palette (scaled_font, face, &num_palette_entries, &palette);
3067
3068 if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
3069 cairo_pattern_t *foreground_pattern = _cairo_pattern_create_solid (foreground_color);
3070 status = _cairo_render_svg_glyph (svg_document,
3071 svg_doc->start_glyph_id,
3072 svg_doc->end_glyph_id,
3073 _cairo_scaled_glyph_index(scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
3074 svg_doc->units_per_EM,
3075 palette,
3076 num_palette_entries,
3077 cr,
3078 foreground_pattern,
3079 &foreground_source_used);
3080 cairo_pattern_destroy_moz_cairo_pattern_destroy (foreground_pattern);
3081 if (status == CAIRO_STATUS_SUCCESS)
3082 status = cairo_status_moz_cairo_status (cr);
3083 }
3084
3085 cairo_destroy_moz_cairo_destroy (cr);
3086 free (svg_document);
3087
3088 if (status) {
3089 cairo_surface_destroy_moz_cairo_surface_destroy (recording_surface);
3090 scaled_glyph->color_glyph = FALSE0;
3091 scaled_glyph->color_glyph_set = TRUE1;
3092 return status;
3093 }
3094
3095 _cairo_scaled_glyph_set_recording_surface (scaled_glyph,
3096 &scaled_font->base,
3097 recording_surface,
3098 foreground_source_used ? foreground_color : NULL((void*)0));
3099
3100 scaled_glyph->color_glyph = TRUE1;
3101 scaled_glyph->color_glyph_set = TRUE1;
3102
3103 /* get metrics */
3104
3105 /* Copied from cairo-user-font.c */
3106 cairo_matrix_t extent_scale;
3107 double extent_x_scale;
3108 double extent_y_scale;
3109 double snap_x_scale;
3110 double snap_y_scale;
3111 double fixed_scale, x_scale, y_scale;
3112
3113 extent_scale = scaled_font->base.scale_inverse;
3114 snap_x_scale = 1.0;
3115 snap_y_scale = 1.0;
3116 status = _cairo_matrix_compute_basis_scale_factors (&extent_scale,
3117 &x_scale, &y_scale,
3118 1);
3119 if (status == CAIRO_STATUS_SUCCESS) {
3120 if (x_scale == 0)
3121 x_scale = 1;
3122 if (y_scale == 0)
3123 y_scale = 1;
3124
3125 snap_x_scale = x_scale;
3126 snap_y_scale = y_scale;
3127
3128 /* since glyphs are pretty much 1.0x1.0, we can reduce error by
3129 * scaling to a larger square. say, 1024.x1024. */
3130 fixed_scale = 1024;
3131 x_scale /= fixed_scale;
3132 y_scale /= fixed_scale;
3133
3134 cairo_matrix_scale_moz_cairo_matrix_scale (&extent_scale, 1.0 / x_scale, 1.0 / y_scale);
3135
3136 extent_x_scale = x_scale;
3137 extent_y_scale = y_scale;
3138 }
3139
3140 {
3141 /* compute width / height */
3142 cairo_box_t bbox;
3143 double x1, y1, x2, y2;
3144 double x_scale, y_scale;
3145
3146 /* Compute extents.x/y/width/height from recording_surface,
3147 * in font space.
3148 */
3149 status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
3150 &bbox,
3151 &extent_scale);
3152 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3153 return status;
3154
3155 _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
3156
3157 x_scale = extent_x_scale;
3158 y_scale = extent_y_scale;
3159 extents->x_bearing = x1 * x_scale;
3160 extents->y_bearing = y1 * y_scale;
3161 extents->width = (x2 - x1) * x_scale;
3162 extents->height = (y2 - y1) * y_scale;
3163 }
3164
3165 if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
3166 extents->x_advance = _cairo_lround (extents->x_advance / snap_x_scale) * snap_x_scale;
3167 extents->y_advance = _cairo_lround (extents->y_advance / snap_y_scale) * snap_y_scale;
3168 }
3169
3170 return status;
3171#else
3172 return CAIRO_INT_STATUS_UNSUPPORTED;
3173#endif
3174}
3175
3176static cairo_int_status_t
3177_cairo_ft_scaled_glyph_init_surface_for_recording_surface (cairo_ft_scaled_font_t *scaled_font,
3178 cairo_scaled_glyph_t *scaled_glyph,
3179 const cairo_color_t *foreground_color)
3180{
3181 cairo_surface_t *surface;
3182 int width, height;
3183 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
3184 cairo_bool_t foreground_used;
3185
3186 width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
3187 _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
3188 height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
3189 _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
3190
3191 surface = cairo_image_surface_create_moz_cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
3192
3193 cairo_surface_set_device_offset_moz_cairo_surface_set_device_offset (surface,
3194 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
3195 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
3196
3197 status = _cairo_recording_surface_replay_with_foreground_color (scaled_glyph->recording_surface,
3198 surface,
3199 foreground_color,
3200 &foreground_used);
3201 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
3202 cairo_surface_destroy_moz_cairo_surface_destroy(surface);
3203 return status;
3204 }
3205
3206 _cairo_scaled_glyph_set_color_surface (scaled_glyph,
3207 &scaled_font->base,
3208 (cairo_image_surface_t *)surface,
3209 foreground_used ? foreground_color : NULL((void*)0));
3210 surface = NULL((void*)0);
3211
3212 if (surface)
3213 cairo_surface_destroy_moz_cairo_surface_destroy (surface);
3214
3215 return status;
3216}
3217
3218static void
3219_cairo_ft_scaled_glyph_get_metrics (cairo_ft_scaled_font_t *scaled_font,
3220 FT_Face face,
3221 cairo_bool_t vertical_layout,
3222 int load_flags,
3223 cairo_text_extents_t *fs_metrics)
3224{
3225 FT_Glyph_Metrics *metrics;
3226 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3227 cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF;
3228 FT_GlyphSlot glyph = face->glyph;
3229
3230 /*
3231 * Compute font-space metrics
3232 */
3233 metrics = &glyph->metrics;
3234
3235 /*
3236 * Note: Y coordinates of the horizontal bearing need to be negated.
3237 *
3238 * Scale metrics back to glyph space from the scaled glyph space returned
3239 * by FreeType
3240 *
3241 * If we want hinted metrics but aren't asking for hinted glyphs from
3242 * FreeType, then we need to do the metric hinting ourselves.
3243 */
3244
3245 if (hint_metrics && (load_flags & FT_LOAD_NO_HINTING( 1L << 1 )))
3246 {
3247 FT_Pos x1, x2;
3248 FT_Pos y1, y2;
3249 FT_Pos advance;
3250
3251 if (!vertical_layout) {
3252 x1 = (metrics->horiBearingX) & -64;
3253 x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
3254 y1 = (-metrics->horiBearingY) & -64;
3255 y2 = (-metrics->horiBearingY + metrics->height + 63) & -64;
3256
3257 advance = ((metrics->horiAdvance + 32) & -64);
3258
3259 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))
;
3260 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))
;
3261
3262 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))
;
3263 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))
;
3264
3265 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))
;
3266 fs_metrics->y_advance = 0;
3267 } else {
3268 x1 = (metrics->vertBearingX) & -64;
3269 x2 = (metrics->vertBearingX + metrics->width + 63) & -64;
3270 y1 = (metrics->vertBearingY) & -64;
3271 y2 = (metrics->vertBearingY + metrics->height + 63) & -64;
3272
3273 advance = ((metrics->vertAdvance + 32) & -64);
3274
3275 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))
;
3276 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))
;
3277
3278 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))
;
3279 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))
;
3280
3281 fs_metrics->x_advance = 0;
3282 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))
;
3283 }
3284 } else {
3285 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))
;
3286 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))
;
3287
3288 if (!vertical_layout) {
3289 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))
;
3290 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))
;
3291
3292 if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
3293 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))
;
3294 else
3295 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))
;
3296 fs_metrics->y_advance = 0;
3297 } else {
3298 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))
;
3299 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))
;
3300
3301 fs_metrics->x_advance = 0;
3302 if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
3303 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))
;
3304 else
3305 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))
;
3306 }
3307 }
3308}
3309
3310static cairo_bool_t
3311_cairo_ft_scaled_glyph_is_colr_v0 (cairo_ft_scaled_font_t *scaled_font,
3312 cairo_scaled_glyph_t *scaled_glyph,
3313 FT_Face face)
3314{
3315#ifdef FT_COLOR_H<freetype/ftcolor.h>
3316 FT_LayerIterator iterator;
3317 FT_UInt layer_glyph_index;
3318 FT_UInt layer_color_index;
3319
3320 iterator.p = NULL((void*)0);
3321 if (FT_Get_Color_Glyph_Layer(face,
3322 _cairo_scaled_glyph_index (scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
3323 &layer_glyph_index,
3324 &layer_color_index,
3325 &iterator) == 1)
3326 {
3327 return TRUE1;
3328 }
3329#endif
3330 return FALSE0;
3331}
3332
3333static cairo_bool_t
3334_cairo_ft_scaled_glyph_is_colr_v1 (cairo_ft_scaled_font_t *scaled_font,
3335 cairo_scaled_glyph_t *scaled_glyph,
3336 FT_Face face)
3337{
3338#if HAVE_FT_COLR_V1
3339 FT_OpaquePaint paint = { NULL((void*)0), 0 };
3340
3341 if (FT_Get_Color_Glyph_Paint (face,
3342 _cairo_scaled_glyph_index (scaled_glyph)((unsigned long)((scaled_glyph)->hash_entry.hash & 0xffffff
))
,
3343 FT_COLOR_INCLUDE_ROOT_TRANSFORM,
3344 &paint) == 1)
3345 {
3346 return TRUE1;
3347 }
3348#endif
3349 return FALSE0;
3350}
3351
3352static cairo_int_status_t
3353_cairo_ft_scaled_glyph_init_metrics (cairo_ft_scaled_font_t *scaled_font,
3354 cairo_scaled_glyph_t *scaled_glyph,
3355 FT_Face face,
3356 cairo_bool_t vertical_layout,
3357 int load_flags,
3358 const cairo_color_t *foreground_color)
3359{
3360 cairo_int_status_t status = CAIRO_INT_STATUS_SUCCESS;
3361 cairo_text_extents_t fs_metrics;
3362 cairo_ft_glyph_private_t *glyph_priv;
3363
3364 cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF;
3365
3366 /* _cairo_ft_scaled_glyph_init_metrics() is called once the first
3367 * time a cairo_scaled_glyph_t is created. We first allocate the
3368 * cairo_ft_glyph_private_t struct and determine the glyph type.
3369 */
3370
3371 glyph_priv = _cairo_calloc (sizeof (*glyph_priv))((sizeof (*glyph_priv)) != 0 ? calloc(1,sizeof (*glyph_priv))
: ((void*)0))
;
3372 if (unlikely (glyph_priv == NULL)(__builtin_expect (!!(glyph_priv == ((void*)0)), 0)))
3373 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3374
3375 _cairo_scaled_glyph_attach_private (scaled_glyph, &glyph_priv->base,
3376 &ft_glyph_private_key,
3377 _cairo_ft_glyph_fini);
3378
3379 /* We need to load color to determine if this is a color format. */
3380 int color_flag = 0;
3381
3382 if (scaled_font->unscaled->have_color && scaled_font->base.options.color_mode != CAIRO_COLOR_MODE_NO_COLOR)
3383 color_flag = FT_LOAD_COLOR( 1L << 20 );
3384
3385 /* Ensure use_em_size = FALSE as the format (bitmap or outline)
3386 * may change with the size. */
3387 status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3388 scaled_glyph,
3389 face,
3390 load_flags | color_flag,
3391 FALSE0,
3392 vertical_layout);
3393 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3394 return status;
3395
3396 cairo_bool_t is_svg_format = FALSE0;
3397#if HAVE_FT_SVG_DOCUMENT
3398 if (face->glyph->format == FT_GLYPH_FORMAT_SVG)
3399 is_svg_format = TRUE1;
3400#endif
3401
3402 if (is_svg_format) {
3403 glyph_priv->format = CAIRO_FT_GLYPH_TYPE_SVG;
3404
3405#if defined(HAVE_FT_COLR_V1) && defined(HAVE_FT_LOAD_NO_SVG)
3406 /* Prefer COLRv1 table over SVG table due to performance reasons for now */
3407 if (_cairo_ft_scaled_glyph_is_colr_v1 (scaled_font, scaled_glyph, face)) {
3408 glyph_priv->format = CAIRO_FT_GLYPH_TYPE_COLR_V1;
3409 }
3410#endif
3411
3412 } else if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
3413 glyph_priv->format = CAIRO_FT_GLYPH_TYPE_OUTLINE;
3414 if (color_flag) {
3415 if (_cairo_ft_scaled_glyph_is_colr_v1 (scaled_font, scaled_glyph, face))
3416 glyph_priv->format = CAIRO_FT_GLYPH_TYPE_COLR_V1;
3417 else if (_cairo_ft_scaled_glyph_is_colr_v0 (scaled_font, scaled_glyph, face))
3418 glyph_priv->format = CAIRO_FT_GLYPH_TYPE_COLR_V0;
3419 }
3420 } else {
3421 /* For anything else we let FreeType render a bitmap. */
3422 glyph_priv->format = CAIRO_FT_GLYPH_TYPE_BITMAP;
3423 }
3424
3425 /* If hinting is off, load the glyph with font size set the the em size. */
3426 if (!hint_metrics) {
3427 status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3428 scaled_glyph,
3429 face,
3430 load_flags | color_flag,
3431 TRUE1,
3432 vertical_layout);
3433 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3434 return status;
3435 }
3436
3437 _cairo_ft_scaled_glyph_get_metrics (scaled_font,
3438 face,
3439 vertical_layout,
3440 load_flags,
3441 &fs_metrics);
3442
3443
3444 /* SVG and COLRv1 glyphs require the bounding box to be obtained
3445 * from the ink extents of the rendering. We need to render glyph
3446 * to a recording surface to obtain these extents. But we also
3447 * need the advance from _cairo_ft_scaled_glyph_get_metrics()
3448 * before calling this function.
3449 */
3450
3451 if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG) {
3452 status = (cairo_int_status_t)_cairo_ft_scaled_glyph_init_record_svg_glyph (scaled_font,
3453 scaled_glyph,
3454 face,
3455 foreground_color,
3456 &fs_metrics);
3457 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3458 return status;
3459 }
3460
3461 if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) {
3462 /* Restore font size if previously loaded at em_size. */
3463 if (!hint_metrics) {
3464 status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3465 scaled_glyph,
3466 face,
3467 load_flags | color_flag,
3468 FALSE0,
3469 vertical_layout);
3470 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3471 return status;
3472 }
3473
3474 status = (cairo_int_status_t)_cairo_ft_scaled_glyph_init_record_colr_v1_glyph (scaled_font,
3475 scaled_glyph,
3476 face,
3477 foreground_color,
3478 &fs_metrics);
3479 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3480 return status;
3481 }
3482
3483 _cairo_scaled_glyph_set_metrics (scaled_glyph,
3484 &scaled_font->base,
3485 &fs_metrics);
3486
3487 return status;
3488}
3489
3490static cairo_int_status_t
3491_cairo_ft_scaled_glyph_init (void *abstract_font,
3492 cairo_scaled_glyph_t *scaled_glyph,
3493 cairo_scaled_glyph_info_t info,
3494 const cairo_color_t *foreground_color)
3495{
3496 cairo_ft_scaled_font_t *scaled_font = abstract_font;
3497 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3498 FT_Face face;
3499 int load_flags = scaled_font->ft_options.load_flags;
3500 cairo_bool_t vertical_layout = FALSE0;
3501 cairo_status_t status = CAIRO_STATUS_SUCCESS;
3502 cairo_ft_glyph_private_t *glyph_priv;
3503
3504 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3505 if (!face)
3506 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3507
3508 /* Ignore global advance unconditionally */
3509 load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH( 1L << 9 );
3510
3511 if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
3512 (info & (CAIRO_SCALED_GLYPH_INFO_SURFACE |
3513 CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE)) == 0) {
3514 load_flags |= FT_LOAD_NO_BITMAP( 1L << 3 );
3515 }
3516
3517 /*
3518 * Don't pass FT_LOAD_VERTICAL_LAYOUT to FT_Load_Glyph here as
3519 * suggested by freetype people.
3520 */
3521 if (load_flags & FT_LOAD_VERTICAL_LAYOUT( 1L << 4 )) {
3522 load_flags &= ~FT_LOAD_VERTICAL_LAYOUT( 1L << 4 );
3523 vertical_layout = TRUE1;
3524 }
3525
3526 /* Metrics will always be requested when a scaled glyph is created */
3527 if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
3528 status = _cairo_ft_scaled_glyph_init_metrics (scaled_font,
3529 scaled_glyph,
3530 face,
3531 vertical_layout,
3532 load_flags,
3533 foreground_color);
3534 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3535 goto FAIL;
3536 }
3537
3538 glyph_priv = (cairo_ft_glyph_private_t *) _cairo_scaled_glyph_find_private (scaled_glyph,
3539 &ft_glyph_private_key);
3540 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"
, 3540, __extension__ __PRETTY_FUNCTION__); }))
;
3541
3542 if (info & CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE) {
3543 status = CAIRO_INT_STATUS_UNSUPPORTED;
3544 if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG ||
3545 glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V0 ||
3546 glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1)
3547 {
3548 status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3549 scaled_glyph,
3550 face,
3551 load_flags | FT_LOAD_COLOR( 1L << 20 ),
3552 FALSE0,
3553 vertical_layout);
3554 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3555 goto FAIL;
3556
3557 if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG) {
3558 status = _cairo_ft_scaled_glyph_init_record_svg_glyph (scaled_font,
3559 scaled_glyph,
3560 face,
3561 foreground_color,
3562 &scaled_glyph->fs_metrics);
3563 } else if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1) {
3564 status = _cairo_ft_scaled_glyph_init_record_colr_v1_glyph (scaled_font,
3565 scaled_glyph,
3566 face,
3567 foreground_color,
3568 &scaled_glyph->fs_metrics);
3569 } else if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V0) {
3570 status = _cairo_ft_scaled_glyph_init_record_colr_v0_glyph (scaled_font,
3571 scaled_glyph,
3572 face,
3573 vertical_layout,
3574 load_flags);
3575 }
3576 }
3577 if (status)
3578 goto FAIL;
3579 }
3580
3581 if ((info & CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE) && scaled_font->base.options.color_mode != CAIRO_COLOR_MODE_NO_COLOR) {
3582 if (glyph_priv->format == CAIRO_FT_GLYPH_TYPE_SVG ||
3583 glyph_priv->format == CAIRO_FT_GLYPH_TYPE_COLR_V1)
3584 {
3585 status = _cairo_ft_scaled_glyph_init_surface_for_recording_surface (scaled_font,
3586 scaled_glyph,
3587 foreground_color);
3588 } else {
3589 status = _cairo_ft_scaled_glyph_init_surface (scaled_font,
3590 scaled_glyph,
3591 glyph_priv,
3592 CAIRO_SCALED_GLYPH_INFO_COLOR_SURFACE,
3593 face,
3594 foreground_color,
3595 vertical_layout,
3596 load_flags);
3597 }
3598 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3599 goto FAIL;
3600 }
3601
3602 if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
3603 status = _cairo_ft_scaled_glyph_init_surface (scaled_font,
3604 scaled_glyph,
3605 glyph_priv,
3606 CAIRO_SCALED_GLYPH_INFO_SURFACE,
3607 face,
3608 NULL((void*)0), /* foreground color */
3609 vertical_layout,
3610 load_flags);
3611 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3612 goto FAIL;
3613 }
3614
3615 if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
3616 cairo_path_fixed_t *path = NULL((void*)0); /* hide compiler warning */
3617
3618 /* Load non-color glyph */
3619 status = _cairo_ft_scaled_glyph_load_glyph (scaled_font,
3620 scaled_glyph,
3621 face,
3622 load_flags,
3623 FALSE0,
3624 vertical_layout);
3625 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3626 goto FAIL;
3627
3628 if (face->glyph->format == FT_GLYPH_FORMAT_OUTLINE)
3629 status = _cairo_ft_face_decompose_glyph_outline (face, &path);
3630 else
3631 status = CAIRO_INT_STATUS_UNSUPPORTED;
3632
3633 if (unlikely (status)(__builtin_expect (!!(status), 0)))
3634 goto FAIL;
3635
3636 _cairo_scaled_glyph_set_path (scaled_glyph,
3637 &scaled_font->base,
3638 path);
3639 }
3640 FAIL:
3641 _cairo_ft_unscaled_font_unlock_face (unscaled);
3642
3643 return status;
3644}
3645
3646static unsigned long
3647_cairo_ft_ucs4_to_index (void *abstract_font,
3648 uint32_t ucs4)
3649{
3650 cairo_ft_scaled_font_t *scaled_font = abstract_font;
3651 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3652 FT_Face face;
3653 FT_UInt index;
3654
3655 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3656 if (!face)
3657 return 0;
3658
3659#if CAIRO_HAS_FC_FONT1
3660 index = FcFreeTypeCharIndex (face, ucs4);
3661#else
3662 index = FT_Get_Char_Index (face, ucs4);
3663#endif
3664
3665 _cairo_ft_unscaled_font_unlock_face (unscaled);
3666 return index;
3667}
3668
3669static cairo_int_status_t
3670_cairo_ft_load_truetype_table (void *abstract_font,
3671 unsigned long tag,
3672 long offset,
3673 unsigned char *buffer,
3674 unsigned long *length)
3675{
3676 cairo_ft_scaled_font_t *scaled_font = abstract_font;
3677 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3678 FT_Face face;
3679 cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
3680
3681 /* We don't support the FreeType feature of loading a table
3682 * without specifying the size since this may overflow our
3683 * buffer. */
3684 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", 3684
, __extension__ __PRETTY_FUNCTION__); }))
;
3685
3686 if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base))
3687 return CAIRO_INT_STATUS_UNSUPPORTED;
3688
3689 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3690 if (!face)
3691 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3692
3693 if (FT_IS_SFNT (face)( !!( (face)->face_flags & ( 1L << 3 ) ) )) {
3694 if (buffer == NULL((void*)0))
3695 *length = 0;
3696
3697 if (FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0)
3698 status = CAIRO_STATUS_SUCCESS;
3699 }
3700
3701 _cairo_ft_unscaled_font_unlock_face (unscaled);
3702
3703 return status;
3704}
3705
3706static cairo_int_status_t
3707_cairo_ft_index_to_ucs4(void *abstract_font,
3708 unsigned long index,
3709 uint32_t *ucs4)
3710{
3711 cairo_ft_scaled_font_t *scaled_font = abstract_font;
3712 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3713 FT_Face face;
3714 FT_ULong charcode;
3715 FT_UInt gindex;
3716
3717 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3718 if (!face)
3719 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3720
3721 *ucs4 = (uint32_t) -1;
3722 charcode = FT_Get_First_Char(face, &gindex);
3723 while (gindex != 0) {
3724 if (gindex == index) {
3725 *ucs4 = charcode;
3726 break;
3727 }
3728 charcode = FT_Get_Next_Char (face, charcode, &gindex);
3729 }
3730
3731 _cairo_ft_unscaled_font_unlock_face (unscaled);
3732
3733 return CAIRO_STATUS_SUCCESS;
3734}
3735
3736static cairo_int_status_t
3737_cairo_ft_is_synthetic (void *abstract_font,
3738 cairo_bool_t *is_synthetic)
3739{
3740 cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
3741 cairo_ft_scaled_font_t *scaled_font = abstract_font;
3742 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3743 FT_Face face;
3744 FT_Error error;
3745
3746 static GetVarFunc getVar;
3747 static DoneVarFunc doneVar;
3748 static GetVarBlendCoordsFunc getVarBlendCoords;
3749
3750 static int firstTime = 1;
3751 if (firstTime) {
3752 getVar = (GetVarFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Get_MM_Var");
3753 doneVar = (DoneVarFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Done_MM_Var");
3754 getVarBlendCoords = (GetVarBlendCoordsFunc) dlsym (RTLD_DEFAULT((void *) 0), "FT_Get_Var_Blend_Coordinates");
3755 firstTime = 0;
3756 }
3757
3758 if (scaled_font->ft_options.synth_flags != 0) {
3759 *is_synthetic = TRUE1;
3760 return status;
3761 }
3762
3763 *is_synthetic = FALSE0;
3764 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3765 if (!face)
3766 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3767
3768 if (face->face_flags & FT_FACE_FLAG_MULTIPLE_MASTERS( 1L << 8 )) {
3769 FT_MM_Var *mm_var = NULL((void*)0);
3770 FT_Fixed *coords = NULL((void*)0);
3771 int num_axis;
3772 int i;
3773
3774 /* If this is an MM or variable font we can't assume the current outlines
3775 * are the same as the font tables */
3776 *is_synthetic = TRUE1;
3777
3778 error = getVar ? (*getVar) (face, &mm_var) : -1;
3779 if (error) {
3780 status = _cairo_error (_cairo_ft_to_cairo_error (error));
3781 goto cleanup;
3782 }
3783
3784 num_axis = mm_var->num_axis;
3785 coords = _cairo_malloc_ab (num_axis, sizeof(FT_Fixed));
3786 if (!coords) {
3787 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
3788 goto cleanup;
3789 }
3790
3791 /* Check if the current design coordinates are the default
3792 * coordinates. In this case the current outlines match the
3793 * font tables.
3794 */
3795 if (getVarBlendCoords) {
3796 (*getVarBlendCoords) (face, num_axis, coords);
3797 *is_synthetic = FALSE0;
3798 for (i = 0; i < num_axis; i++) {
3799 if (coords[i]) {
3800 *is_synthetic = TRUE1;
3801 break;
3802 }
3803 }
3804 }
3805
3806 cleanup:
3807 free (coords);
3808 if (doneVar)
3809 (*doneVar) (face->glyph->library, mm_var);
3810 else
3811 free (mm_var);
3812 }
3813
3814 _cairo_ft_unscaled_font_unlock_face (unscaled);
3815
3816 return status;
3817}
3818
3819static cairo_int_status_t
3820_cairo_index_to_glyph_name (void *abstract_font,
3821 char **glyph_names,
3822 int num_glyph_names,
3823 unsigned long glyph_index,
3824 unsigned long *glyph_array_index)
3825{
3826 cairo_ft_scaled_font_t *scaled_font = abstract_font;
3827 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3828 FT_Face face;
3829 char buffer[256]; /* PLRM specifies max name length of 127 */
3830 FT_Error error;
3831 int i;
3832
3833 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3834 if (!face)
3835 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3836
3837 error = FT_Get_Glyph_Name (face, glyph_index, buffer, sizeof buffer);
3838
3839 _cairo_ft_unscaled_font_unlock_face (unscaled);
3840
3841 if (error != FT_Err_Ok) {
3842 /* propagate fatal errors from FreeType */
3843 if (error == FT_Err_Out_Of_Memory)
3844 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3845
3846 return CAIRO_INT_STATUS_UNSUPPORTED;
3847 }
3848
3849 /* FT first numbers the glyphs in the order they are read from the
3850 * Type 1 font. Then if .notdef is not the first glyph, the first
3851 * glyph is swapped with .notdef to ensure that .notdef is at
3852 * glyph index 0.
3853 *
3854 * As all but two glyphs in glyph_names already have the same
3855 * index as the FT glyph index, we first check if
3856 * glyph_names[glyph_index] is the name we are looking for. If not
3857 * we fall back to searching the entire array.
3858 */
3859
3860 if ((long)glyph_index < num_glyph_names &&
3861 strcmp (glyph_names[glyph_index], buffer) == 0)
3862 {
3863 *glyph_array_index = glyph_index;
3864
3865 return CAIRO_STATUS_SUCCESS;
3866 }
3867
3868 for (i = 0; i < num_glyph_names; i++) {
3869 if (strcmp (glyph_names[i], buffer) == 0) {
3870 *glyph_array_index = i;
3871
3872 return CAIRO_STATUS_SUCCESS;
3873 }
3874 }
3875
3876 return CAIRO_INT_STATUS_UNSUPPORTED;
3877}
3878
3879static cairo_bool_t
3880_ft_is_type1 (FT_Face face)
3881{
3882 const char *font_format = FT_Get_Font_Format (face);
3883 if (font_format &&
3884 (strcmp (font_format, "Type 1") == 0 ||
3885 strcmp (font_format, "CFF") == 0))
3886 {
3887 return TRUE1;
3888 }
3889
3890 return FALSE0;
3891}
3892
3893static cairo_int_status_t
3894_cairo_ft_load_type1_data (void *abstract_font,
3895 long offset,
3896 unsigned char *buffer,
3897 unsigned long *length)
3898{
3899 cairo_ft_scaled_font_t *scaled_font = abstract_font;
3900 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
3901 FT_Face face;
3902 cairo_status_t status = CAIRO_STATUS_SUCCESS;
3903 unsigned long available_length;
3904 unsigned long ret;
3905
3906 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", 3906
, __extension__ __PRETTY_FUNCTION__); }))
;
3907
3908 if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base))
3909 return CAIRO_INT_STATUS_UNSUPPORTED;
3910
3911 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3912 if (!face)
3913 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3914
3915 if (FT_IS_SFNT (face)( !!( (face)->face_flags & ( 1L << 3 ) ) )) {
3916 status = CAIRO_INT_STATUS_UNSUPPORTED;
3917 goto unlock;
3918 }
3919
3920 if (! _ft_is_type1 (face)) {
3921 status = CAIRO_INT_STATUS_UNSUPPORTED;
3922 goto unlock;
3923 }
3924
3925 available_length = MAX (face->stream->size - offset, 0)((face->stream->size - offset) > (0) ? (face->stream
->size - offset) : (0))
;
3926 if (!buffer) {
3927 *length = available_length;
3928 } else {
3929 if (*length > available_length) {
3930 status = CAIRO_INT_STATUS_UNSUPPORTED;
3931 } else if (face->stream->read != NULL((void*)0)) {
3932 /* Note that read() may be implemented as a macro, thanks POSIX!, so we
3933 * need to wrap the following usage in parentheses in order to
3934 * disambiguate it for the pre-processor - using the verbose function
3935 * pointer dereference for clarity.
3936 */
3937 ret = (* face->stream->read) (face->stream,
3938 offset,
3939 buffer,
3940 *length);
3941 if (ret != *length)
3942 status = _cairo_error (CAIRO_STATUS_READ_ERROR);
3943 } else {
3944 memcpy (buffer, face->stream->base + offset, *length);
3945 }
3946 }
3947
3948 unlock:
3949 _cairo_ft_unscaled_font_unlock_face (unscaled);
3950
3951 return status;
3952}
3953
3954static cairo_bool_t
3955_cairo_ft_has_color_glyphs (void *scaled)
3956{
3957 cairo_ft_unscaled_font_t *unscaled = ((cairo_ft_scaled_font_t *)scaled)->unscaled;
3958
3959 if (!unscaled->have_color_set) {
3960 FT_Face face;
3961 face = _cairo_ft_unscaled_font_lock_face (unscaled);
3962 if (unlikely (face == NULL)(__builtin_expect (!!(face == ((void*)0)), 0)))
3963 return FALSE0;
3964 _cairo_ft_unscaled_font_unlock_face (unscaled);
3965 }
3966
3967 return unscaled->have_color;
3968}
3969
3970static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
3971 CAIRO_FONT_TYPE_FT,
3972 _cairo_ft_scaled_font_fini,
3973 _cairo_ft_scaled_glyph_init,
3974 NULL((void*)0), /* text_to_glyphs */
3975 _cairo_ft_ucs4_to_index,
3976 _cairo_ft_load_truetype_table,
3977 _cairo_ft_index_to_ucs4,
3978 _cairo_ft_is_synthetic,
3979 _cairo_index_to_glyph_name,
3980 _cairo_ft_load_type1_data,
3981 _cairo_ft_has_color_glyphs
3982};
3983
3984/* #cairo_ft_font_face_t */
3985
3986#if CAIRO_HAS_FC_FONT1
3987static cairo_font_face_t *
3988_cairo_ft_font_face_create_for_pattern (FcPattern *pattern);
3989
3990static cairo_status_t
3991_cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t *toy_face,
3992 cairo_font_face_t **font_face_out)
3993{
3994 cairo_font_face_t *font_face = (cairo_font_face_t *) &_cairo_font_face_nil;
3995 FcPattern *pattern;
3996 int fcslant;
3997 int fcweight;
3998
3999 pattern = FcPatternCreate ();
4000 if (!pattern) {
4001 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4002 return font_face->status;
4003 }
4004
4005 if (!FcPatternAddString (pattern,
4006 FC_FAMILY"family", (unsigned char *) toy_face->family))
4007 {
4008 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4009 goto FREE_PATTERN;
4010 }
4011
4012 switch (toy_face->slant)
4013 {
4014 case CAIRO_FONT_SLANT_ITALIC:
4015 fcslant = FC_SLANT_ITALIC100;
4016 break;
4017 case CAIRO_FONT_SLANT_OBLIQUE:
4018 fcslant = FC_SLANT_OBLIQUE110;
4019 break;
4020 case CAIRO_FONT_SLANT_NORMAL:
4021 default:
4022 fcslant = FC_SLANT_ROMAN0;
4023 break;
4024 }
4025
4026 if (!FcPatternAddInteger (pattern, FC_SLANT"slant", fcslant)) {
4027 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4028 goto FREE_PATTERN;
4029 }
4030
4031 switch (toy_face->weight)
4032 {
4033 case CAIRO_FONT_WEIGHT_BOLD:
4034 fcweight = FC_WEIGHT_BOLD200;
4035 break;
4036 case CAIRO_FONT_WEIGHT_NORMAL:
4037 default:
4038 fcweight = FC_WEIGHT_MEDIUM100;
4039 break;
4040 }
4041
4042 if (!FcPatternAddInteger (pattern, FC_WEIGHT"weight", fcweight)) {
4043 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4044 goto FREE_PATTERN;
4045 }
4046
4047 font_face = _cairo_ft_font_face_create_for_pattern (pattern);
4048
4049 FREE_PATTERN:
4050 FcPatternDestroy (pattern);
4051
4052 *font_face_out = font_face;
4053 return font_face->status;
4054}
4055#endif
4056
4057static cairo_bool_t
4058_cairo_ft_font_face_destroy (void *abstract_face)
4059{
4060 cairo_ft_font_face_t *font_face = abstract_face;
4061
4062 /* When destroying a face created by cairo_ft_font_face_create_for_ft_face,
4063 * we have a special "zombie" state for the face when the unscaled font
4064 * is still alive but there are no other references to a font face with
4065 * the same FT_Face.
4066 *
4067 * We go from:
4068 *
4069 * font_face ------> unscaled
4070 * <-....weak....../
4071 *
4072 * To:
4073 *
4074 * font_face <------- unscaled
4075 */
4076
4077 if (font_face->unscaled) {
4078 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
)))
;
4079
4080 if (font_face->unscaled->from_face &&
4081 font_face->next == NULL((void*)0) &&
4082 font_face->unscaled->faces == font_face &&
4083 CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count)_cairo_atomic_int_get (&(&font_face->unscaled->
base.ref_count)->ref_count)
> 1)
4084 {
4085 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)))
;
4086 _cairo_unscaled_font_destroy (&font_face->unscaled->base);
4087 font_face->unscaled = NULL((void*)0);
4088
4089 return FALSE0;
4090 }
4091
4092 cairo_ft_font_face_t *tmp_face = NULL((void*)0);
4093 cairo_ft_font_face_t *last_face = NULL((void*)0);
4094
4095 /* Remove face from linked list */
4096 for (tmp_face = font_face->unscaled->faces;
4097 tmp_face;
4098 tmp_face = tmp_face->next)
4099 {
4100 if (tmp_face == font_face) {
4101 if (last_face)
4102 last_face->next = tmp_face->next;
4103 else
4104 font_face->unscaled->faces = tmp_face->next;
4105 }
4106
4107 last_face = tmp_face;
4108 }
4109
4110 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)))
;
4111 _cairo_unscaled_font_destroy (&font_face->unscaled->base);
4112 font_face->unscaled = NULL((void*)0);
4113 }
4114
4115 _cairo_ft_options_fini (&font_face->ft_options);
4116
4117#if CAIRO_HAS_FC_FONT1
4118 if (font_face->pattern) {
4119 FcPatternDestroy (font_face->pattern);
4120 cairo_font_face_destroy_moz_cairo_font_face_destroy (font_face->resolved_font_face);
4121 }
4122#endif
4123
4124 return TRUE1;
4125}
4126
4127static cairo_font_face_t *
4128_cairo_ft_font_face_get_implementation (void *abstract_face,
4129 const cairo_matrix_t *font_matrix,
4130 const cairo_matrix_t *ctm,
4131 const cairo_font_options_t *options)
4132{
4133 /* The handling of font options is different depending on how the
4134 * font face was created. When the user creates a font face with
4135 * cairo_ft_font_face_create_for_ft_face(), then the load flags
4136 * passed in augment the load flags for the options. But for
4137 * cairo_ft_font_face_create_for_pattern(), the load flags are
4138 * derived from a pattern where the user has called
4139 * cairo_ft_font_options_substitute(), so *just* use those load
4140 * flags and ignore the options.
4141 */
4142
4143#if CAIRO_HAS_FC_FONT1
4144 cairo_ft_font_face_t *font_face = abstract_face;
4145
4146 /* If we have an unresolved pattern, resolve it and create
4147 * unscaled font. Otherwise, use the ones stored in font_face.
4148 */
4149 if (font_face->pattern) {
4150 cairo_font_face_t *resolved;
4151
4152 /* Cache the resolved font whilst the FcConfig remains consistent. */
4153 resolved = font_face->resolved_font_face;
4154 if (resolved != NULL((void*)0)) {
4155 if (! FcInitBringUptoDate ()) {
4156 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4157 return (cairo_font_face_t *) &_cairo_font_face_nil;
4158 }
4159
4160 if (font_face->resolved_config == FcConfigGetCurrent ())
4161 return cairo_font_face_reference_moz_cairo_font_face_reference (resolved);
4162
4163 cairo_font_face_destroy_moz_cairo_font_face_destroy (resolved);
4164 font_face->resolved_font_face = NULL((void*)0);
4165 }
4166
4167 resolved = _cairo_ft_resolve_pattern (font_face->pattern,
4168 font_matrix,
4169 ctm,
4170 options);
4171 if (unlikely (resolved->status)(__builtin_expect (!!(resolved->status), 0)))
4172 return resolved;
4173
4174 font_face->resolved_font_face = cairo_font_face_reference_moz_cairo_font_face_reference (resolved);
4175 font_face->resolved_config = FcConfigGetCurrent ();
4176
4177 return resolved;
4178 }
4179#endif
4180
4181 return abstract_face;
4182}
4183
4184static void
4185_cairo_ft_font_face_lock (void *abstract_face)
4186{
4187 cairo_ft_font_face_t *font_face = abstract_face;
4188 if (font_face->unscaled) {
4189 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
)))
;
4190 }
4191}
4192
4193static void
4194_cairo_ft_font_face_unlock (void *abstract_face)
4195{
4196 cairo_ft_font_face_t *font_face = abstract_face;
4197 if (font_face->unscaled) {
4198 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)))
;
4199 }
4200}
4201
4202const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
4203 CAIRO_FONT_TYPE_FT,
4204#if CAIRO_HAS_FC_FONT1
4205 _cairo_ft_font_face_create_for_toy,
4206#else
4207 NULL((void*)0),
4208#endif
4209 _cairo_ft_font_face_destroy,
4210 _cairo_ft_font_face_scaled_font_create,
4211 _cairo_ft_font_face_get_implementation,
4212/*
4213 _cairo_ft_font_face_lock,
4214 _cairo_ft_font_face_unlock
4215*/
4216};
4217
4218#if CAIRO_HAS_FC_FONT1
4219static cairo_font_face_t *
4220_cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
4221{
4222 cairo_ft_font_face_t *font_face;
4223
4224 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))
;
4225 if (unlikely (font_face == NULL)(__builtin_expect (!!(font_face == ((void*)0)), 0))) {
4226 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4227 return (cairo_font_face_t *) &_cairo_font_face_nil;
4228 }
4229
4230 font_face->unscaled = NULL((void*)0);
4231
4232 _get_pattern_ft_options (pattern, &font_face->ft_options);
4233
4234 font_face->next = NULL((void*)0);
4235
4236 font_face->pattern = FcPatternDuplicate (pattern);
4237 if (unlikely (font_face->pattern == NULL)(__builtin_expect (!!(font_face->pattern == ((void*)0)), 0
))
) {
4238 free (font_face);
4239 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4240 return (cairo_font_face_t *) &_cairo_font_face_nil;
4241 }
4242
4243 font_face->resolved_font_face = NULL((void*)0);
4244 font_face->resolved_config = NULL((void*)0);
4245
4246 _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
4247
4248 return &font_face->base;
4249}
4250#endif
4251
4252static cairo_font_face_t *
4253_cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
4254 cairo_ft_options_t *ft_options)
4255{
4256 cairo_ft_font_face_t *font_face, **prev_font_face;
4257
4258 CAIRO_FT_LOCK (unscaled)((unscaled)->face_context ? (void)mozilla_LockSharedFTFace
((unscaled)->face_context, ((void*)0)) : (void)pthread_mutex_lock
(&((unscaled)->mutex)))
;
4259
4260 /* Looked for an existing matching font face */
4261 for (font_face = unscaled->faces, prev_font_face = &unscaled->faces;
4262 font_face;
4263 prev_font_face = &font_face->next, font_face = font_face->next)
4264 {
4265 if (font_face->ft_options.load_flags == ft_options->load_flags &&
4266 font_face->ft_options.synth_flags == ft_options->synth_flags &&
4267 cairo_font_options_equal_moz_cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
4268 {
4269 if (font_face->base.status) {
4270 /* The font_face has been left in an error state, abandon it. */
4271 *prev_font_face = font_face->next;
4272 break;
4273 }
4274
4275 if (font_face->unscaled == NULL((void*)0)) {
4276 /* Resurrect this "zombie" font_face (from
4277 * _cairo_ft_font_face_destroy), switching its unscaled_font
4278 * from owner to ownee. */
4279 font_face->unscaled = unscaled;
4280 _cairo_unscaled_font_reference (&unscaled->base);
4281 } else {
4282 cairo_font_face_reference_moz_cairo_font_face_reference (&font_face->base);
4283 }
4284
4285 CAIRO_FT_UNLOCK (unscaled)((unscaled)->face_context ? mozilla_UnlockSharedFTFace((unscaled
)->face_context) : (void)pthread_mutex_unlock (&((unscaled
)->mutex)))
;
4286 return &font_face->base;
4287 }
4288 }
4289
4290 /* No match found, create a new one */
4291 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))
;
4292 if (unlikely (!font_face)(__builtin_expect (!!(!font_face), 0))) {
4293 CAIRO_FT_UNLOCK (unscaled)((unscaled)->face_context ? mozilla_UnlockSharedFTFace((unscaled
)->face_context) : (void)pthread_mutex_unlock (&((unscaled
)->mutex)))
;
4294 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_NO_MEMORY
); (void) status__; } while (0)
;
4295 return (cairo_font_face_t *)&_cairo_font_face_nil;
4296 }
4297
4298 font_face->unscaled = unscaled;
4299 _cairo_unscaled_font_reference (&unscaled->base);
4300
4301 _cairo_ft_options_init_copy (&font_face->ft_options, ft_options);
4302
4303 if (unscaled->faces && unscaled->faces->unscaled == NULL((void*)0)) {
4304 /* This "zombie" font_face (from _cairo_ft_font_face_destroy)
4305 * is no longer needed. */
4306 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", 4306
, __extension__ __PRETTY_FUNCTION__); }))
;
4307 cairo_font_face_destroy_moz_cairo_font_face_destroy (&unscaled->faces->base);
4308 unscaled->faces = NULL((void*)0);
4309 }
4310
4311 font_face->next = unscaled->faces;
4312 unscaled->faces = font_face;
4313
4314#if CAIRO_HAS_FC_FONT1
4315 font_face->pattern = NULL((void*)0);
4316#endif
4317
4318 _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
4319
4320 CAIRO_FT_UNLOCK (unscaled)((unscaled)->face_context ? mozilla_UnlockSharedFTFace((unscaled
)->face_context) : (void)pthread_mutex_unlock (&((unscaled
)->mutex)))
;
4321 return &font_face->base;
4322}
4323
4324/* implement the platform-specific interface */
4325
4326#if CAIRO_HAS_FC_FONT1
4327static cairo_status_t
4328_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
4329 FcPattern *pattern)
4330{
4331 FcValue v;
4332
4333 if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
4334 {
4335 if (FcPatternGet (pattern, FC_ANTIALIAS"antialias", 0, &v) == FcResultNoMatch)
4336 {
4337 if (! FcPatternAddBool (pattern,
4338 FC_ANTIALIAS"antialias",
4339 options->antialias != CAIRO_ANTIALIAS_NONE))
4340 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4341
4342 if (options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
4343 FcPatternDel (pattern, FC_RGBA"rgba");
4344 if (! FcPatternAddInteger (pattern, FC_RGBA"rgba", FC_RGBA_NONE5))
4345 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4346 }
4347 }
4348 }
4349
4350 if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
4351 {
4352 if (FcPatternGet (pattern, FC_RGBA"rgba", 0, &v) == FcResultNoMatch)
4353 {
4354 int rgba;
4355
4356 if (options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
4357 switch (options->subpixel_order) {
4358 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
4359 case CAIRO_SUBPIXEL_ORDER_RGB:
4360 default:
4361 rgba = FC_RGBA_RGB1;
4362 break;
4363 case CAIRO_SUBPIXEL_ORDER_BGR:
4364 rgba = FC_RGBA_BGR2;
4365 break;
4366 case CAIRO_SUBPIXEL_ORDER_VRGB:
4367 rgba = FC_RGBA_VRGB3;
4368 break;
4369 case CAIRO_SUBPIXEL_ORDER_VBGR:
4370 rgba = FC_RGBA_VBGR4;
4371 break;
4372 }
4373 } else {
4374 rgba = FC_RGBA_NONE5;
4375 }
4376
4377 if (! FcPatternAddInteger (pattern, FC_RGBA"rgba", rgba))
4378 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4379 }
4380 }
4381
4382 if (options->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
4383 {
4384 if (FcPatternGet (pattern, FC_LCD_FILTER"lcdfilter", 0, &v) == FcResultNoMatch)
4385 {
4386 int lcd_filter;
4387
4388 switch (options->lcd_filter) {
4389 case CAIRO_LCD_FILTER_NONE:
4390 lcd_filter = FT_LCD_FILTER_NONE;
4391 break;
4392 case CAIRO_LCD_FILTER_INTRA_PIXEL:
4393 lcd_filter = FT_LCD_FILTER_LEGACY;
4394 break;
4395 case CAIRO_LCD_FILTER_FIR3:
4396 lcd_filter = FT_LCD_FILTER_LIGHT;
4397 break;
4398 default:
4399 case CAIRO_LCD_FILTER_DEFAULT:
4400 case CAIRO_LCD_FILTER_FIR5:
4401 lcd_filter = FT_LCD_FILTER_DEFAULT;
4402 break;
4403 }
4404
4405 if (! FcPatternAddInteger (pattern, FC_LCD_FILTER"lcdfilter", lcd_filter))
4406 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4407 }
4408 }
4409
4410 if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
4411 {
4412 if (FcPatternGet (pattern, FC_HINTING"hinting", 0, &v) == FcResultNoMatch)
4413 {
4414 if (! FcPatternAddBool (pattern,
4415 FC_HINTING"hinting",
4416 options->hint_style != CAIRO_HINT_STYLE_NONE))
4417 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4418 }
4419
4420 if (FcPatternGet (pattern, FC_HINT_STYLE"hintstyle", 0, &v) == FcResultNoMatch)
4421 {
4422 int hint_style;
4423
4424 switch (options->hint_style) {
4425 case CAIRO_HINT_STYLE_NONE:
4426 hint_style = FC_HINT_NONE0;
4427 break;
4428 case CAIRO_HINT_STYLE_SLIGHT:
4429 hint_style = FC_HINT_SLIGHT1;
4430 break;
4431 case CAIRO_HINT_STYLE_MEDIUM:
4432 hint_style = FC_HINT_MEDIUM2;
4433 break;
4434 case CAIRO_HINT_STYLE_FULL:
4435 case CAIRO_HINT_STYLE_DEFAULT:
4436 default:
4437 hint_style = FC_HINT_FULL3;
4438 break;
4439 }
4440
4441 if (! FcPatternAddInteger (pattern, FC_HINT_STYLE"hintstyle", hint_style))
4442 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
4443 }
4444 }
4445
4446 return CAIRO_STATUS_SUCCESS;
4447}
4448
4449/**
4450 * cairo_ft_font_options_substitute:
4451 * @options: a #cairo_font_options_t object
4452 * @pattern: an existing #FcPattern
4453 *
4454 * Add options to a #FcPattern based on a #cairo_font_options_t font
4455 * options object. Options that are already in the pattern, are not overridden,
4456 * so you should call this function after calling FcConfigSubstitute() (the
4457 * user's settings should override options based on the surface type), but
4458 * before calling FcDefaultSubstitute().
4459 *
4460 * Since: 1.0
4461 **/
4462void
4463cairo_ft_font_options_substitute_moz_cairo_ft_font_options_substitute (const cairo_font_options_t *options,
4464 FcPattern *pattern)
4465{
4466 if (cairo_font_options_status_moz_cairo_font_options_status ((cairo_font_options_t *) options))
4467 return;
4468
4469 _cairo_ft_font_options_substitute (options, pattern);
4470}
4471
4472static cairo_font_face_t *
4473_cairo_ft_resolve_pattern (FcPattern *pattern,
4474 const cairo_matrix_t *font_matrix,
4475 const cairo_matrix_t *ctm,
4476 const cairo_font_options_t *font_options)
4477{
4478 cairo_status_t status;
4479
4480 cairo_matrix_t scale;
4481 FcPattern *resolved;
4482 cairo_ft_font_transform_t sf;
4483 FcResult result;
4484 cairo_ft_unscaled_font_t *unscaled;
4485 cairo_ft_options_t ft_options;
4486 cairo_font_face_t *font_face;
4487
4488 scale = *ctm;
4489 scale.x0 = scale.y0 = 0;
4490 cairo_matrix_multiply_moz_cairo_matrix_multiply (&scale,
4491 font_matrix,
4492 &scale);
4493
4494 status = _compute_transform (&sf, &scale, NULL((void*)0));
4495 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4496 return (cairo_font_face_t *)&_cairo_font_face_nil;
4497
4498 pattern = FcPatternDuplicate (pattern);
4499 if (pattern == NULL((void*)0))
4500 return (cairo_font_face_t *)&_cairo_font_face_nil;
4501
4502 if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE"pixelsize", sf.y_scale)) {
4503 font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4504 goto FREE_PATTERN;
4505 }
4506
4507 if (! FcConfigSubstitute (NULL((void*)0), pattern, FcMatchPattern)) {
4508 font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4509 goto FREE_PATTERN;
4510 }
4511
4512 status = _cairo_ft_font_options_substitute (font_options, pattern);
4513 if (status) {
4514 font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4515 goto FREE_PATTERN;
4516 }
4517
4518 FcDefaultSubstitute (pattern);
4519
4520 status = _cairo_ft_unscaled_font_create_for_pattern (pattern, &unscaled);
4521 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
4522 font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4523 goto FREE_PATTERN;
4524 }
4525
4526 if (unscaled == NULL((void*)0)) {
4527 resolved = FcFontMatch (NULL((void*)0), pattern, &result);
4528 if (!resolved) {
4529 /* We failed to find any font. Substitute twin so that the user can
4530 * see something (and hopefully recognise that the font is missing)
4531 * and not just receive a NO_MEMORY error during rendering.
4532 */
4533 font_face = _cairo_font_face_twin_create_fallback ();
4534 goto FREE_PATTERN;
4535 }
4536
4537 status = _cairo_ft_unscaled_font_create_for_pattern (resolved, &unscaled);
4538 if (unlikely (status || unscaled == NULL)(__builtin_expect (!!(status || unscaled == ((void*)0)), 0))) {
4539 font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
4540 goto FREE_RESOLVED;
4541 }
4542 } else
4543 resolved = pattern;
4544
4545 _get_pattern_ft_options (resolved, &ft_options);
4546 font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
4547 _cairo_ft_options_fini (&ft_options);
4548 _cairo_unscaled_font_destroy (&unscaled->base);
4549
4550FREE_RESOLVED:
4551 if (resolved != pattern)
4552 FcPatternDestroy (resolved);
4553
4554FREE_PATTERN:
4555 FcPatternDestroy (pattern);
4556
4557 return font_face;
4558}
4559
4560/**
4561 * cairo_ft_font_face_create_for_pattern:
4562 * @pattern: A fontconfig pattern. Cairo makes a copy of the pattern
4563 * if it needs to. You are free to modify or free @pattern after this call.
4564 *
4565 * Creates a new font face for the FreeType font backend based on a
4566 * fontconfig pattern. This font can then be used with
4567 * cairo_set_font_face() or cairo_scaled_font_create(). The
4568 * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
4569 * also for the FreeType backend and can be used with functions such
4570 * as cairo_ft_scaled_font_lock_face().
4571 *
4572 * Font rendering options are represented both here and when you
4573 * call cairo_scaled_font_create(). Font options that have a representation
4574 * in a #FcPattern must be passed in here; to modify #FcPattern
4575 * appropriately to reflect the options in a #cairo_font_options_t, call
4576 * cairo_ft_font_options_substitute().
4577 *
4578 * The pattern's FC_FT_FACE element is inspected first and if that is set,
4579 * that will be the FreeType font face associated with the returned cairo
4580 * font face. Otherwise the FC_FILE element is checked. If it's set,
4581 * that and the value of the FC_INDEX element (defaults to zero) of @pattern
4582 * are used to load a font face from file.
4583 *
4584 * If both steps from the previous paragraph fails, @pattern will be passed
4585 * to FcConfigSubstitute, FcDefaultSubstitute, and finally FcFontMatch,
4586 * and the resulting font pattern is used.
4587 *
4588 * If the FC_FT_FACE element of @pattern is set, the user is responsible
4589 * for making sure that the referenced FT_Face remains valid for the life
4590 * time of the returned #cairo_font_face_t. See
4591 * cairo_ft_font_face_create_for_ft_face() for an example of how to couple
4592 * the life time of the FT_Face to that of the cairo font-face.
4593 *
4594 * Return value: a newly created #cairo_font_face_t. Free with
4595 * cairo_font_face_destroy() when you are done using it.
4596 *
4597 * Since: 1.0
4598 **/
4599cairo_font_face_t *
4600cairo_ft_font_face_create_for_pattern_moz_cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
4601{
4602 cairo_ft_unscaled_font_t *unscaled;
1
'unscaled' declared without an initial value
4603 cairo_font_face_t *font_face;
4604 cairo_ft_options_t ft_options;
4605 cairo_status_t status;
4606
4607 status = _cairo_ft_unscaled_font_create_for_pattern (pattern, &unscaled);
2
Calling '_cairo_ft_unscaled_font_create_for_pattern'
8
Returning from '_cairo_ft_unscaled_font_create_for_pattern'
4608 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
9
Assuming 'status' is 0
10
Taking false branch
4609 if (status == CAIRO_STATUS_FILE_NOT_FOUND)
4610 return (cairo_font_face_t *) &_cairo_font_face_nil_file_not_found;
4611 else
4612 return (cairo_font_face_t *) &_cairo_font_face_nil;
4613 }
4614 if (unlikely (unscaled == NULL)(__builtin_expect (!!(unscaled == ((void*)0)), 0))) {
11
The left operand of '==' is a garbage value
4615 /* Store the pattern. We will resolve it and create unscaled
4616 * font when creating scaled fonts */
4617 return _cairo_ft_font_face_create_for_pattern (pattern);
4618 }
4619
4620 _get_pattern_ft_options (pattern, &ft_options);
4621 font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
4622 _cairo_ft_options_fini (&ft_options);
4623 _cairo_unscaled_font_destroy (&unscaled->base);
4624
4625 return font_face;
4626}
4627#endif
4628
4629/**
4630 * cairo_ft_font_face_create_for_ft_face:
4631 * @face: A FreeType face object, already opened. This must
4632 * be kept around until the face's ref_count drops to
4633 * zero and it is freed. Since the face may be referenced
4634 * internally to Cairo, the best way to determine when it
4635 * is safe to free the face is to pass a
4636 * #cairo_destroy_func_t to cairo_font_face_set_user_data()
4637 * @load_flags: flags to pass to FT_Load_Glyph when loading
4638 * glyphs from the font. These flags are OR'ed together with
4639 * the flags derived from the #cairo_font_options_t passed
4640 * to cairo_scaled_font_create(), so only a few values such
4641 * as %FT_LOAD_VERTICAL_LAYOUT, and %FT_LOAD_FORCE_AUTOHINT
4642 * are useful. You should not pass any of the flags affecting
4643 * the load target, such as %FT_LOAD_TARGET_LIGHT.
4644 *
4645 * Creates a new font face for the FreeType font backend from a
4646 * pre-opened FreeType face. This font can then be used with
4647 * cairo_set_font_face() or cairo_scaled_font_create(). The
4648 * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
4649 * also for the FreeType backend and can be used with functions such
4650 * as cairo_ft_scaled_font_lock_face(). Note that Cairo may keep a reference
4651 * to the FT_Face alive in a font-cache and the exact lifetime of the reference
4652 * depends highly upon the exact usage pattern and is subject to external
4653 * factors. You must not call FT_Done_Face() before the last reference to the
4654 * #cairo_font_face_t has been dropped.
4655 *
4656 * As an example, below is how one might correctly couple the lifetime of
4657 * the FreeType face object to the #cairo_font_face_t.
4658 *
4659 * <informalexample><programlisting>
4660 * static const cairo_user_data_key_t key;
4661 *
4662 * font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
4663 * status = cairo_font_face_set_user_data (font_face, &key,
4664 * ft_face, (cairo_destroy_func_t) FT_Done_Face);
4665 * if (status) {
4666 * cairo_font_face_destroy (font_face);
4667 * FT_Done_Face (ft_face);
4668 * return ERROR;
4669 * }
4670 * </programlisting></informalexample>
4671 *
4672 * Return value: a newly created #cairo_font_face_t. Free with
4673 * cairo_font_face_destroy() when you are done using it.
4674 *
4675 * Since: 1.0
4676 **/
4677cairo_font_face_t *
4678cairo_ft_font_face_create_for_ft_face_moz_cairo_ft_font_face_create_for_ft_face (FT_Face face,
4679 int load_flags,
4680 unsigned int synth_flags,
4681 void *face_context)
4682{
4683 cairo_ft_unscaled_font_t *unscaled;
4684 cairo_font_face_t *font_face;
4685 cairo_ft_options_t ft_options;
4686 cairo_status_t status;
4687
4688 status = _cairo_ft_unscaled_font_create_from_face (face, face_context,
4689 &unscaled);
4690 if (unlikely (status)(__builtin_expect (!!(status), 0)))
4691 return (cairo_font_face_t *)&_cairo_font_face_nil;
4692
4693 ft_options.load_flags = load_flags;
4694 ft_options.synth_flags = synth_flags;
4695 _cairo_font_options_init_default (&ft_options.base);
4696
4697 font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
4698 _cairo_unscaled_font_destroy (&unscaled->base);
4699
4700 return font_face;
4701}
4702
4703/**
4704 * cairo_ft_font_face_set_synthesize:
4705 * @font_face: The #cairo_ft_font_face_t object to modify
4706 * @synth_flags: the set of synthesis options to enable
4707 *
4708 * FreeType provides the ability to synthesize different glyphs from a base
4709 * font, which is useful if you lack those glyphs from a true bold or oblique
4710 * font. See also #cairo_ft_synthesize_t.
4711 *
4712 * Since: 1.12
4713 **/
4714void
4715cairo_ft_font_face_set_synthesize_moz_cairo_ft_font_face_set_synthesize (cairo_font_face_t *font_face,
4716 unsigned int synth_flags)
4717{
4718 cairo_ft_font_face_t *ft;
4719
4720 if (font_face->backend->type != CAIRO_FONT_TYPE_FT)
4721 return;
4722
4723 ft = (cairo_ft_font_face_t *) font_face;
4724 ft->ft_options.synth_flags |= synth_flags;
4725}
4726
4727/**
4728 * cairo_ft_font_face_unset_synthesize:
4729 * @font_face: The #cairo_ft_font_face_t object to modify
4730 * @synth_flags: the set of synthesis options to disable
4731 *
4732 * See cairo_ft_font_face_set_synthesize().
4733 *
4734 * Since: 1.12
4735 **/
4736void
4737cairo_ft_font_face_unset_synthesize (cairo_font_face_t *font_face,
4738 unsigned int synth_flags)
4739{
4740 cairo_ft_font_face_t *ft;
4741
4742 if (font_face->backend->type != CAIRO_FONT_TYPE_FT)
4743 return;
4744
4745 ft = (cairo_ft_font_face_t *) font_face;
4746 ft->ft_options.synth_flags &= ~synth_flags;
4747}
4748
4749/**
4750 * cairo_ft_font_face_get_synthesize:
4751 * @font_face: The #cairo_ft_font_face_t object to query
4752 *
4753 * See #cairo_ft_synthesize_t.
4754 *
4755 * Returns: the current set of synthesis options.
4756 *
4757 * Since: 1.12
4758 **/
4759unsigned int
4760cairo_ft_font_face_get_synthesize (cairo_font_face_t *font_face)
4761{
4762 cairo_ft_font_face_t *ft;
4763
4764 if (font_face->backend->type != CAIRO_FONT_TYPE_FT)
4765 return 0;
4766
4767 ft = (cairo_ft_font_face_t *) font_face;
4768 return ft->ft_options.synth_flags;
4769}
4770
4771/**
4772 * cairo_ft_scaled_font_lock_face:
4773 * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
4774 * object can be created by calling cairo_scaled_font_create() on a
4775 * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
4776 * cairo_ft_font_face_create_for_ft_face()).
4777 *
4778 * cairo_ft_scaled_font_lock_face() gets the #FT_Face object from a FreeType
4779 * backend font and scales it appropriately for the font and applies OpenType
4780 * font variations if applicable. You must
4781 * release the face with cairo_ft_scaled_font_unlock_face()
4782 * when you are done using it. Since the #FT_Face object can be
4783 * shared between multiple #cairo_scaled_font_t objects, you must not
4784 * lock any other font objects until you unlock this one. A count is
4785 * kept of the number of times cairo_ft_scaled_font_lock_face() is
4786 * called. cairo_ft_scaled_font_unlock_face() must be called the same number
4787 * of times.
4788 *
4789 * You must be careful when using this function in a library or in a
4790 * threaded application, because freetype's design makes it unsafe to
4791 * call freetype functions simultaneously from multiple threads, (even
4792 * if using distinct FT_Face objects). Because of this, application
4793 * code that acquires an FT_Face object with this call must add its
4794 * own locking to protect any use of that object, (and which also must
4795 * protect any other calls into cairo as almost any cairo function
4796 * might result in a call into the freetype library).
4797 *
4798 * Return value: The #FT_Face object for @font, scaled appropriately,
4799 * or %NULL if @scaled_font is in an error state (see
4800 * cairo_scaled_font_status()) or there is insufficient memory.
4801 *
4802 * Since: 1.0
4803 **/
4804FT_Face
4805cairo_ft_scaled_font_lock_face_moz_cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
4806{
4807 cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
4808 FT_Face face;
4809 cairo_status_t status;
4810
4811 if (! _cairo_scaled_font_is_ft (abstract_font)) {
4812 _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_FONT_TYPE_MISMATCH
); (void) status__; } while (0)
;
4813 return NULL((void*)0);
4814 }
4815
4816 if (scaled_font->base.status)
4817 return NULL((void*)0);
4818
4819 face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
4820 if (unlikely (face == NULL)(__builtin_expect (!!(face == ((void*)0)), 0))) {
4821 status = _cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
4822 return NULL((void*)0);
4823 }
4824
4825 status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
4826 &scaled_font->base.scale);
4827 if (unlikely (status)(__builtin_expect (!!(status), 0))) {
4828 _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
4829 status = _cairo_scaled_font_set_error (&scaled_font->base, status);
4830 return NULL((void*)0);
4831 }
4832
4833 cairo_ft_apply_variations (face, scaled_font);
4834
4835 /* Note: We deliberately release the unscaled font's mutex here,
4836 * so that we are not holding a lock across two separate calls to
4837 * cairo function, (which would give the application some
4838 * opportunity for creating deadlock. This is obviously unsafe,
4839 * but as documented, the user must add manual locking when using
4840 * this function. */
4841 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)))
;
4842
4843 return face;
4844}
4845
4846/**
4847 * cairo_ft_scaled_font_unlock_face:
4848 * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
4849 * object can be created by calling cairo_scaled_font_create() on a
4850 * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
4851 * cairo_ft_font_face_create_for_ft_face()).
4852 *
4853 * Releases a face obtained with cairo_ft_scaled_font_lock_face().
4854 *
4855 * Since: 1.0
4856 **/
4857void
4858cairo_ft_scaled_font_unlock_face_moz_cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
4859{
4860 cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
4861
4862 if (! _cairo_scaled_font_is_ft (abstract_font)) {
4863 _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH)do { cairo_status_t status__ = _cairo_error (CAIRO_STATUS_FONT_TYPE_MISMATCH
); (void) status__; } while (0)
;
4864 return;
4865 }
4866
4867 if (scaled_font->base.status)
4868 return;
4869
4870 /* Note: We released the unscaled font's mutex at the end of
4871 * cairo_ft_scaled_font_lock_face, so we have to acquire it again
4872 * as _cairo_ft_unscaled_font_unlock_face expects it to be held
4873 * when we call into it. */
4874 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)))
;
4875
4876 _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
4877}
4878
4879static cairo_bool_t
4880_cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font)
4881{
4882 cairo_ft_scaled_font_t *ft_scaled_font;
4883
4884 if (!_cairo_scaled_font_is_ft (scaled_font))
4885 return FALSE0;
4886
4887 ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
4888 if (ft_scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT( 1L << 4 ))
4889 return TRUE1;
4890 return FALSE0;
4891}
4892
4893unsigned int
4894_cairo_ft_scaled_font_get_load_flags (cairo_scaled_font_t *scaled_font)
4895{
4896 cairo_ft_scaled_font_t *ft_scaled_font;
4897
4898 if (! _cairo_scaled_font_is_ft (scaled_font))
4899 return 0;
4900
4901 ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
4902 return ft_scaled_font->ft_options.load_flags;
4903}
4904
4905void
4906_cairo_ft_font_reset_static_data (void)
4907{
4908 _cairo_ft_unscaled_font_map_destroy ();
4909}