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 _BSD_SOURCE /* for strdup() */
42 #include "cairoint.h"
43 
44 #include "cairo-error-private.h"
45 #include "cairo-ft-private.h"
46 
47 #include <float.h>
48 
49 #include "cairo-fontconfig-private.h"
50 
51 #include <ft2build.h>
52 #include FT_FREETYPE_H
53 #include FT_OUTLINE_H
54 #include FT_IMAGE_H
55 #include FT_BITMAP_H
56 #include FT_TRUETYPE_TABLES_H
57 #include FT_MULTIPLE_MASTERS_H
58 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
59 #include FT_SYNTHESIS_H
60 #endif
61 
62 #if HAVE_FT_LIBRARY_SETLCDFILTER
63 #include FT_LCD_FILTER_H
64 #endif
65 
66 #define _GNU_SOURCE /* for RTLD_DEFAULT */
67 #include <dlfcn.h>
68 
69 #ifndef RTLD_DEFAULT
70 #define RTLD_DEFAULT ((void *) 0)
71 #endif
72 
73 /* Fontconfig version older than 2.6 didn't have these options */
74 #ifndef FC_LCD_FILTER
75 #define FC_LCD_FILTER	"lcdfilter"
76 #endif
77 /* Some Ubuntu versions defined FC_LCD_FILTER without defining the following */
78 #ifndef FC_LCD_NONE
79 #define FC_LCD_NONE	0
80 #define FC_LCD_DEFAULT	1
81 #define FC_LCD_LIGHT	2
82 #define FC_LCD_LEGACY	3
83 #endif
84 
85 /* FreeType version older than 2.3.5(?) didn't have these options */
86 #ifndef FT_LCD_FILTER_NONE
87 #define FT_LCD_FILTER_NONE	0
88 #define FT_LCD_FILTER_DEFAULT	1
89 #define FT_LCD_FILTER_LIGHT	2
90 #define FT_LCD_FILTER_LEGACY	16
91 #endif
92 
93 typedef FT_Error (*setLcdFilterFunc)(FT_Library, int);
94 static setLcdFilterFunc setLcdFilter;
95 
96 #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
97 #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
98 #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
99 #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
100 
101 /* This is the max number of FT_face objects we keep open at once
102  */
103 #define MAX_OPEN_FACES 10
104 /* This is the maximum font size we allow to be passed to FT_Set_Char_Size
105  */
106 #define MAX_FONT_SIZE 2000
107 
108 extern FT_Face mozilla_NewFTFace(FT_Library aFTLibrary, const char* aFileName, int aFaceIndex);
109 extern FT_Face mozilla_NewFTFaceFromData(FT_Library aFTLibrary, const uint8_t* aData, size_t aDataSize, int aFaceIndex);
110 extern void mozilla_ReleaseFTFace(FT_Face aFace);
111 extern void mozilla_LockFTLibrary(FT_Library aFTLibrary);
112 extern void mozilla_UnlockFTLibrary(FT_Library aFTLibrary);
113 
114 /**
115  * SECTION:cairo-ft
116  * @Title: FreeType Fonts
117  * @Short_Description: Font support for FreeType
118  * @See_Also: #cairo_font_face_t
119  *
120  * The FreeType font backend is primarily used to render text on GNU/Linux
121  * systems, but can be used on other platforms too.
122  */
123 
124 /**
125  * CAIRO_HAS_FT_FONT:
126  *
127  * Defined if the FreeType font backend is available.
128  * This macro can be used to conditionally compile backend-specific code.
129  */
130 
131 /**
132  * CAIRO_HAS_FC_FONT:
133  *
134  * Defined if the Fontconfig-specific functions of the FreeType font backend
135  * are available.
136  * This macro can be used to conditionally compile backend-specific code.
137  */
138 
139 /*
140  * The simple 2x2 matrix is converted into separate scale and shape
141  * factors so that hinting works right
142  */
143 
144 typedef struct _cairo_ft_font_transform {
145     double  x_scale, y_scale;
146     double  shape[2][2];
147 } cairo_ft_font_transform_t;
148 
149 /*
150  * We create an object that corresponds to a single font on the disk;
151  * (identified by a filename/id pair) these are shared between all
152  * fonts using that file.  For cairo_ft_font_face_create_for_ft_face(), we
153  * just create a one-off version with a permanent face value.
154  */
155 
156 typedef struct _cairo_ft_font_face cairo_ft_font_face_t;
157 
158 struct _cairo_ft_unscaled_font {
159     cairo_unscaled_font_t base;
160 
161     cairo_bool_t from_face; /* was the FT_Face provided by user? */
162     FT_Face face;	    /* provided or cached face */
163 
164     /* only set if from_face is false */
165     char *filename;
166     int id;
167 
168     /* For variation fonts, the variation coordinates to apply to each axis. */
169     const FT_Fixed *var_coords;
170     int num_var_coords;
171 
172     /* We temporarily scale the unscaled font as needed */
173     cairo_bool_t have_scale;
174     cairo_matrix_t current_scale;
175     double x_scale;		/* Extracted X scale factor */
176     double y_scale;             /* Extracted Y scale factor */
177     cairo_bool_t have_shape;	/* true if the current scale has a non-scale component*/
178     cairo_matrix_t current_shape;
179     FT_Matrix Current_Shape;
180 
181     cairo_mutex_t mutex;
182     int lock_count;
183 
184     cairo_ft_font_face_t *faces;	/* Linked list of faces for this font */
185 };
186 
187 static int
188 _cairo_ft_unscaled_font_keys_equal (const void *key_a,
189 				    const void *key_b);
190 
191 static void
192 _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled);
193 
194 typedef enum _cairo_ft_extra_flags {
195     CAIRO_FT_OPTIONS_HINT_METRICS = (1 << 0),
196     CAIRO_FT_OPTIONS_EMBOLDEN = (1 << 1)
197 } cairo_ft_extra_flags_t;
198 
199 typedef struct _cairo_ft_options {
200     cairo_font_options_t    base;
201     int			    load_flags;	 /* flags for FT_Load_Glyph */
202     cairo_ft_extra_flags_t  extra_flags; /* other flags that affect results */
203 } cairo_ft_options_t;
204 
205 struct _cairo_ft_font_face {
206     cairo_font_face_t base;
207 
208     cairo_ft_unscaled_font_t *unscaled;
209     cairo_ft_options_t ft_options;
210     cairo_ft_font_face_t *next;
211 
212 #if CAIRO_HAS_FC_FONT
213     FcPattern *pattern; /* if pattern is set, the above fields will be NULL */
214     cairo_font_face_t *resolved_font_face;
215     FcConfig *resolved_config;
216 #endif
217 };
218 
219 static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;
220 
221 #if CAIRO_HAS_FC_FONT
222 static cairo_status_t
223 _cairo_ft_font_options_substitute (const cairo_font_options_t *options,
224 				   FcPattern                  *pattern);
225 
226 static cairo_font_face_t *
227 _cairo_ft_resolve_pattern (FcPattern		      *pattern,
228 			   const cairo_matrix_t       *font_matrix,
229 			   const cairo_matrix_t       *ctm,
230 			   const cairo_font_options_t *options);
231 
232 #endif
233 
234 /*
235  * We maintain a hash table to map file/id => #cairo_ft_unscaled_font_t.
236  * The hash table itself isn't limited in size. However, we limit the
237  * number of FT_Face objects we keep around; when we've exceeded that
238  * limit and need to create a new FT_Face, we dump the FT_Face from a
239  * random #cairo_ft_unscaled_font_t which has an unlocked FT_Face, (if
240  * there are any).
241  */
242 
243 typedef struct _cairo_ft_unscaled_font_map {
244     cairo_hash_table_t *hash_table;
245     FT_Library ft_library;
246     int num_open_faces;
247 } cairo_ft_unscaled_font_map_t;
248 
249 static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;
250 
251 
252 static void
_font_map_release_face_lock_held(cairo_ft_unscaled_font_map_t * font_map,cairo_ft_unscaled_font_t * unscaled)253 _font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
254 				  cairo_ft_unscaled_font_t *unscaled)
255 {
256     if (unscaled->face) {
257 	mozilla_ReleaseFTFace (unscaled->face);
258 	unscaled->face = NULL;
259 	unscaled->have_scale = FALSE;
260 
261 	font_map->num_open_faces--;
262     }
263 }
264 
265 static cairo_status_t
_cairo_ft_unscaled_font_map_create(void)266 _cairo_ft_unscaled_font_map_create (void)
267 {
268     cairo_ft_unscaled_font_map_t *font_map;
269 
270     /* This function is only intended to be called from
271      * _cairo_ft_unscaled_font_map_lock. So we'll crash if we can
272      * detect some other call path. */
273     assert (cairo_ft_unscaled_font_map == NULL);
274 
275     font_map = malloc (sizeof (cairo_ft_unscaled_font_map_t));
276     if (unlikely (font_map == NULL))
277 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
278 
279     font_map->hash_table =
280 	_cairo_hash_table_create (_cairo_ft_unscaled_font_keys_equal);
281 
282     if (unlikely (font_map->hash_table == NULL))
283 	goto FAIL;
284 
285     if (unlikely (FT_Init_FreeType (&font_map->ft_library)))
286 	goto FAIL;
287 
288     font_map->num_open_faces = 0;
289 
290     cairo_ft_unscaled_font_map = font_map;
291     return CAIRO_STATUS_SUCCESS;
292 
293 FAIL:
294     if (font_map->hash_table)
295 	_cairo_hash_table_destroy (font_map->hash_table);
296     free (font_map);
297 
298     return _cairo_error (CAIRO_STATUS_NO_MEMORY);
299 }
300 
301 
302 static void
_cairo_ft_unscaled_font_map_pluck_entry(void * entry,void * closure)303 _cairo_ft_unscaled_font_map_pluck_entry (void *entry, void *closure)
304 {
305     cairo_ft_unscaled_font_t *unscaled = entry;
306     cairo_ft_unscaled_font_map_t *font_map = closure;
307 
308     _cairo_hash_table_remove (font_map->hash_table,
309 			      &unscaled->base.hash_entry);
310 
311     if (! unscaled->from_face)
312 	_font_map_release_face_lock_held (font_map, unscaled);
313 
314     _cairo_ft_unscaled_font_fini (unscaled);
315     free (unscaled);
316 }
317 
318 static void
_cairo_ft_unscaled_font_map_destroy(void)319 _cairo_ft_unscaled_font_map_destroy (void)
320 {
321     cairo_ft_unscaled_font_map_t *font_map;
322 
323     CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
324     font_map = cairo_ft_unscaled_font_map;
325     cairo_ft_unscaled_font_map = NULL;
326     CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
327 
328     if (font_map != NULL) {
329 	_cairo_hash_table_foreach (font_map->hash_table,
330 				   _cairo_ft_unscaled_font_map_pluck_entry,
331 				   font_map);
332 	assert (font_map->num_open_faces == 0);
333 
334 	FT_Done_FreeType (font_map->ft_library);
335 
336 	_cairo_hash_table_destroy (font_map->hash_table);
337 
338 	free (font_map);
339     }
340 }
341 
342 static cairo_ft_unscaled_font_map_t *
_cairo_ft_unscaled_font_map_lock(void)343 _cairo_ft_unscaled_font_map_lock (void)
344 {
345     CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
346 
347     if (unlikely (cairo_ft_unscaled_font_map == NULL)) {
348 	if (unlikely (_cairo_ft_unscaled_font_map_create ())) {
349 	    CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
350 	    return NULL;
351 	}
352     }
353 
354     return cairo_ft_unscaled_font_map;
355 }
356 
357 static void
_cairo_ft_unscaled_font_map_unlock(void)358 _cairo_ft_unscaled_font_map_unlock (void)
359 {
360     CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
361 }
362 
363 static void
_cairo_ft_unscaled_font_init_key(cairo_ft_unscaled_font_t * key,cairo_bool_t from_face,char * filename,int id,const FT_Fixed * var_coords,int num_var_coords,FT_Face face)364 _cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
365 				  cairo_bool_t              from_face,
366 				  char			   *filename,
367 				  int			    id,
368                                   const FT_Fixed           *var_coords,
369                                   int                       num_var_coords,
370 				  FT_Face		    face)
371 {
372     unsigned long hash;
373 
374     key->from_face = from_face;
375     key->filename = filename;
376     key->id = id;
377     key->face = face;
378     key->var_coords = var_coords;
379     key->num_var_coords = num_var_coords;
380 
381     hash = _cairo_hash_string (filename);
382     /* the constants are just arbitrary primes */
383     hash += ((unsigned long) id) * 1607;
384     hash += ((unsigned long) face) * 2137;
385 
386     hash = _cairo_hash_bytes (hash, var_coords, num_var_coords * sizeof(FT_Fixed));
387 
388     key->base.hash_entry.hash = hash;
389 }
390 
391 /**
392  * _cairo_ft_unscaled_font_init:
393  *
394  * Initialize a #cairo_ft_unscaled_font_t.
395  *
396  * There are two basic flavors of #cairo_ft_unscaled_font_t, one
397  * created from an FT_Face and the other created from a filename/id
398  * pair. These two flavors are identified as from_face and !from_face.
399  *
400  * To initialize a from_face font, pass filename==%NULL, id=0 and the
401  * desired face.
402  *
403  * To initialize a !from_face font, pass the filename/id as desired
404  * and face==%NULL.
405  *
406  * Note that the code handles these two flavors in very distinct
407  * ways. For example there is a hash_table mapping
408  * filename/id->#cairo_unscaled_font_t in the !from_face case, but no
409  * parallel in the from_face case, (where the calling code would have
410  * to do its own mapping to ensure similar sharing).
411  **/
412 static cairo_status_t
_cairo_ft_unscaled_font_init(cairo_ft_unscaled_font_t * unscaled,cairo_bool_t from_face,const char * filename,int id,const FT_Fixed * var_coords,int num_var_coords,FT_Face face)413 _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
414 			      cairo_bool_t              from_face,
415 			      const char	       *filename,
416 			      int			id,
417                               const FT_Fixed           *var_coords,
418                               int                       num_var_coords,
419 			      FT_Face			face)
420 {
421     _cairo_unscaled_font_init (&unscaled->base,
422 			       &cairo_ft_unscaled_font_backend);
423 
424     if (from_face) {
425 	unscaled->from_face = TRUE;
426 	_cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, 0, var_coords, num_var_coords, face);
427     } else {
428 	char *filename_copy;
429 
430 	unscaled->from_face = FALSE;
431 	unscaled->face = NULL;
432 
433 	filename_copy = strdup (filename);
434 	if (unlikely (filename_copy == NULL))
435 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
436 
437 	_cairo_ft_unscaled_font_init_key (unscaled, FALSE, filename_copy, id, var_coords, num_var_coords, NULL);
438     }
439 
440     unscaled->have_scale = FALSE;
441     CAIRO_MUTEX_INIT (unscaled->mutex);
442     unscaled->lock_count = 0;
443 
444     unscaled->faces = NULL;
445 
446     return CAIRO_STATUS_SUCCESS;
447 }
448 
449 /**
450  * _cairo_ft_unscaled_font_fini:
451  *
452  * Free all data associated with a #cairo_ft_unscaled_font_t.
453  *
454  * CAUTION: The unscaled->face field must be %NULL before calling this
455  * function. This is because the #cairo_ft_unscaled_font_t_map keeps a
456  * count of these faces (font_map->num_open_faces) so it maintains the
457  * unscaled->face field while it has its lock held. See
458  * _font_map_release_face_lock_held().
459  **/
460 static void
_cairo_ft_unscaled_font_fini(cairo_ft_unscaled_font_t * unscaled)461 _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
462 {
463     assert (unscaled->face == NULL);
464 
465     if (unscaled->filename) {
466 	free (unscaled->filename);
467 	unscaled->filename = NULL;
468     }
469 
470     if (unscaled->var_coords) {
471         free (unscaled->var_coords);
472         unscaled->var_coords = NULL;
473     }
474 
475     CAIRO_MUTEX_FINI (unscaled->mutex);
476 }
477 
478 static int
_cairo_ft_unscaled_font_keys_equal(const void * key_a,const void * key_b)479 _cairo_ft_unscaled_font_keys_equal (const void *key_a,
480 				    const void *key_b)
481 {
482     const cairo_ft_unscaled_font_t *unscaled_a = key_a;
483     const cairo_ft_unscaled_font_t *unscaled_b = key_b;
484 
485     if (unscaled_a->id == unscaled_b->id &&
486 	unscaled_a->from_face == unscaled_b->from_face &&
487         unscaled_a->num_var_coords == unscaled_b->num_var_coords)
488     {
489         if (unscaled_a->from_face)
490 	    return unscaled_a->face == unscaled_b->face;
491 
492         if (unscaled_a->num_var_coords > 0 &&
493             (memcmp (unscaled_a->var_coords, unscaled_b->var_coords,
494                      unscaled_a->num_var_coords * sizeof(FT_Fixed)) != 0))
495             return FALSE;
496 	else if (unscaled_a->filename == NULL && unscaled_b->filename == NULL)
497 	    return TRUE;
498 	else if (unscaled_a->filename == NULL || unscaled_b->filename == NULL)
499 	    return FALSE;
500 	else
501 	    return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0);
502     }
503 
504     return FALSE;
505 }
506 
507 /* Finds or creates a #cairo_ft_unscaled_font_t for the filename/id from
508  * pattern.  Returns a new reference to the unscaled font.
509  */
510 static cairo_status_t
_cairo_ft_unscaled_font_create_internal(cairo_bool_t from_face,char * filename,int id,FT_Face font_face,const FT_Fixed * var_coords,int num_var_coords,cairo_ft_unscaled_font_t ** out)511 _cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
512 					 char *filename,
513 					 int id,
514 					 FT_Face font_face,
515                                          const FT_Fixed *var_coords,
516                                          int num_var_coords,
517 					 cairo_ft_unscaled_font_t **out)
518 {
519     cairo_ft_unscaled_font_t key, *unscaled;
520     cairo_ft_unscaled_font_map_t *font_map;
521     FT_Fixed* new_var_coords = NULL;
522     cairo_status_t status;
523 
524     font_map = _cairo_ft_unscaled_font_map_lock ();
525     if (unlikely (font_map == NULL))
526 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
527 
528     _cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, var_coords, num_var_coords, font_face);
529 
530     /* Return existing unscaled font if it exists in the hash table. */
531     unscaled = _cairo_hash_table_lookup (font_map->hash_table,
532 					 &key.base.hash_entry);
533     if (unscaled != NULL) {
534 	_cairo_unscaled_font_reference (&unscaled->base);
535 	goto DONE;
536     }
537 
538     /* Otherwise create it and insert into hash table. */
539     unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
540     if (unlikely (unscaled == NULL)) {
541 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
542 	goto UNWIND_FONT_MAP_LOCK;
543     }
544 
545     /* If we have variation coordinate data, make a copy to save in the unscaled_font */
546     if (var_coords && num_var_coords) {
547         new_var_coords = malloc (num_var_coords * sizeof(FT_Fixed));
548         if (unlikely (!new_var_coords)) {
549             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
550             goto UNWIND_VAR_COORDS;
551         }
552         memcpy (new_var_coords, var_coords, num_var_coords * sizeof(FT_Fixed));
553     }
554 
555     status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, new_var_coords, num_var_coords, font_face);
556     if (unlikely (status))
557 	goto UNWIND_UNSCALED_MALLOC;
558 
559     assert (unscaled->base.hash_entry.hash == key.base.hash_entry.hash);
560     status = _cairo_hash_table_insert (font_map->hash_table,
561 				       &unscaled->base.hash_entry);
562     if (unlikely (status))
563 	goto UNWIND_UNSCALED_FONT_INIT;
564 
565 DONE:
566     _cairo_ft_unscaled_font_map_unlock ();
567     *out = unscaled;
568     return CAIRO_STATUS_SUCCESS;
569 
570 UNWIND_UNSCALED_FONT_INIT:
571     _cairo_ft_unscaled_font_fini (unscaled);
572 UNWIND_UNSCALED_MALLOC:
573     free (unscaled);
574 UNWIND_VAR_COORDS:
575     free (new_var_coords);
576 UNWIND_FONT_MAP_LOCK:
577     _cairo_ft_unscaled_font_map_unlock ();
578     return status;
579 }
580 
581 
582 #if CAIRO_HAS_FC_FONT
583 static cairo_status_t
_cairo_ft_unscaled_font_create_for_pattern(FcPattern * pattern,const FT_Fixed * var_coords,int num_var_coords,cairo_ft_unscaled_font_t ** out)584 _cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern,
585                                             const FT_Fixed *var_coords, int num_var_coords,
586 					    cairo_ft_unscaled_font_t **out)
587 {
588     FT_Face font_face = NULL;
589     char *filename = NULL;
590     int id = 0;
591     FcResult ret;
592 
593     ret = FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face);
594     if (ret == FcResultMatch)
595 	goto DONE;
596     if (ret == FcResultOutOfMemory)
597 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
598 
599     ret = FcPatternGetString (pattern, FC_FILE, 0, (FcChar8 **) &filename);
600     if (ret == FcResultOutOfMemory)
601 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
602     if (ret == FcResultMatch) {
603 	/* If FC_INDEX is not set, we just use 0 */
604 	ret = FcPatternGetInteger (pattern, FC_INDEX, 0, &id);
605 	if (ret == FcResultOutOfMemory)
606 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
607 
608 	goto DONE;
609     }
610 
611     /* The pattern contains neither a face nor a filename, resolve it later. */
612     *out = NULL;
613     return CAIRO_STATUS_SUCCESS;
614 
615 DONE:
616     return _cairo_ft_unscaled_font_create_internal (font_face != NULL,
617 						    filename, id, font_face,
618                                                     var_coords, num_var_coords,
619 						    out);
620 }
621 #endif
622 
623 static cairo_status_t
_cairo_ft_unscaled_font_create_from_face(FT_Face face,const FT_Fixed * var_coords,int num_var_coords,cairo_ft_unscaled_font_t ** out)624 _cairo_ft_unscaled_font_create_from_face (FT_Face face, const FT_Fixed *var_coords, int num_var_coords,
625 					  cairo_ft_unscaled_font_t **out)
626 {
627     return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face,
628                                                     var_coords, num_var_coords, out);
629 }
630 
631 static void
_cairo_ft_unscaled_font_destroy(void * abstract_font)632 _cairo_ft_unscaled_font_destroy (void *abstract_font)
633 {
634     cairo_ft_unscaled_font_t *unscaled  = abstract_font;
635     cairo_ft_unscaled_font_map_t *font_map;
636 
637     if (unscaled == NULL)
638 	return;
639 
640     font_map = _cairo_ft_unscaled_font_map_lock ();
641     /* All created objects must have been mapped in the font map. */
642     assert (font_map != NULL);
643 
644     if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled->base.ref_count)) {
645 	/* somebody recreated the font whilst we waited for the lock */
646 	_cairo_ft_unscaled_font_map_unlock ();
647 	return;
648     }
649 
650     _cairo_hash_table_remove (font_map->hash_table,
651 			      &unscaled->base.hash_entry);
652 
653     if (unscaled->from_face) {
654 	/* See comments in _ft_font_face_destroy about the "zombie" state
655 	 * for a _ft_font_face.
656 	 */
657 	if (unscaled->faces && unscaled->faces->unscaled == NULL) {
658 	    assert (unscaled->faces->next == NULL);
659 	    cairo_font_face_destroy (&unscaled->faces->base);
660 	}
661     } else {
662 	_font_map_release_face_lock_held (font_map, unscaled);
663     }
664     unscaled->face = NULL;
665 
666     _cairo_ft_unscaled_font_map_unlock ();
667 
668     _cairo_ft_unscaled_font_fini (unscaled);
669 }
670 
671 static cairo_bool_t
_has_unlocked_face(const void * entry)672 _has_unlocked_face (const void *entry)
673 {
674     const cairo_ft_unscaled_font_t *unscaled = entry;
675 
676     return (!unscaled->from_face && unscaled->lock_count == 0 && unscaled->face);
677 }
678 
679 /* Ensures that an unscaled font has a face object. If we exceed
680  * MAX_OPEN_FACES, try to close some.
681  *
682  * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
683  * set the scale on the face, but just returns it at the last scale.
684  */
685 cairo_warn FT_Face
_cairo_ft_unscaled_font_lock_face(cairo_ft_unscaled_font_t * unscaled)686 _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
687 {
688     cairo_ft_unscaled_font_map_t *font_map;
689     FT_Face face = NULL;
690 
691     CAIRO_MUTEX_LOCK (unscaled->mutex);
692     unscaled->lock_count++;
693 
694     if (unscaled->face)
695 	return unscaled->face;
696 
697     /* If this unscaled font was created from an FT_Face then we just
698      * returned it above. */
699     assert (!unscaled->from_face);
700 
701     font_map = _cairo_ft_unscaled_font_map_lock ();
702     {
703 	assert (font_map != NULL);
704 
705 	while (font_map->num_open_faces >= MAX_OPEN_FACES)
706 	{
707 	    cairo_ft_unscaled_font_t *entry;
708 
709 	    entry = _cairo_hash_table_random_entry (font_map->hash_table,
710 						    _has_unlocked_face);
711 	    if (entry == NULL)
712 		break;
713 
714 	    _font_map_release_face_lock_held (font_map, entry);
715 	}
716     }
717     _cairo_ft_unscaled_font_map_unlock ();
718 
719     face = mozilla_NewFTFace (font_map->ft_library, unscaled->filename, unscaled->id);
720     if (!face)
721     {
722 	unscaled->lock_count--;
723 	CAIRO_MUTEX_UNLOCK (unscaled->mutex);
724 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
725 	return NULL;
726     }
727 
728     if (unscaled->var_coords) {
729 #if MOZ_TREE_FREETYPE
730         FT_Set_Var_Design_Coordinates(face, unscaled->num_var_coords, unscaled->var_coords);
731 #else
732         typedef FT_Error (*SetCoordsFunc)(FT_Face, FT_UInt, FT_Fixed*);
733         static SetCoordsFunc setCoords;
734         static cairo_bool_t firstTime = TRUE;
735         if (firstTime) {
736             firstTime = FALSE;
737             (SetCoordsFunc)dlsym(RTLD_DEFAULT, "FT_Set_Var_Design_Coordinates");
738         }
739         if (setCoords) {
740             (*setCoords)(face, unscaled->num_var_coords, unscaled->var_coords);
741         }
742 #endif
743     }
744 
745     unscaled->face = face;
746 
747     font_map->num_open_faces++;
748 
749     return face;
750 }
751 
752 
753 /* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face
754  */
755 void
_cairo_ft_unscaled_font_unlock_face(cairo_ft_unscaled_font_t * unscaled)756 _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
757 {
758     assert (unscaled->lock_count > 0);
759 
760     unscaled->lock_count--;
761 
762     CAIRO_MUTEX_UNLOCK (unscaled->mutex);
763 }
764 
765 
766 static cairo_status_t
_compute_transform(cairo_ft_font_transform_t * sf,cairo_matrix_t * scale,cairo_ft_unscaled_font_t * unscaled)767 _compute_transform (cairo_ft_font_transform_t *sf,
768 		    cairo_matrix_t      *scale,
769 		    cairo_ft_unscaled_font_t *unscaled)
770 {
771     cairo_status_t status;
772     double x_scale, y_scale;
773     cairo_matrix_t normalized = *scale;
774 
775     /* The font matrix has x and y "scale" components which we extract and
776      * use as character scale values. These influence the way freetype
777      * chooses hints, as well as selecting different bitmaps in
778      * hand-rendered fonts. We also copy the normalized matrix to
779      * freetype's transformation.
780      */
781 
782     status = _cairo_matrix_compute_basis_scale_factors (scale,
783 						  &x_scale, &y_scale,
784 						  1);
785     if (unlikely (status))
786 	return status;
787 
788     /* FreeType docs say this about x_scale and y_scale:
789      * "A character width or height smaller than 1pt is set to 1pt;"
790      * So, we cap them from below at 1.0 and let the FT transform
791      * take care of sub-1.0 scaling. */
792     if (x_scale < 1.0)
793       x_scale = 1.0;
794     if (y_scale < 1.0)
795       y_scale = 1.0;
796 
797     if (unscaled && (unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) == 0) {
798 	double min_distance = DBL_MAX;
799 	cairo_bool_t magnify = TRUE;
800 	int i;
801 	int best_i = 0;
802 	double best_x_size = 0;
803 	double best_y_size = 0;
804 
805 	for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
806 	    double x_size = unscaled->face->available_sizes[i].x_ppem / 64.;
807 	    double y_size = unscaled->face->available_sizes[i].y_ppem / 64.;
808 	    double distance = y_size - y_scale;
809 
810 	    /*
811 	     * distance is positive if current strike is larger than desired
812 	     * size, and negative if smaller.
813 	     *
814 	     * We like to prefer down-scaling to upscaling.
815 	     */
816 
817 	    if ((magnify && distance >= 0) || fabs (distance) <= min_distance) {
818 		magnify = distance < 0;
819 		min_distance = fabs (distance);
820 		best_i = i;
821 		best_x_size = x_size;
822 		best_y_size = y_size;
823 	    }
824 	}
825 
826 	x_scale = best_x_size;
827 	y_scale = best_y_size;
828     }
829 
830     sf->x_scale = x_scale;
831     sf->y_scale = y_scale;
832 
833     cairo_matrix_scale (&normalized, 1.0 / x_scale, 1.0 / y_scale);
834 
835     _cairo_matrix_get_affine (&normalized,
836 			      &sf->shape[0][0], &sf->shape[0][1],
837 			      &sf->shape[1][0], &sf->shape[1][1],
838 			      NULL, NULL);
839 
840     return CAIRO_STATUS_SUCCESS;
841 }
842 
843 /* Temporarily scales an unscaled font to the give scale. We catch
844  * scaling to the same size, since changing a FT_Face is expensive.
845  */
846 static cairo_status_t
_cairo_ft_unscaled_font_set_scale(cairo_ft_unscaled_font_t * unscaled,cairo_matrix_t * scale)847 _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
848 				   cairo_matrix_t	      *scale)
849 {
850     cairo_status_t status;
851     cairo_ft_font_transform_t sf;
852     FT_Matrix mat;
853     FT_Error error;
854     double x_scale, y_scale;
855 
856     assert (unscaled->face != NULL);
857 
858     if (unscaled->have_scale &&
859 	scale->xx == unscaled->current_scale.xx &&
860 	scale->yx == unscaled->current_scale.yx &&
861 	scale->xy == unscaled->current_scale.xy &&
862 	scale->yy == unscaled->current_scale.yy)
863 	return CAIRO_STATUS_SUCCESS;
864 
865     unscaled->have_scale = TRUE;
866     unscaled->current_scale = *scale;
867 
868     status = _compute_transform (&sf, scale, unscaled);
869     if (unlikely (status))
870 	return status;
871 
872     unscaled->x_scale = sf.x_scale;
873     unscaled->y_scale = sf.y_scale;
874 
875     mat.xx = DOUBLE_TO_16_16(sf.shape[0][0]);
876     mat.yx = - DOUBLE_TO_16_16(sf.shape[0][1]);
877     mat.xy = - DOUBLE_TO_16_16(sf.shape[1][0]);
878     mat.yy = DOUBLE_TO_16_16(sf.shape[1][1]);
879 
880     unscaled->have_shape = (mat.xx != 0x10000 ||
881 			    mat.yx != 0x00000 ||
882 			    mat.xy != 0x00000 ||
883 			    mat.yy != 0x10000);
884 
885     unscaled->Current_Shape = mat;
886     cairo_matrix_init (&unscaled->current_shape,
887 		       sf.shape[0][0], sf.shape[0][1],
888 		       sf.shape[1][0], sf.shape[1][1],
889 		       0.0, 0.0);
890 
891     FT_Set_Transform(unscaled->face, &mat, NULL);
892 
893     x_scale = MIN(sf.x_scale, MAX_FONT_SIZE);
894     y_scale = MIN(sf.y_scale, MAX_FONT_SIZE);
895     error = FT_Set_Char_Size (unscaled->face,
896 			      x_scale * 64.0 + .5,
897 			      y_scale * 64.0 + .5,
898 			      0, 0);
899     if (error)
900       return _cairo_error (CAIRO_STATUS_NO_MEMORY);
901 
902     return CAIRO_STATUS_SUCCESS;
903 }
904 
905 /* we sometimes need to convert the glyph bitmap in a FT_GlyphSlot
906  * into a different format. For example, we want to convert a
907  * FT_PIXEL_MODE_LCD or FT_PIXEL_MODE_LCD_V bitmap into a 32-bit
908  * ARGB or ABGR bitmap.
909  *
910  * this function prepares a target descriptor for this operation.
911  *
912  * input :: target bitmap descriptor. The function will set its
913  *          'width', 'rows' and 'pitch' fields, and only these
914  *
915  * slot  :: the glyph slot containing the source bitmap. this
916  *          function assumes that slot->format == FT_GLYPH_FORMAT_BITMAP
917  *
918  * mode  :: the requested final rendering mode. supported values are
919  *          MONO, NORMAL (i.e. gray), LCD and LCD_V
920  *
921  * the function returns the size in bytes of the corresponding buffer,
922  * it's up to the caller to allocate the corresponding memory block
923  * before calling _fill_xrender_bitmap
924  *
925  * it also returns -1 in case of error (e.g. incompatible arguments,
926  * like trying to convert a gray bitmap into a monochrome one)
927  */
928 static int
_compute_xrender_bitmap_size(FT_Bitmap * target,FT_GlyphSlot slot,FT_Render_Mode mode)929 _compute_xrender_bitmap_size(FT_Bitmap      *target,
930 			     FT_GlyphSlot    slot,
931 			     FT_Render_Mode  mode)
932 {
933     FT_Bitmap *ftbit;
934     int width, height, pitch;
935 
936     if (slot->format != FT_GLYPH_FORMAT_BITMAP)
937 	return -1;
938 
939     /* compute the size of the final bitmap */
940     ftbit = &slot->bitmap;
941 
942     width = ftbit->width;
943     height = ftbit->rows;
944     pitch = (width + 3) & ~3;
945 
946     switch (ftbit->pixel_mode) {
947     case FT_PIXEL_MODE_MONO:
948 	if (mode == FT_RENDER_MODE_MONO) {
949 	    pitch = (((width + 31) & ~31) >> 3);
950 	    break;
951 	}
952 	/* fall-through */
953 
954     case FT_PIXEL_MODE_GRAY:
955 	if (mode == FT_RENDER_MODE_LCD ||
956 	    mode == FT_RENDER_MODE_LCD_V)
957 	{
958 	    /* each pixel is replicated into a 32-bit ARGB value */
959 	    pitch = width * 4;
960 	}
961 	break;
962 
963     case FT_PIXEL_MODE_LCD:
964 	if (mode != FT_RENDER_MODE_LCD)
965 	    return -1;
966 
967 	/* horz pixel triplets are packed into 32-bit ARGB values */
968 	width /= 3;
969 	pitch = width * 4;
970 	break;
971 
972     case FT_PIXEL_MODE_LCD_V:
973 	if (mode != FT_RENDER_MODE_LCD_V)
974 	    return -1;
975 
976 	/* vert pixel triplets are packed into 32-bit ARGB values */
977 	height /= 3;
978 	pitch = width * 4;
979 	break;
980 
981     default:  /* unsupported source format */
982 	return -1;
983     }
984 
985     target->width = width;
986     target->rows = height;
987     target->pitch = pitch;
988     target->buffer = NULL;
989 
990     return pitch * height;
991 }
992 
993 /* this functions converts the glyph bitmap found in a FT_GlyphSlot
994  * into a different format (see _compute_xrender_bitmap_size)
995  *
996  * you should call this function after _compute_xrender_bitmap_size
997  *
998  * target :: target bitmap descriptor. Note that its 'buffer' pointer
999  *           must point to memory allocated by the caller
1000  *
1001  * slot   :: the glyph slot containing the source bitmap
1002  *
1003  * mode   :: the requested final rendering mode
1004  *
1005  * bgr    :: boolean, set if BGR or VBGR pixel ordering is needed
1006  */
1007 static void
_fill_xrender_bitmap(FT_Bitmap * target,FT_GlyphSlot slot,FT_Render_Mode mode,int bgr)1008 _fill_xrender_bitmap(FT_Bitmap      *target,
1009 		     FT_GlyphSlot    slot,
1010 		     FT_Render_Mode  mode,
1011 		     int             bgr)
1012 {
1013     FT_Bitmap *ftbit = &slot->bitmap;
1014     unsigned char *srcLine = ftbit->buffer;
1015     unsigned char *dstLine = target->buffer;
1016     int src_pitch = ftbit->pitch;
1017     int width = target->width;
1018     int height = target->rows;
1019     int pitch = target->pitch;
1020     int subpixel;
1021     int h;
1022 
1023     subpixel = (mode == FT_RENDER_MODE_LCD ||
1024 		mode == FT_RENDER_MODE_LCD_V);
1025 
1026     if (src_pitch < 0)
1027 	srcLine -= src_pitch * (ftbit->rows - 1);
1028 
1029     target->pixel_mode = ftbit->pixel_mode;
1030 
1031     switch (ftbit->pixel_mode) {
1032     case FT_PIXEL_MODE_MONO:
1033 	if (subpixel) {
1034 	    /* convert mono to ARGB32 values */
1035 
1036 	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1037 		int x;
1038 
1039 		for (x = 0; x < width; x++) {
1040 		    if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
1041 			((unsigned int *) dstLine)[x] = 0xffffffffU;
1042 		}
1043 	    }
1044 	    target->pixel_mode = FT_PIXEL_MODE_LCD;
1045 
1046 	} else if (mode == FT_RENDER_MODE_NORMAL) {
1047 	    /* convert mono to 8-bit gray */
1048 
1049 	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1050 		int x;
1051 
1052 		for (x = 0; x < width; x++) {
1053 		    if (srcLine[(x >> 3)] & (0x80 >> (x & 7)))
1054 			dstLine[x] = 0xff;
1055 		}
1056 	    }
1057 	    target->pixel_mode = FT_PIXEL_MODE_GRAY;
1058 
1059 	} else {
1060 	    /* copy mono to mono */
1061 
1062 	    int  bytes = (width + 7) >> 3;
1063 
1064 	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
1065 		memcpy (dstLine, srcLine, bytes);
1066 	}
1067 	break;
1068 
1069     case FT_PIXEL_MODE_GRAY:
1070 	if (subpixel) {
1071 	    /* convert gray to ARGB32 values */
1072 
1073 	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1074 		int x;
1075 		unsigned int *dst = (unsigned int *) dstLine;
1076 
1077 		for (x = 0; x < width; x++) {
1078 		    unsigned int pix = srcLine[x];
1079 
1080 		    pix |= (pix << 8);
1081 		    pix |= (pix << 16);
1082 
1083 		    dst[x] = pix;
1084 		}
1085 	    }
1086 	    target->pixel_mode = FT_PIXEL_MODE_LCD;
1087         } else {
1088             /* copy gray into gray */
1089 
1090             for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch)
1091                 memcpy (dstLine, srcLine, width);
1092         }
1093         break;
1094 
1095     case FT_PIXEL_MODE_LCD:
1096 	if (!bgr) {
1097 	    /* convert horizontal RGB into ARGB32 */
1098 
1099 	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1100 		int x;
1101 		unsigned char *src = srcLine;
1102 		unsigned int *dst = (unsigned int *) dstLine;
1103 
1104 		for (x = 0; x < width; x++, src += 3) {
1105 		    unsigned int  pix;
1106 
1107 		    pix = ((unsigned int)src[0] << 16) |
1108 			  ((unsigned int)src[1] <<  8) |
1109 			  ((unsigned int)src[2]      ) |
1110 			  ((unsigned int)src[1] << 24) ;
1111 
1112 		    dst[x] = pix;
1113 		}
1114 	    }
1115 	} else {
1116 	    /* convert horizontal BGR into ARGB32 */
1117 
1118 	    for (h = height; h > 0; h--, srcLine += src_pitch, dstLine += pitch) {
1119 
1120 		int x;
1121 		unsigned char *src = srcLine;
1122 		unsigned int *dst = (unsigned int *) dstLine;
1123 
1124 		for (x = 0; x < width; x++, src += 3) {
1125 		    unsigned int  pix;
1126 
1127 		    pix = ((unsigned int)src[2] << 16) |
1128 			  ((unsigned int)src[1] <<  8) |
1129 			  ((unsigned int)src[0]      ) |
1130 			  ((unsigned int)src[1] << 24) ;
1131 
1132 		    dst[x] = pix;
1133 		}
1134 	    }
1135 	}
1136 	break;
1137 
1138     default:  /* FT_PIXEL_MODE_LCD_V */
1139 	/* convert vertical RGB into ARGB32 */
1140 	if (!bgr) {
1141 
1142 	    for (h = height; h > 0; h--, srcLine += 3 * src_pitch, dstLine += pitch) {
1143 		int x;
1144 		unsigned char* src = srcLine;
1145 		unsigned int*  dst = (unsigned int *) dstLine;
1146 
1147 		for (x = 0; x < width; x++, src += 1) {
1148 		    unsigned int pix;
1149 		    pix = ((unsigned int)src[0]           << 16) |
1150 			  ((unsigned int)src[src_pitch]   <<  8) |
1151 			  ((unsigned int)src[src_pitch*2]      ) |
1152 			  ((unsigned int)src[src_pitch]   << 24) ;
1153 		    dst[x] = pix;
1154 		}
1155 	    }
1156 	} else {
1157 
1158 	    for (h = height; h > 0; h--, srcLine += 3*src_pitch, dstLine += pitch) {
1159 		int x;
1160 		unsigned char *src = srcLine;
1161 		unsigned int *dst = (unsigned int *) dstLine;
1162 
1163 		for (x = 0; x < width; x++, src += 1) {
1164 		    unsigned int  pix;
1165 
1166 		    pix = ((unsigned int)src[src_pitch * 2] << 16) |
1167 			  ((unsigned int)src[src_pitch]     <<  8) |
1168 			  ((unsigned int)src[0]                  ) |
1169 			  ((unsigned int)src[src_pitch]     << 24) ;
1170 
1171 		    dst[x] = pix;
1172 		}
1173 	    }
1174 	}
1175     }
1176 }
1177 
1178 
1179 /* Fills in val->image with an image surface created from @bitmap
1180  */
1181 static cairo_status_t
_get_bitmap_surface(FT_Bitmap * bitmap,FT_Library library,cairo_bool_t own_buffer,cairo_font_options_t * font_options,cairo_image_surface_t ** surface)1182 _get_bitmap_surface (FT_Bitmap		     *bitmap,
1183 		     FT_Library		      library,
1184 		     cairo_bool_t	      own_buffer,
1185 		     cairo_font_options_t    *font_options,
1186 		     cairo_image_surface_t  **surface)
1187 {
1188     int width, height, stride;
1189     unsigned char *data;
1190     int format = CAIRO_FORMAT_A8;
1191     cairo_image_surface_t *image;
1192     cairo_bool_t component_alpha = FALSE;
1193 
1194     width = bitmap->width;
1195     height = bitmap->rows;
1196 
1197     if (width == 0 || height == 0) {
1198 	*surface = (cairo_image_surface_t *)
1199 	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
1200 	return (*surface)->base.status;
1201     }
1202 
1203     switch (bitmap->pixel_mode) {
1204     case FT_PIXEL_MODE_MONO:
1205 	stride = (((width + 31) & ~31) >> 3);
1206 	if (own_buffer) {
1207 	    data = bitmap->buffer;
1208 	    assert (stride == bitmap->pitch);
1209 	} else {
1210 	    data = _cairo_malloc_ab (height, stride);
1211 	    if (!data)
1212 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1213 
1214 	    if (stride == bitmap->pitch) {
1215 		memcpy (data, bitmap->buffer, stride * height);
1216 	    } else {
1217 		int i;
1218 		unsigned char *source, *dest;
1219 		int copy_len = MIN (stride, bitmap->pitch);
1220 		int pad_len = stride - bitmap->pitch;
1221 
1222 		source = bitmap->buffer;
1223 		dest = data;
1224 		for (i = height; i; i--) {
1225 		    memcpy (dest, source, copy_len);
1226 		    source += bitmap->pitch;
1227 		    dest += stride;
1228 		}
1229 		/* do we really care about zeroing any extra row padding in dest? */
1230 		if (pad_len > 0) {
1231 		    dest = data + copy_len;
1232 		    for (i = height; i; i--) {
1233 			memset (dest, '\0', pad_len);
1234 			dest += stride;
1235 		    }
1236 		}
1237 	    }
1238 	}
1239 
1240 #ifndef WORDS_BIGENDIAN
1241 	{
1242 	    uint8_t   *d = data;
1243 	    int		count = stride * height;
1244 
1245 	    while (count--) {
1246 		*d = CAIRO_BITSWAP8 (*d);
1247 		d++;
1248 	    }
1249 	}
1250 #endif
1251 	format = CAIRO_FORMAT_A1;
1252 	break;
1253 
1254     case FT_PIXEL_MODE_LCD:
1255     case FT_PIXEL_MODE_LCD_V:
1256     case FT_PIXEL_MODE_GRAY:
1257 	if (font_options->antialias != CAIRO_ANTIALIAS_SUBPIXEL ||
1258 	    bitmap->pixel_mode == FT_PIXEL_MODE_GRAY)
1259 	{
1260 	    stride = bitmap->pitch;
1261 
1262 	    /* We don't support stride not multiple of 4. */
1263 	    if (stride & 3)
1264 	    {
1265 		assert (!own_buffer);
1266 		goto convert;
1267 	    }
1268 
1269 	    if (own_buffer) {
1270 		data = bitmap->buffer;
1271 	    } else {
1272 		data = _cairo_malloc_ab (height, stride);
1273 		if (!data)
1274 		    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1275 
1276 		memcpy (data, bitmap->buffer, stride * height);
1277 	    }
1278 
1279 	    format = CAIRO_FORMAT_A8;
1280 	} else {
1281 	    data = bitmap->buffer;
1282 	    stride = bitmap->pitch;
1283 	    format = CAIRO_FORMAT_ARGB32;
1284 	    component_alpha = TRUE;
1285 	}
1286 	break;
1287 #ifdef FT_LOAD_COLOR
1288     case FT_PIXEL_MODE_BGRA:
1289 	stride = width * 4;
1290 	if (own_buffer) {
1291 	    data = bitmap->buffer;
1292 	} else {
1293 	    data = _cairo_malloc_ab (height, stride);
1294 	    if (!data)
1295 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1296 
1297 	    memcpy (data, bitmap->buffer, stride * height);
1298 	}
1299 	format = CAIRO_FORMAT_ARGB32;
1300 	break;
1301 #endif
1302     case FT_PIXEL_MODE_GRAY2:
1303     case FT_PIXEL_MODE_GRAY4:
1304     convert:
1305 	if (!own_buffer && library)
1306 	{
1307 	    /* This is pretty much the only case that we can get in here. */
1308 	    /* Convert to 8bit grayscale. */
1309 
1310 	    FT_Bitmap  tmp;
1311 	    FT_Int     align;
1312 
1313 	    format = CAIRO_FORMAT_A8;
1314 
1315 	    align = cairo_format_stride_for_width (format, bitmap->width);
1316 
1317 	    FT_Bitmap_New( &tmp );
1318 
1319 	    if (FT_Bitmap_Convert( library, bitmap, &tmp, align ))
1320 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1321 
1322 	    FT_Bitmap_Done( library, bitmap );
1323 	    *bitmap = tmp;
1324 
1325 	    stride = bitmap->pitch;
1326 	    data = _cairo_malloc_ab (height, stride);
1327 	    if (!data)
1328 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1329 
1330 	    if (bitmap->num_grays != 256)
1331 	    {
1332 	      unsigned int x, y;
1333 	      unsigned int mul = 255 / (bitmap->num_grays - 1);
1334 	      FT_Byte *p = bitmap->buffer;
1335 	      for (y = 0; y < height; y++) {
1336 	        for (x = 0; x < width; x++)
1337 		  p[x] *= mul;
1338 		p += bitmap->pitch;
1339 	      }
1340 	    }
1341 
1342 	    memcpy (data, bitmap->buffer, stride * height);
1343 	    break;
1344 	}
1345 	/* These could be triggered by very rare types of TrueType fonts */
1346     default:
1347 	if (own_buffer)
1348 	    free (bitmap->buffer);
1349 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1350     }
1351 
1352     /* XXX */
1353     *surface = image = (cairo_image_surface_t *)
1354 	cairo_image_surface_create_for_data (data,
1355 					     format,
1356 					     width, height, stride);
1357     if (image->base.status) {
1358 	free (data);
1359 	return (*surface)->base.status;
1360     }
1361 
1362     if (component_alpha)
1363 	pixman_image_set_component_alpha (image->pixman_image, TRUE);
1364 
1365     _cairo_image_surface_assume_ownership_of_data (image);
1366 
1367     _cairo_debug_check_image_surface_is_defined (&image->base);
1368 
1369     return CAIRO_STATUS_SUCCESS;
1370 }
1371 
1372 /* Converts an outline FT_GlyphSlot into an image
1373  *
1374  * This could go through _render_glyph_bitmap as well, letting
1375  * FreeType convert the outline to a bitmap, but doing it ourselves
1376  * has two minor advantages: first, we save a copy of the bitmap
1377  * buffer: we can directly use the buffer that FreeType renders
1378  * into.
1379  *
1380  * Second, it may help when we add support for subpixel
1381  * rendering: the Xft code does it this way. (Keith thinks that
1382  * it may also be possible to get the subpixel rendering with
1383  * FT_Render_Glyph: something worth looking into in more detail
1384  * when we add subpixel support. If so, we may want to eliminate
1385  * this version of the code path entirely.
1386  */
1387 static cairo_status_t
_render_glyph_outline(FT_Face face,cairo_font_options_t * font_options,cairo_image_surface_t ** surface)1388 _render_glyph_outline (FT_Face                    face,
1389 		       cairo_font_options_t	 *font_options,
1390 		       cairo_image_surface_t	**surface)
1391 {
1392     int rgba = FC_RGBA_UNKNOWN;
1393     int lcd_filter = FT_LCD_FILTER_LEGACY;
1394     FT_GlyphSlot glyphslot = face->glyph;
1395     FT_Outline *outline = &glyphslot->outline;
1396     FT_Bitmap bitmap;
1397     FT_BBox cbox;
1398     unsigned int width, height;
1399     cairo_status_t status;
1400     FT_Error fterror;
1401     FT_Library library = glyphslot->library;
1402     FT_Render_Mode render_mode = FT_RENDER_MODE_NORMAL;
1403 
1404     switch (font_options->antialias) {
1405     case CAIRO_ANTIALIAS_NONE:
1406 	render_mode = FT_RENDER_MODE_MONO;
1407 	break;
1408 
1409     case CAIRO_ANTIALIAS_SUBPIXEL:
1410 	switch (font_options->subpixel_order) {
1411 	    case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1412 	    case CAIRO_SUBPIXEL_ORDER_RGB:
1413 	    case CAIRO_SUBPIXEL_ORDER_BGR:
1414 		render_mode = FT_RENDER_MODE_LCD;
1415 		break;
1416 
1417 	    case CAIRO_SUBPIXEL_ORDER_VRGB:
1418 	    case CAIRO_SUBPIXEL_ORDER_VBGR:
1419 		render_mode = FT_RENDER_MODE_LCD_V;
1420 		break;
1421 	}
1422 
1423 	switch (font_options->lcd_filter) {
1424 	case CAIRO_LCD_FILTER_NONE:
1425 	    lcd_filter = FT_LCD_FILTER_NONE;
1426 	    break;
1427 	case CAIRO_LCD_FILTER_DEFAULT:
1428 	case CAIRO_LCD_FILTER_INTRA_PIXEL:
1429 	    lcd_filter = FT_LCD_FILTER_LEGACY;
1430 	    break;
1431 	case CAIRO_LCD_FILTER_FIR3:
1432 	    lcd_filter = FT_LCD_FILTER_LIGHT;
1433 	    break;
1434 	case CAIRO_LCD_FILTER_FIR5:
1435 	    lcd_filter = FT_LCD_FILTER_DEFAULT;
1436 	    break;
1437 	}
1438 
1439 	break;
1440 
1441     case CAIRO_ANTIALIAS_DEFAULT:
1442     case CAIRO_ANTIALIAS_GRAY:
1443 	render_mode = FT_RENDER_MODE_NORMAL;
1444     }
1445 
1446     FT_Outline_Get_CBox (outline, &cbox);
1447 
1448     cbox.xMin &= -64;
1449     cbox.yMin &= -64;
1450     cbox.xMax = (cbox.xMax + 63) & -64;
1451     cbox.yMax = (cbox.yMax + 63) & -64;
1452 
1453     width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
1454     height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
1455 
1456     if (width * height == 0) {
1457 	cairo_format_t format;
1458 	/* Looks like fb handles zero-sized images just fine */
1459 	switch (render_mode) {
1460 	case FT_RENDER_MODE_MONO:
1461 	    format = CAIRO_FORMAT_A1;
1462 	    break;
1463 	case FT_RENDER_MODE_LCD:
1464 	case FT_RENDER_MODE_LCD_V:
1465 	    format= CAIRO_FORMAT_ARGB32;
1466 	    break;
1467 	case FT_RENDER_MODE_LIGHT:
1468 	case FT_RENDER_MODE_NORMAL:
1469 	case FT_RENDER_MODE_MAX:
1470 	default:
1471 	    format = CAIRO_FORMAT_A8;
1472 	    break;
1473 	}
1474 
1475 	(*surface) = (cairo_image_surface_t *)
1476 	    cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
1477 	if ((*surface)->base.status)
1478 	    return (*surface)->base.status;
1479     } else {
1480 
1481 	int bitmap_size;
1482         static int initialized_setLcdFilter = 0;
1483 
1484 	switch (render_mode) {
1485 	case FT_RENDER_MODE_LCD:
1486 	    if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_BGR) {
1487 		rgba = FC_RGBA_BGR;
1488 	    } else {
1489 		rgba = FC_RGBA_RGB;
1490 	    }
1491             break;
1492 	case FT_RENDER_MODE_LCD_V:
1493 	    if (font_options->subpixel_order == CAIRO_SUBPIXEL_ORDER_VBGR) {
1494 		rgba = FC_RGBA_VBGR;
1495 	    } else {
1496 		rgba = FC_RGBA_VRGB;
1497 		}
1498 	    break;
1499 	case FT_RENDER_MODE_MONO:
1500 	case FT_RENDER_MODE_LIGHT:
1501 	case FT_RENDER_MODE_NORMAL:
1502 	case FT_RENDER_MODE_MAX:
1503 	default:
1504 	    break;
1505 	    }
1506 
1507         if (!initialized_setLcdFilter) {
1508           initialized_setLcdFilter = 1;
1509 #ifdef HAVE_FT_LIBRARY_SETLCDFILTER
1510 	  setLcdFilter = &FT_Library_SetLcdFilter;
1511 #else
1512           setLcdFilter = (setLcdFilterFunc) dlsym(RTLD_DEFAULT, "FT_Library_SetLcdFilter");
1513 #endif
1514         }
1515 
1516 	if (setLcdFilter &&
1517 	    (render_mode == FT_RENDER_MODE_LCD ||
1518 	     render_mode == FT_RENDER_MODE_LCD_V)) {
1519 	    mozilla_LockFTLibrary (library);
1520 	    setLcdFilter (library, lcd_filter);
1521 	}
1522 
1523 	fterror = FT_Render_Glyph (face->glyph, render_mode);
1524 
1525 	if (setLcdFilter &&
1526 	    (render_mode == FT_RENDER_MODE_LCD ||
1527 	     render_mode == FT_RENDER_MODE_LCD_V)) {
1528 	    setLcdFilter (library, FT_LCD_FILTER_NONE);
1529 	    mozilla_UnlockFTLibrary (library);
1530 	}
1531 
1532 	if (fterror != 0)
1533 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1534 
1535 	bitmap_size = _compute_xrender_bitmap_size (&bitmap,
1536 						    face->glyph,
1537 						    render_mode);
1538 	if (bitmap_size < 0)
1539 	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1540 
1541 	bitmap.buffer = calloc (1, bitmap_size);
1542 	if (bitmap.buffer == NULL)
1543 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1544 
1545 	_fill_xrender_bitmap (&bitmap, face->glyph, render_mode,
1546 			      (rgba == FC_RGBA_BGR || rgba == FC_RGBA_VBGR));
1547 
1548 	/* Note:
1549 	 * _get_bitmap_surface will free bitmap.buffer if there is an error
1550 	 */
1551 	status = _get_bitmap_surface (&bitmap, NULL, TRUE, font_options, surface);
1552 	if (unlikely (status))
1553 	    return status;
1554 
1555 	/* Note: the font's coordinate system is upside down from ours, so the
1556 	 * Y coordinate of the control box needs to be negated.  Moreover, device
1557 	 * offsets are position of glyph origin relative to top left while xMin
1558 	 * and yMax are offsets of top left relative to origin.  Another negation.
1559 	 */
1560 	cairo_surface_set_device_offset (&(*surface)->base,
1561 					 (double)-glyphslot->bitmap_left,
1562 					 (double)+glyphslot->bitmap_top);
1563     }
1564 
1565     return CAIRO_STATUS_SUCCESS;
1566 }
1567 
1568 /* Converts a bitmap (or other) FT_GlyphSlot into an image */
1569 static cairo_status_t
_render_glyph_bitmap(FT_Face face,cairo_font_options_t * font_options,cairo_image_surface_t ** surface)1570 _render_glyph_bitmap (FT_Face		      face,
1571 		      cairo_font_options_t   *font_options,
1572 		      cairo_image_surface_t **surface)
1573 {
1574     FT_GlyphSlot glyphslot = face->glyph;
1575     cairo_status_t status;
1576     FT_Error error;
1577 
1578     /* According to the FreeType docs, glyphslot->format could be
1579      * something other than FT_GLYPH_FORMAT_OUTLINE or
1580      * FT_GLYPH_FORMAT_BITMAP. Calling FT_Render_Glyph gives FreeType
1581      * the opportunity to convert such to
1582      * bitmap. FT_GLYPH_FORMAT_COMPOSITE will not be encountered since
1583      * we avoid the FT_LOAD_NO_RECURSE flag.
1584      */
1585     error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
1586     /* XXX ignoring all other errors for now.  They are not fatal, typically
1587      * just a glyph-not-found. */
1588     if (error == FT_Err_Out_Of_Memory)
1589 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1590 
1591     status = _get_bitmap_surface (&glyphslot->bitmap,
1592 				  glyphslot->library,
1593 				  FALSE, font_options,
1594 				  surface);
1595     if (unlikely (status))
1596 	return status;
1597 
1598     /*
1599      * Note: the font's coordinate system is upside down from ours, so the
1600      * Y coordinate of the control box needs to be negated.  Moreover, device
1601      * offsets are position of glyph origin relative to top left while
1602      * bitmap_left and bitmap_top are offsets of top left relative to origin.
1603      * Another negation.
1604      */
1605     cairo_surface_set_device_offset (&(*surface)->base,
1606 				     -glyphslot->bitmap_left,
1607 				     +glyphslot->bitmap_top);
1608 
1609     return CAIRO_STATUS_SUCCESS;
1610 }
1611 
1612 static cairo_status_t
_transform_glyph_bitmap(cairo_matrix_t * shape,cairo_image_surface_t ** surface)1613 _transform_glyph_bitmap (cairo_matrix_t         * shape,
1614 			 cairo_image_surface_t ** surface)
1615 {
1616     cairo_matrix_t original_to_transformed;
1617     cairo_matrix_t transformed_to_original;
1618     cairo_image_surface_t *old_image;
1619     cairo_surface_t *image;
1620     double x[4], y[4];
1621     double origin_x, origin_y;
1622     int orig_width, orig_height;
1623     int i;
1624     int x_min, y_min, x_max, y_max;
1625     int width, height;
1626     cairo_status_t status;
1627     cairo_surface_pattern_t pattern;
1628 
1629     /* We want to compute a transform that takes the origin
1630      * (device_x_offset, device_y_offset) to 0,0, then applies
1631      * the "shape" portion of the font transform
1632      */
1633     original_to_transformed = *shape;
1634 
1635     cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y);
1636     orig_width = (*surface)->width;
1637     orig_height = (*surface)->height;
1638 
1639     cairo_matrix_translate (&original_to_transformed,
1640 			    -origin_x, -origin_y);
1641 
1642     /* Find the bounding box of the original bitmap under that
1643      * transform
1644      */
1645     x[0] = 0;          y[0] = 0;
1646     x[1] = orig_width; y[1] = 0;
1647     x[2] = orig_width; y[2] = orig_height;
1648     x[3] = 0;          y[3] = orig_height;
1649 
1650     for (i = 0; i < 4; i++)
1651       cairo_matrix_transform_point (&original_to_transformed,
1652 				    &x[i], &y[i]);
1653 
1654     x_min = floor (x[0]);   y_min = floor (y[0]);
1655     x_max =  ceil (x[0]);   y_max =  ceil (y[0]);
1656 
1657     for (i = 1; i < 4; i++) {
1658 	if (x[i] < x_min)
1659 	    x_min = floor (x[i]);
1660 	else if (x[i] > x_max)
1661 	    x_max = ceil (x[i]);
1662 	if (y[i] < y_min)
1663 	    y_min = floor (y[i]);
1664 	else if (y[i] > y_max)
1665 	    y_max = ceil (y[i]);
1666     }
1667 
1668     /* Adjust the transform so that the bounding box starts at 0,0 ...
1669      * this gives our final transform from original bitmap to transformed
1670      * bitmap.
1671      */
1672     original_to_transformed.x0 -= x_min;
1673     original_to_transformed.y0 -= y_min;
1674 
1675     /* Create the transformed bitmap */
1676     width  = x_max - x_min;
1677     height = y_max - y_min;
1678 
1679     transformed_to_original = original_to_transformed;
1680     status = cairo_matrix_invert (&transformed_to_original);
1681     if (unlikely (status))
1682 	return status;
1683 
1684     if (cairo_image_surface_get_format (*surface) == CAIRO_FORMAT_ARGB32 &&
1685         !pixman_image_get_component_alpha ((*surface)->pixman_image))
1686       image = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
1687     else
1688       image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
1689     if (unlikely (image->status))
1690 	return image->status;
1691 
1692     /* Draw the original bitmap transformed into the new bitmap
1693      */
1694     _cairo_pattern_init_for_surface (&pattern, &(*surface)->base);
1695     cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
1696 
1697     status = _cairo_surface_paint (image,
1698 				   CAIRO_OPERATOR_SOURCE,
1699 				   &pattern.base,
1700 				   NULL);
1701 
1702     _cairo_pattern_fini (&pattern.base);
1703 
1704     if (unlikely (status)) {
1705 	cairo_surface_destroy (image);
1706 	return status;
1707     }
1708 
1709     /* Now update the cache entry for the new bitmap, recomputing
1710      * the origin based on the final transform.
1711      */
1712     cairo_matrix_transform_point (&original_to_transformed,
1713 				  &origin_x, &origin_y);
1714 
1715     old_image = (*surface);
1716     (*surface) = (cairo_image_surface_t *)image;
1717     cairo_surface_destroy (&old_image->base);
1718 
1719     cairo_surface_set_device_offset (&(*surface)->base,
1720 				     _cairo_lround (origin_x),
1721 				     _cairo_lround (origin_y));
1722     return CAIRO_STATUS_SUCCESS;
1723 }
1724 
1725 static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = {
1726     _cairo_ft_unscaled_font_destroy,
1727 #if 0
1728     _cairo_ft_unscaled_font_create_glyph
1729 #endif
1730 };
1731 
1732 /* #cairo_ft_scaled_font_t */
1733 
1734 typedef struct _cairo_ft_scaled_font {
1735     cairo_scaled_font_t base;
1736     cairo_ft_unscaled_font_t *unscaled;
1737     cairo_ft_options_t ft_options;
1738 } cairo_ft_scaled_font_t;
1739 
1740 static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend;
1741 
1742 #if CAIRO_HAS_FC_FONT
1743 /* The load flags passed to FT_Load_Glyph control aspects like hinting and
1744  * antialiasing. Here we compute them from the fields of a FcPattern.
1745  */
1746 static void
_get_pattern_ft_options(FcPattern * pattern,cairo_ft_options_t * ret)1747 _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
1748 {
1749     FcBool antialias, vertical_layout, hinting, autohint, bitmap, embolden;
1750     cairo_ft_options_t ft_options;
1751     int rgba;
1752 #ifdef FC_HINT_STYLE
1753     int hintstyle;
1754 #endif
1755 
1756     _cairo_font_options_init_default (&ft_options.base);
1757     ft_options.load_flags = FT_LOAD_DEFAULT;
1758     ft_options.extra_flags = 0;
1759 
1760 #ifndef FC_EMBEDDED_BITMAP
1761 #define FC_EMBEDDED_BITMAP "embeddedbitmap"
1762 #endif
1763 
1764     /* Check whether to force use of embedded bitmaps */
1765     if (FcPatternGetBool (pattern,
1766 			  FC_EMBEDDED_BITMAP, 0, &bitmap) != FcResultMatch)
1767 	bitmap = FcFalse;
1768 
1769     /* disable antialiasing if requested */
1770     if (FcPatternGetBool (pattern,
1771 			  FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
1772 	antialias = FcTrue;
1773 
1774     if (antialias) {
1775 	cairo_subpixel_order_t subpixel_order;
1776 	int lcd_filter;
1777 
1778 	/* disable hinting if requested */
1779 	if (FcPatternGetBool (pattern,
1780 			      FC_HINTING, 0, &hinting) != FcResultMatch)
1781 	    hinting = FcTrue;
1782 
1783 	if (FcPatternGetInteger (pattern,
1784 				 FC_RGBA, 0, &rgba) != FcResultMatch)
1785 	    rgba = FC_RGBA_UNKNOWN;
1786 
1787 	switch (rgba) {
1788 	case FC_RGBA_RGB:
1789 	    subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
1790 	    break;
1791 	case FC_RGBA_BGR:
1792 	    subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
1793 	    break;
1794 	case FC_RGBA_VRGB:
1795 	    subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
1796 	    break;
1797 	case FC_RGBA_VBGR:
1798 	    subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
1799 	    break;
1800 	case FC_RGBA_UNKNOWN:
1801 	case FC_RGBA_NONE:
1802 	default:
1803 	    subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
1804 	    break;
1805 	}
1806 
1807 	if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) {
1808 	    ft_options.base.subpixel_order = subpixel_order;
1809 	    ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
1810 	}
1811 
1812 	if (FcPatternGetInteger (pattern,
1813 				 FC_LCD_FILTER, 0, &lcd_filter) == FcResultMatch)
1814 	{
1815 	    switch (lcd_filter) {
1816 	    case FC_LCD_NONE:
1817 		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_NONE;
1818 		break;
1819 	    case FC_LCD_DEFAULT:
1820 		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR5;
1821 		break;
1822 	    case FC_LCD_LIGHT:
1823 		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_FIR3;
1824 		break;
1825 	    case FC_LCD_LEGACY:
1826 		ft_options.base.lcd_filter = CAIRO_LCD_FILTER_INTRA_PIXEL;
1827 		break;
1828 	    }
1829 	}
1830 
1831 #ifdef FC_HINT_STYLE
1832 	if (FcPatternGetInteger (pattern,
1833 				 FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
1834 	    hintstyle = FC_HINT_FULL;
1835 
1836 	if (!hinting)
1837 	    hintstyle = FC_HINT_NONE;
1838 
1839 	switch (hintstyle) {
1840 	case FC_HINT_NONE:
1841 	    ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
1842 	    break;
1843 	case FC_HINT_SLIGHT:
1844 	    ft_options.base.hint_style = CAIRO_HINT_STYLE_SLIGHT;
1845 	    break;
1846 	case FC_HINT_MEDIUM:
1847 	default:
1848 	    ft_options.base.hint_style = CAIRO_HINT_STYLE_MEDIUM;
1849 	    break;
1850 	case FC_HINT_FULL:
1851 	    ft_options.base.hint_style = CAIRO_HINT_STYLE_FULL;
1852 	    break;
1853 	}
1854 #else /* !FC_HINT_STYLE */
1855 	if (!hinting) {
1856 	    ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
1857 	}
1858 #endif /* FC_HINT_STYLE */
1859 
1860 	/* Force embedded bitmaps off if no hinting requested */
1861 	if (ft_options.base.hint_style == CAIRO_HINT_STYLE_NONE)
1862 	  bitmap = FcFalse;
1863 
1864 	if (!bitmap)
1865 	    ft_options.load_flags |= FT_LOAD_NO_BITMAP;
1866 
1867     } else {
1868 	ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
1869     }
1870 
1871     /* force autohinting if requested */
1872     if (FcPatternGetBool (pattern,
1873 			  FC_AUTOHINT, 0, &autohint) != FcResultMatch)
1874 	autohint = FcFalse;
1875 
1876     if (autohint)
1877 	ft_options.load_flags |= FT_LOAD_FORCE_AUTOHINT;
1878 
1879     if (FcPatternGetBool (pattern,
1880 			  FC_VERTICAL_LAYOUT, 0, &vertical_layout) != FcResultMatch)
1881 	vertical_layout = FcFalse;
1882 
1883     if (vertical_layout)
1884 	ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT;
1885 
1886 #ifndef FC_EMBOLDEN
1887 #define FC_EMBOLDEN "embolden"
1888 #endif
1889     if (FcPatternGetBool (pattern,
1890 			  FC_EMBOLDEN, 0, &embolden) != FcResultMatch)
1891 	embolden = FcFalse;
1892 
1893     if (embolden)
1894 	ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN;
1895 
1896     *ret = ft_options;
1897 }
1898 #endif
1899 
1900 static void
_cairo_ft_options_merge(cairo_ft_options_t * options,cairo_ft_options_t * other)1901 _cairo_ft_options_merge (cairo_ft_options_t *options,
1902 			 cairo_ft_options_t *other)
1903 {
1904     int load_flags = other->load_flags;
1905     int load_target = FT_LOAD_TARGET_NORMAL;
1906 
1907     /* clear load target mode */
1908     load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(other->load_flags)));
1909 
1910     if (load_flags & FT_LOAD_NO_HINTING)
1911 	other->base.hint_style = CAIRO_HINT_STYLE_NONE;
1912 
1913     if (other->base.antialias == CAIRO_ANTIALIAS_NONE ||
1914 	options->base.antialias == CAIRO_ANTIALIAS_NONE) {
1915 	options->base.antialias = CAIRO_ANTIALIAS_NONE;
1916 	options->base.subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
1917     } else if (options->base.antialias != CAIRO_ANTIALIAS_GRAY) {
1918 	/* The surface supports subpixel aa, so let the font face options
1919 	 * choose whether to use subpixel aa.  If the surface has
1920 	 * CAIRO_ANTIALIAS_GRAY (e.g. PS, PDF, SVG, translucent part of a
1921 	 * CONTENT_COLOR_ALPHA surface), then don't accept subpixel aa. */
1922 	if (other->base.antialias != CAIRO_ANTIALIAS_DEFAULT)
1923 	    options->base.antialias = other->base.antialias;
1924 	/* If the surface knows the subpixel order then use that. */
1925 	if (options->base.subpixel_order == CAIRO_SUBPIXEL_ORDER_DEFAULT)
1926 	    options->base.subpixel_order = other->base.subpixel_order;
1927     }
1928 
1929     if (options->base.hint_style == CAIRO_HINT_STYLE_DEFAULT)
1930 	options->base.hint_style = other->base.hint_style;
1931 
1932     if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
1933 	options->base.hint_style = CAIRO_HINT_STYLE_NONE;
1934 
1935     if (options->base.lcd_filter == CAIRO_LCD_FILTER_DEFAULT)
1936 	options->base.lcd_filter = other->base.lcd_filter;
1937 
1938     if (other->base.lcd_filter == CAIRO_LCD_FILTER_NONE)
1939 	options->base.lcd_filter = CAIRO_LCD_FILTER_NONE;
1940 
1941     if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
1942 	if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
1943 	    load_flags |= FT_LOAD_NO_HINTING;
1944 	else
1945 	    load_target = FT_LOAD_TARGET_MONO;
1946 	load_flags |= FT_LOAD_MONOCHROME;
1947     } else {
1948 	switch (options->base.hint_style) {
1949 	case CAIRO_HINT_STYLE_NONE:
1950 	    load_flags |= FT_LOAD_NO_HINTING;
1951 	    break;
1952 	case CAIRO_HINT_STYLE_SLIGHT:
1953 	    load_target = FT_LOAD_TARGET_LIGHT;
1954 	    break;
1955 	case CAIRO_HINT_STYLE_MEDIUM:
1956 	    break;
1957 	case CAIRO_HINT_STYLE_FULL:
1958 	case CAIRO_HINT_STYLE_DEFAULT:
1959 	    if (options->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
1960 		switch (options->base.subpixel_order) {
1961 		case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1962 		case CAIRO_SUBPIXEL_ORDER_RGB:
1963 		case CAIRO_SUBPIXEL_ORDER_BGR:
1964 		    load_target = FT_LOAD_TARGET_LCD;
1965 		    break;
1966 		case CAIRO_SUBPIXEL_ORDER_VRGB:
1967 		case CAIRO_SUBPIXEL_ORDER_VBGR:
1968 		    load_target = FT_LOAD_TARGET_LCD_V;
1969 		break;
1970 		}
1971 	    }
1972 	    break;
1973 	}
1974     }
1975 
1976     options->load_flags = load_flags | load_target;
1977     options->extra_flags = other->extra_flags;
1978     if (options->base.hint_metrics != CAIRO_HINT_METRICS_OFF)
1979 	options->extra_flags |= CAIRO_FT_OPTIONS_HINT_METRICS;
1980 }
1981 
1982 static cairo_status_t
_cairo_ft_font_face_scaled_font_create(void * abstract_font_face,const cairo_matrix_t * font_matrix,const cairo_matrix_t * ctm,const cairo_font_options_t * options,cairo_scaled_font_t ** font_out)1983 _cairo_ft_font_face_scaled_font_create (void		    *abstract_font_face,
1984 					const cairo_matrix_t	 *font_matrix,
1985 					const cairo_matrix_t	 *ctm,
1986 					const cairo_font_options_t *options,
1987 					cairo_scaled_font_t       **font_out)
1988 {
1989     cairo_ft_font_face_t *font_face = abstract_font_face;
1990     cairo_ft_scaled_font_t *scaled_font;
1991     FT_Face face;
1992     FT_Size_Metrics *metrics;
1993     cairo_font_extents_t fs_metrics;
1994     cairo_status_t status;
1995     cairo_ft_unscaled_font_t *unscaled;
1996 
1997     assert (font_face->unscaled);
1998 
1999     face = _cairo_ft_unscaled_font_lock_face (font_face->unscaled);
2000     if (unlikely (face == NULL)) /* backend error */
2001 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2002 
2003     scaled_font = malloc (sizeof (cairo_ft_scaled_font_t));
2004     if (unlikely (scaled_font == NULL)) {
2005 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2006 	goto FAIL;
2007     }
2008 
2009     scaled_font->unscaled = unscaled = font_face->unscaled;
2010     _cairo_unscaled_font_reference (&unscaled->base);
2011 
2012     _cairo_font_options_init_copy (&scaled_font->ft_options.base, options);
2013     _cairo_ft_options_merge (&scaled_font->ft_options, &font_face->ft_options);
2014 
2015     status = _cairo_scaled_font_init (&scaled_font->base,
2016 			              &font_face->base,
2017 				      font_matrix, ctm, options,
2018 				      &_cairo_ft_scaled_font_backend);
2019     if (unlikely (status))
2020 	goto CLEANUP_SCALED_FONT;
2021 
2022     status = _cairo_ft_unscaled_font_set_scale (unscaled,
2023 				                &scaled_font->base.scale);
2024     if (unlikely (status)) {
2025 	/* This can only fail if we encounter an error with the underlying
2026 	 * font, so propagate the error back to the font-face. */
2027 	_cairo_ft_unscaled_font_unlock_face (unscaled);
2028 	_cairo_unscaled_font_destroy (&unscaled->base);
2029 	free (scaled_font);
2030 	return status;
2031     }
2032 
2033 
2034     metrics = &face->size->metrics;
2035 
2036     /*
2037      * Get to unscaled metrics so that the upper level can get back to
2038      * user space
2039      *
2040      * Also use this path for bitmap-only fonts.  The other branch uses
2041      * face members that are only relevant for scalable fonts.  This is
2042      * detected by simply checking for units_per_EM==0.
2043      */
2044     if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF ||
2045 	face->units_per_EM == 0) {
2046 	double x_factor, y_factor;
2047 
2048 	if (unscaled->x_scale == 0)
2049 	    x_factor = 0;
2050 	else
2051 	    x_factor = 1 / unscaled->x_scale;
2052 
2053 	if (unscaled->y_scale == 0)
2054 	    y_factor = 0;
2055 	else
2056 	    y_factor = 1 / unscaled->y_scale;
2057 
2058 	fs_metrics.ascent =        DOUBLE_FROM_26_6(metrics->ascender) * y_factor;
2059 	fs_metrics.descent =       DOUBLE_FROM_26_6(- metrics->descender) * y_factor;
2060 	fs_metrics.height =        DOUBLE_FROM_26_6(metrics->height) * y_factor;
2061 	if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
2062 	    fs_metrics.max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) * x_factor;
2063 	    fs_metrics.max_y_advance = 0;
2064 	} else {
2065 	    fs_metrics.max_x_advance = 0;
2066 	    fs_metrics.max_y_advance = DOUBLE_FROM_26_6(metrics->max_advance) * y_factor;
2067 	}
2068     } else {
2069 	double scale = face->units_per_EM;
2070 
2071 	fs_metrics.ascent =        face->ascender / scale;
2072 	fs_metrics.descent =       - face->descender / scale;
2073 	fs_metrics.height =        face->height / scale;
2074 	if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
2075 	    fs_metrics.max_x_advance = face->max_advance_width / scale;
2076 	    fs_metrics.max_y_advance = 0;
2077 	} else {
2078 	    fs_metrics.max_x_advance = 0;
2079 	    fs_metrics.max_y_advance = face->max_advance_height / scale;
2080 	}
2081     }
2082 
2083     status = _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics);
2084     if (unlikely (status))
2085 	goto CLEANUP_SCALED_FONT;
2086 
2087     _cairo_ft_unscaled_font_unlock_face (unscaled);
2088 
2089     *font_out = &scaled_font->base;
2090     return CAIRO_STATUS_SUCCESS;
2091 
2092   CLEANUP_SCALED_FONT:
2093     _cairo_unscaled_font_destroy (&unscaled->base);
2094     free (scaled_font);
2095   FAIL:
2096     _cairo_ft_unscaled_font_unlock_face (font_face->unscaled);
2097     *font_out = _cairo_scaled_font_create_in_error (status);
2098     return CAIRO_STATUS_SUCCESS; /* non-backend error */
2099 }
2100 
2101 cairo_bool_t
_cairo_scaled_font_is_ft(cairo_scaled_font_t * scaled_font)2102 _cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
2103 {
2104     return scaled_font->backend == &_cairo_ft_scaled_font_backend;
2105 }
2106 
2107 static void
_cairo_ft_scaled_font_fini(void * abstract_font)2108 _cairo_ft_scaled_font_fini (void *abstract_font)
2109 {
2110     cairo_ft_scaled_font_t *scaled_font = abstract_font;
2111 
2112     if (scaled_font == NULL)
2113         return;
2114 
2115     _cairo_unscaled_font_destroy (&scaled_font->unscaled->base);
2116 }
2117 
2118 static int
_move_to(FT_Vector * to,void * closure)2119 _move_to (FT_Vector *to, void *closure)
2120 {
2121     cairo_path_fixed_t *path = closure;
2122     cairo_fixed_t x, y;
2123 
2124     x = _cairo_fixed_from_26_6 (to->x);
2125     y = _cairo_fixed_from_26_6 (to->y);
2126 
2127     if (_cairo_path_fixed_close_path (path) != CAIRO_STATUS_SUCCESS)
2128 	return 1;
2129     if (_cairo_path_fixed_move_to (path, x, y) != CAIRO_STATUS_SUCCESS)
2130 	return 1;
2131 
2132     return 0;
2133 }
2134 
2135 static int
_line_to(FT_Vector * to,void * closure)2136 _line_to (FT_Vector *to, void *closure)
2137 {
2138     cairo_path_fixed_t *path = closure;
2139     cairo_fixed_t x, y;
2140 
2141     x = _cairo_fixed_from_26_6 (to->x);
2142     y = _cairo_fixed_from_26_6 (to->y);
2143 
2144     if (_cairo_path_fixed_line_to (path, x, y) != CAIRO_STATUS_SUCCESS)
2145 	return 1;
2146 
2147     return 0;
2148 }
2149 
2150 static int
_conic_to(FT_Vector * control,FT_Vector * to,void * closure)2151 _conic_to (FT_Vector *control, FT_Vector *to, void *closure)
2152 {
2153     cairo_path_fixed_t *path = closure;
2154 
2155     cairo_fixed_t x0, y0;
2156     cairo_fixed_t x1, y1;
2157     cairo_fixed_t x2, y2;
2158     cairo_fixed_t x3, y3;
2159     cairo_point_t conic;
2160 
2161     if (! _cairo_path_fixed_get_current_point (path, &x0, &y0))
2162 	return 1;
2163 
2164     conic.x = _cairo_fixed_from_26_6 (control->x);
2165     conic.y = _cairo_fixed_from_26_6 (control->y);
2166 
2167     x3 = _cairo_fixed_from_26_6 (to->x);
2168     y3 = _cairo_fixed_from_26_6 (to->y);
2169 
2170     x1 = x0 + 2.0/3.0 * (conic.x - x0);
2171     y1 = y0 + 2.0/3.0 * (conic.y - y0);
2172 
2173     x2 = x3 + 2.0/3.0 * (conic.x - x3);
2174     y2 = y3 + 2.0/3.0 * (conic.y - y3);
2175 
2176     if (_cairo_path_fixed_curve_to (path,
2177 				    x1, y1,
2178 				    x2, y2,
2179 				    x3, y3) != CAIRO_STATUS_SUCCESS)
2180 	return 1;
2181 
2182     return 0;
2183 }
2184 
2185 static int
_cubic_to(FT_Vector * control1,FT_Vector * control2,FT_Vector * to,void * closure)2186 _cubic_to (FT_Vector *control1, FT_Vector *control2,
2187 	   FT_Vector *to, void *closure)
2188 {
2189     cairo_path_fixed_t *path = closure;
2190     cairo_fixed_t x0, y0;
2191     cairo_fixed_t x1, y1;
2192     cairo_fixed_t x2, y2;
2193 
2194     x0 = _cairo_fixed_from_26_6 (control1->x);
2195     y0 = _cairo_fixed_from_26_6 (control1->y);
2196 
2197     x1 = _cairo_fixed_from_26_6 (control2->x);
2198     y1 = _cairo_fixed_from_26_6 (control2->y);
2199 
2200     x2 = _cairo_fixed_from_26_6 (to->x);
2201     y2 = _cairo_fixed_from_26_6 (to->y);
2202 
2203     if (_cairo_path_fixed_curve_to (path,
2204 				    x0, y0,
2205 				    x1, y1,
2206 				    x2, y2) != CAIRO_STATUS_SUCCESS)
2207 	return 1;
2208 
2209     return 0;
2210 }
2211 
2212 static cairo_status_t
_decompose_glyph_outline(FT_Face face,cairo_font_options_t * options,cairo_path_fixed_t ** pathp)2213 _decompose_glyph_outline (FT_Face		  face,
2214 			  cairo_font_options_t	 *options,
2215 			  cairo_path_fixed_t	**pathp)
2216 {
2217     static const FT_Outline_Funcs outline_funcs = {
2218 	(FT_Outline_MoveToFunc)_move_to,
2219 	(FT_Outline_LineToFunc)_line_to,
2220 	(FT_Outline_ConicToFunc)_conic_to,
2221 	(FT_Outline_CubicToFunc)_cubic_to,
2222 	0, /* shift */
2223 	0, /* delta */
2224     };
2225     static const FT_Matrix invert_y = {
2226 	DOUBLE_TO_16_16 (1.0), 0,
2227 	0, DOUBLE_TO_16_16 (-1.0),
2228     };
2229 
2230     FT_GlyphSlot glyph;
2231     cairo_path_fixed_t *path;
2232     cairo_status_t status;
2233 
2234     path = _cairo_path_fixed_create ();
2235     if (!path)
2236 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2237 
2238     glyph = face->glyph;
2239 
2240     /* Font glyphs have an inverted Y axis compared to cairo. */
2241     FT_Outline_Transform (&glyph->outline, &invert_y);
2242     if (FT_Outline_Decompose (&glyph->outline, &outline_funcs, path)) {
2243 	_cairo_path_fixed_destroy (path);
2244 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2245     }
2246 
2247     status = _cairo_path_fixed_close_path (path);
2248     if (unlikely (status)) {
2249 	_cairo_path_fixed_destroy (path);
2250 	return status;
2251     }
2252 
2253     *pathp = path;
2254 
2255     return CAIRO_STATUS_SUCCESS;
2256 }
2257 
2258 /*
2259  * Translate glyph to match its metrics.
2260  */
2261 static void
_cairo_ft_scaled_glyph_vertical_layout_bearing_fix(void * abstract_font,FT_GlyphSlot glyph)2262 _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (void        *abstract_font,
2263 						    FT_GlyphSlot glyph)
2264 {
2265     cairo_ft_scaled_font_t *scaled_font = abstract_font;
2266     FT_Vector vector;
2267 
2268     vector.x = glyph->metrics.vertBearingX - glyph->metrics.horiBearingX;
2269     vector.y = -glyph->metrics.vertBearingY - glyph->metrics.horiBearingY;
2270 
2271     if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
2272 	FT_Vector_Transform (&vector, &scaled_font->unscaled->Current_Shape);
2273 	FT_Outline_Translate(&glyph->outline, vector.x, vector.y);
2274     } else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
2275 	glyph->bitmap_left += vector.x / 64;
2276 	glyph->bitmap_top  += vector.y / 64;
2277     }
2278 }
2279 
2280 static cairo_int_status_t
_cairo_ft_scaled_glyph_init(void * abstract_font,cairo_scaled_glyph_t * scaled_glyph,cairo_scaled_glyph_info_t info)2281 _cairo_ft_scaled_glyph_init (void			*abstract_font,
2282 			     cairo_scaled_glyph_t	*scaled_glyph,
2283 			     cairo_scaled_glyph_info_t	 info)
2284 {
2285     cairo_text_extents_t    fs_metrics;
2286     cairo_ft_scaled_font_t *scaled_font = abstract_font;
2287     cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
2288     FT_GlyphSlot glyph;
2289     FT_Face face = NULL;
2290     FT_Error error;
2291     int load_flags = scaled_font->ft_options.load_flags;
2292     FT_Glyph_Metrics *metrics;
2293     double x_factor, y_factor;
2294     cairo_bool_t vertical_layout = FALSE;
2295     cairo_status_t status;
2296 
2297     face = _cairo_ft_unscaled_font_lock_face (unscaled);
2298     if (!face)
2299 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2300 
2301     status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
2302 				                &scaled_font->base.scale);
2303     if (unlikely (status))
2304 	goto FAIL;
2305 
2306     /* Ignore global advance unconditionally */
2307     load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
2308 
2309     if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
2310 	(info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0)
2311 	load_flags |= FT_LOAD_NO_BITMAP;
2312 
2313     /*
2314      * Don't pass FT_LOAD_VERTICAL_LAYOUT to FT_Load_Glyph here as
2315      * suggested by freetype people.
2316      */
2317     if (load_flags & FT_LOAD_VERTICAL_LAYOUT) {
2318 	load_flags &= ~FT_LOAD_VERTICAL_LAYOUT;
2319 	vertical_layout = TRUE;
2320     }
2321 
2322 #ifdef FT_LOAD_COLOR
2323     /* Color-glyph support:
2324      *
2325      * This flags needs plumbing through fontconfig (does it?), and
2326      * maybe we should cache color and grayscale bitmaps separately
2327      * such that users of the font (ie. the surface) can choose which
2328      * version to use based on target content type.
2329      */
2330 
2331     load_flags |= FT_LOAD_COLOR;
2332 #endif
2333 
2334     error = FT_Load_Glyph (scaled_font->unscaled->face,
2335 			   _cairo_scaled_glyph_index(scaled_glyph),
2336 			   load_flags);
2337     /* XXX ignoring all other errors for now.  They are not fatal, typically
2338      * just a glyph-not-found. */
2339     if (error == FT_Err_Out_Of_Memory) {
2340 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2341 	goto FAIL;
2342     }
2343 
2344     glyph = face->glyph;
2345 
2346 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
2347     /*
2348      * embolden glyphs if requested
2349      */
2350     if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN)
2351 	FT_GlyphSlot_Embolden (glyph);
2352 #endif
2353 
2354     if (vertical_layout)
2355 	_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph);
2356 
2357     if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
2358 
2359 	cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF;
2360 	/*
2361 	 * Compute font-space metrics
2362 	 */
2363 	metrics = &glyph->metrics;
2364 
2365 	if (unscaled->x_scale == 0)
2366 	    x_factor = 0;
2367 	else
2368 	    x_factor = 1 / unscaled->x_scale;
2369 
2370 	if (unscaled->y_scale == 0)
2371 	    y_factor = 0;
2372 	else
2373 	    y_factor = 1 / unscaled->y_scale;
2374 
2375 	/*
2376 	 * Note: Y coordinates of the horizontal bearing need to be negated.
2377 	 *
2378 	 * Scale metrics back to glyph space from the scaled glyph space returned
2379 	 * by FreeType
2380 	 *
2381 	 * If we want hinted metrics but aren't asking for hinted glyphs from
2382 	 * FreeType, then we need to do the metric hinting ourselves.
2383 	 */
2384 
2385 	if (hint_metrics && (load_flags & FT_LOAD_NO_HINTING))
2386 	{
2387 	    FT_Pos x1, x2;
2388 	    FT_Pos y1, y2;
2389 	    FT_Pos advance;
2390 
2391 	    if (!vertical_layout) {
2392 		x1 = (metrics->horiBearingX) & -64;
2393 		x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
2394 		y1 = (-metrics->horiBearingY) & -64;
2395 		y2 = (-metrics->horiBearingY + metrics->height + 63) & -64;
2396 
2397 		advance = ((metrics->horiAdvance + 32) & -64);
2398 
2399 		fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor;
2400 		fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor;
2401 
2402 		fs_metrics.width  = DOUBLE_FROM_26_6 (x2 - x1) * x_factor;
2403 		fs_metrics.height  = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
2404 
2405 		fs_metrics.x_advance = DOUBLE_FROM_26_6 (advance) * x_factor;
2406 		fs_metrics.y_advance = 0;
2407 	    } else {
2408 		x1 = (metrics->vertBearingX) & -64;
2409 		x2 = (metrics->vertBearingX + metrics->width + 63) & -64;
2410 		y1 = (metrics->vertBearingY) & -64;
2411 		y2 = (metrics->vertBearingY + metrics->height + 63) & -64;
2412 
2413 		advance = ((metrics->vertAdvance + 32) & -64);
2414 
2415 		fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor;
2416 		fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor;
2417 
2418 		fs_metrics.width  = DOUBLE_FROM_26_6 (x2 - x1) * x_factor;
2419 		fs_metrics.height  = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
2420 
2421 		fs_metrics.x_advance = 0;
2422 		fs_metrics.y_advance = DOUBLE_FROM_26_6 (advance) * y_factor;
2423 	    }
2424 	 } else {
2425 	    fs_metrics.width  = DOUBLE_FROM_26_6 (metrics->width) * x_factor;
2426 	    fs_metrics.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor;
2427 
2428 	    if (!vertical_layout) {
2429 		fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor;
2430 		fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor;
2431 
2432 		if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
2433 		    fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor;
2434 		else
2435 		    fs_metrics.x_advance = DOUBLE_FROM_16_16 (glyph->linearHoriAdvance) * x_factor;
2436 		fs_metrics.y_advance = 0 * y_factor;
2437 	    } else {
2438 		fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingX) * x_factor;
2439 		fs_metrics.y_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingY) * y_factor;
2440 
2441 		fs_metrics.x_advance = 0 * x_factor;
2442 		if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
2443 		    fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor;
2444 		else
2445 		    fs_metrics.y_advance = DOUBLE_FROM_16_16 (glyph->linearVertAdvance) * y_factor;
2446 	    }
2447 	 }
2448 
2449 	_cairo_scaled_glyph_set_metrics (scaled_glyph,
2450 					 &scaled_font->base,
2451 					 &fs_metrics);
2452     }
2453 
2454     if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
2455 	cairo_image_surface_t	*surface;
2456 
2457 	if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
2458 	    status = _render_glyph_outline (face, &scaled_font->ft_options.base,
2459 					    &surface);
2460 	} else {
2461 	    status = _render_glyph_bitmap (face, &scaled_font->ft_options.base,
2462 					   &surface);
2463 	    if (likely (status == CAIRO_STATUS_SUCCESS) &&
2464 		unscaled->have_shape)
2465 	    {
2466 		status = _transform_glyph_bitmap (&unscaled->current_shape,
2467 						  &surface);
2468 		if (unlikely (status))
2469 		    cairo_surface_destroy (&surface->base);
2470 	    }
2471 	}
2472 	if (unlikely (status))
2473 	    goto FAIL;
2474 
2475 	_cairo_scaled_glyph_set_surface (scaled_glyph,
2476 					 &scaled_font->base,
2477 					 surface);
2478     }
2479 
2480     if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
2481 	cairo_path_fixed_t *path = NULL; /* hide compiler warning */
2482 
2483 	/*
2484 	 * A kludge -- the above code will trash the outline,
2485 	 * so reload it. This will probably never occur though
2486 	 */
2487 	if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
2488 	    error = FT_Load_Glyph (face,
2489 				   _cairo_scaled_glyph_index(scaled_glyph),
2490 				   load_flags | FT_LOAD_NO_BITMAP);
2491 	    /* XXX ignoring all other errors for now.  They are not fatal, typically
2492 	     * just a glyph-not-found. */
2493 	    if (error == FT_Err_Out_Of_Memory) {
2494 		status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2495 		goto FAIL;
2496 	    }
2497 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
2498 	    /*
2499 	     * embolden glyphs if requested
2500 	     */
2501 	    if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN)
2502 		FT_GlyphSlot_Embolden (glyph);
2503 #endif
2504 	    if (vertical_layout)
2505 		_cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph);
2506 
2507 	}
2508 	if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
2509 	    status = _decompose_glyph_outline (face, &scaled_font->ft_options.base,
2510 					       &path);
2511 	else
2512 	    status = CAIRO_INT_STATUS_UNSUPPORTED;
2513 
2514 	if (unlikely (status))
2515 	    goto FAIL;
2516 
2517 	_cairo_scaled_glyph_set_path (scaled_glyph,
2518 				      &scaled_font->base,
2519 				      path);
2520     }
2521  FAIL:
2522     _cairo_ft_unscaled_font_unlock_face (unscaled);
2523 
2524     return status;
2525 }
2526 
2527 static unsigned long
_cairo_ft_ucs4_to_index(void * abstract_font,uint32_t ucs4)2528 _cairo_ft_ucs4_to_index (void	    *abstract_font,
2529 			 uint32_t    ucs4)
2530 {
2531     cairo_ft_scaled_font_t *scaled_font = abstract_font;
2532     cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
2533     FT_Face face;
2534     FT_UInt index;
2535 
2536     face = _cairo_ft_unscaled_font_lock_face (unscaled);
2537     if (!face)
2538 	return 0;
2539 
2540 #if CAIRO_HAS_FC_FONT
2541     index = FcFreeTypeCharIndex (face, ucs4);
2542 #else
2543     index = FT_Get_Char_Index (face, ucs4);
2544 #endif
2545 
2546     _cairo_ft_unscaled_font_unlock_face (unscaled);
2547     return index;
2548 }
2549 
2550 static cairo_int_status_t
_cairo_ft_load_truetype_table(void * abstract_font,unsigned long tag,long offset,unsigned char * buffer,unsigned long * length)2551 _cairo_ft_load_truetype_table (void	       *abstract_font,
2552                               unsigned long     tag,
2553                               long              offset,
2554                               unsigned char    *buffer,
2555                               unsigned long    *length)
2556 {
2557     cairo_ft_scaled_font_t *scaled_font = abstract_font;
2558     cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
2559     FT_Face face;
2560     cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
2561 
2562     if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base))
2563         return CAIRO_INT_STATUS_UNSUPPORTED;
2564 
2565 #if HAVE_FT_LOAD_SFNT_TABLE
2566     face = _cairo_ft_unscaled_font_lock_face (unscaled);
2567     if (!face)
2568 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2569 
2570     if (FT_IS_SFNT (face) &&
2571 	FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0)
2572         status = CAIRO_STATUS_SUCCESS;
2573 
2574     _cairo_ft_unscaled_font_unlock_face (unscaled);
2575 #endif
2576 
2577     return status;
2578 }
2579 
2580 static cairo_int_status_t
_cairo_ft_index_to_ucs4(void * abstract_font,unsigned long index,uint32_t * ucs4)2581 _cairo_ft_index_to_ucs4(void	        *abstract_font,
2582 			unsigned long    index,
2583 			uint32_t	*ucs4)
2584 {
2585     cairo_ft_scaled_font_t *scaled_font = abstract_font;
2586     cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
2587     FT_Face face;
2588     FT_ULong  charcode;
2589     FT_UInt   gindex;
2590 
2591     face = _cairo_ft_unscaled_font_lock_face (unscaled);
2592     if (!face)
2593 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2594 
2595     *ucs4 = (uint32_t) -1;
2596     charcode = FT_Get_First_Char(face, &gindex);
2597     while (gindex != 0) {
2598 	if (gindex == index) {
2599 	    *ucs4 = charcode;
2600 	    break;
2601 	}
2602 	charcode = FT_Get_Next_Char (face, charcode, &gindex);
2603     }
2604 
2605     _cairo_ft_unscaled_font_unlock_face (unscaled);
2606 
2607     return CAIRO_STATUS_SUCCESS;
2608 }
2609 
2610 static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
2611     CAIRO_FONT_TYPE_FT,
2612     _cairo_ft_scaled_font_fini,
2613     _cairo_ft_scaled_glyph_init,
2614     NULL,			/* text_to_glyphs */
2615     _cairo_ft_ucs4_to_index,
2616     NULL,			/* show_glyphs */
2617     _cairo_ft_load_truetype_table,
2618     _cairo_ft_index_to_ucs4
2619 };
2620 
2621 /* #cairo_ft_font_face_t */
2622 
2623 #if CAIRO_HAS_FC_FONT
2624 static cairo_status_t
2625 _cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
2626 					cairo_font_face_t **out);
2627 
2628 static cairo_status_t
_cairo_ft_font_face_create_for_toy(cairo_toy_font_face_t * toy_face,cairo_font_face_t ** font_face)2629 _cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
2630 				    cairo_font_face_t      **font_face)
2631 {
2632     FcPattern *pattern;
2633     int fcslant;
2634     int fcweight;
2635     cairo_status_t status = CAIRO_STATUS_SUCCESS;
2636 
2637     pattern = FcPatternCreate ();
2638     if (!pattern)
2639 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2640 
2641     if (!FcPatternAddString (pattern,
2642 		             FC_FAMILY, (unsigned char *) toy_face->family))
2643     {
2644 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2645 	goto FREE_PATTERN;
2646     }
2647 
2648     switch (toy_face->slant)
2649     {
2650     case CAIRO_FONT_SLANT_ITALIC:
2651         fcslant = FC_SLANT_ITALIC;
2652         break;
2653     case CAIRO_FONT_SLANT_OBLIQUE:
2654 	fcslant = FC_SLANT_OBLIQUE;
2655         break;
2656     case CAIRO_FONT_SLANT_NORMAL:
2657     default:
2658         fcslant = FC_SLANT_ROMAN;
2659         break;
2660     }
2661 
2662     if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant)) {
2663 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2664 	goto FREE_PATTERN;
2665     }
2666 
2667     switch (toy_face->weight)
2668     {
2669     case CAIRO_FONT_WEIGHT_BOLD:
2670         fcweight = FC_WEIGHT_BOLD;
2671         break;
2672     case CAIRO_FONT_WEIGHT_NORMAL:
2673     default:
2674         fcweight = FC_WEIGHT_MEDIUM;
2675         break;
2676     }
2677 
2678     if (!FcPatternAddInteger (pattern, FC_WEIGHT, fcweight)) {
2679 	status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2680 	goto FREE_PATTERN;
2681     }
2682 
2683     status = _cairo_ft_font_face_create_for_pattern (pattern, font_face);
2684 
2685  FREE_PATTERN:
2686     FcPatternDestroy (pattern);
2687 
2688     return status;
2689 }
2690 #endif
2691 
2692 static void
_cairo_ft_font_face_destroy(void * abstract_face)2693 _cairo_ft_font_face_destroy (void *abstract_face)
2694 {
2695     cairo_ft_font_face_t *font_face = abstract_face;
2696 
2697     /* When destroying a face created by cairo_ft_font_face_create_for_ft_face,
2698      * we have a special "zombie" state for the face when the unscaled font
2699      * is still alive but there are no other references to a font face with
2700      * the same FT_Face.
2701      *
2702      * We go from:
2703      *
2704      *   font_face ------> unscaled
2705      *        <-....weak....../
2706      *
2707      * To:
2708      *
2709      *    font_face <------- unscaled
2710      */
2711 
2712     if (font_face->unscaled)
2713     {
2714 	CAIRO_MUTEX_LOCK (font_face->unscaled->mutex);
2715 
2716 	if (font_face->unscaled->from_face &&
2717 	    font_face->next == NULL &&
2718 	    font_face->unscaled->faces == font_face &&
2719 	    CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1)
2720 	{
2721 	    cairo_font_face_reference (&font_face->base);
2722 
2723 	    CAIRO_MUTEX_UNLOCK (font_face->unscaled->mutex);
2724 	    _cairo_unscaled_font_destroy (&font_face->unscaled->base);
2725 	    font_face->unscaled = NULL;
2726 	    return;
2727 	}
2728 
2729 	cairo_ft_font_face_t *tmp_face = NULL;
2730 	cairo_ft_font_face_t *last_face = NULL;
2731 
2732 	/* Remove face from linked list */
2733 	for (tmp_face = font_face->unscaled->faces;
2734 	     tmp_face;
2735 	     tmp_face = tmp_face->next)
2736 	{
2737 	    if (tmp_face == font_face) {
2738 		if (last_face)
2739 		    last_face->next = tmp_face->next;
2740 		else
2741 		    font_face->unscaled->faces = tmp_face->next;
2742 	    }
2743 
2744 	    last_face = tmp_face;
2745 	}
2746 
2747 	CAIRO_MUTEX_UNLOCK (font_face->unscaled->mutex);
2748 	_cairo_unscaled_font_destroy (&font_face->unscaled->base);
2749 	font_face->unscaled = NULL;
2750     }
2751 
2752 #if CAIRO_HAS_FC_FONT
2753     if (font_face->pattern) {
2754 	FcPatternDestroy (font_face->pattern);
2755 	cairo_font_face_destroy (font_face->resolved_font_face);
2756     }
2757 #endif
2758 }
2759 
2760 static cairo_font_face_t *
_cairo_ft_font_face_get_implementation(void * abstract_face,const cairo_matrix_t * font_matrix,const cairo_matrix_t * ctm,const cairo_font_options_t * options)2761 _cairo_ft_font_face_get_implementation (void                     *abstract_face,
2762 					const cairo_matrix_t       *font_matrix,
2763 					const cairo_matrix_t       *ctm,
2764 					const cairo_font_options_t *options)
2765 {
2766     cairo_ft_font_face_t      *font_face = abstract_face;
2767 
2768     /* The handling of font options is different depending on how the
2769      * font face was created. When the user creates a font face with
2770      * cairo_ft_font_face_create_for_ft_face(), then the load flags
2771      * passed in augment the load flags for the options.  But for
2772      * cairo_ft_font_face_create_for_pattern(), the load flags are
2773      * derived from a pattern where the user has called
2774      * cairo_ft_font_options_substitute(), so *just* use those load
2775      * flags and ignore the options.
2776      */
2777 
2778 #if CAIRO_HAS_FC_FONT
2779     /* If we have an unresolved pattern, resolve it and create
2780      * unscaled font.  Otherwise, use the ones stored in font_face.
2781      */
2782     if (font_face->pattern) {
2783 	cairo_font_face_t *resolved;
2784 
2785 	/* Cache the resolved font whilst the FcConfig remains consistent. */
2786 	resolved = font_face->resolved_font_face;
2787 	if (resolved != NULL) {
2788 	    if (! FcInitBringUptoDate ()) {
2789 		_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
2790 		return (cairo_font_face_t *) &_cairo_font_face_nil;
2791 	    }
2792 
2793 	    if (font_face->resolved_config == FcConfigGetCurrent ())
2794 		return cairo_font_face_reference (resolved);
2795 
2796 	    cairo_font_face_destroy (resolved);
2797 	    font_face->resolved_font_face = NULL;
2798 	}
2799 
2800 	resolved = _cairo_ft_resolve_pattern (font_face->pattern,
2801 					      font_matrix,
2802 					      ctm,
2803 					      options);
2804 	if (unlikely (resolved->status))
2805 	    return resolved;
2806 
2807 	font_face->resolved_font_face = cairo_font_face_reference (resolved);
2808 	font_face->resolved_config = FcConfigGetCurrent ();
2809 
2810 	return resolved;
2811     }
2812 #endif
2813 
2814     return abstract_face;
2815 }
2816 
2817 const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
2818     CAIRO_FONT_TYPE_FT,
2819 #if CAIRO_HAS_FC_FONT
2820     _cairo_ft_font_face_create_for_toy,
2821 #else
2822     NULL,
2823 #endif
2824     _cairo_ft_font_face_destroy,
2825     _cairo_ft_font_face_scaled_font_create,
2826     _cairo_ft_font_face_get_implementation
2827 };
2828 
2829 #if CAIRO_HAS_FC_FONT
2830 static cairo_status_t
_cairo_ft_font_face_create_for_pattern(FcPattern * pattern,cairo_font_face_t ** out)2831 _cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
2832 					cairo_font_face_t **out)
2833 {
2834     cairo_ft_font_face_t *font_face;
2835 
2836     font_face = malloc (sizeof (cairo_ft_font_face_t));
2837     if (unlikely (font_face == NULL))
2838 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2839 
2840     font_face->unscaled = NULL;
2841     font_face->next = NULL;
2842 
2843     font_face->pattern = FcPatternDuplicate (pattern);
2844     if (unlikely (font_face->pattern == NULL)) {
2845 	free (font_face);
2846 	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2847     }
2848 
2849     font_face->resolved_font_face = NULL;
2850     font_face->resolved_config = NULL;
2851 
2852     _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
2853 
2854     *out = &font_face->base;
2855     return CAIRO_STATUS_SUCCESS;
2856 }
2857 #endif
2858 
2859 static cairo_font_face_t *
_cairo_ft_font_face_create(cairo_ft_unscaled_font_t * unscaled,cairo_ft_options_t * ft_options)2860 _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
2861 			    cairo_ft_options_t	     *ft_options)
2862 {
2863     cairo_ft_font_face_t *font_face, **prev_font_face;
2864 
2865     CAIRO_MUTEX_LOCK (unscaled->mutex);
2866 
2867     /* Looked for an existing matching font face */
2868     for (font_face = unscaled->faces, prev_font_face = &unscaled->faces;
2869 	 font_face;
2870 	 prev_font_face = &font_face->next, font_face = font_face->next)
2871     {
2872 	if (font_face->ft_options.load_flags == ft_options->load_flags &&
2873 	    font_face->ft_options.extra_flags == ft_options->extra_flags &&
2874 	    cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
2875 	{
2876 	    if (font_face->base.status) {
2877 		/* The font_face has been left in an error state, abandon it. */
2878 		*prev_font_face = font_face->next;
2879 		break;
2880 	    }
2881 
2882 	    if (font_face->unscaled == NULL) {
2883 		/* Resurrect this "zombie" font_face (from
2884 		 * _cairo_ft_font_face_destroy), switching its unscaled_font
2885 		 * from owner to ownee. */
2886 		font_face->unscaled = unscaled;
2887 		_cairo_unscaled_font_reference (&unscaled->base);
2888 	    } else {
2889 		cairo_font_face_reference (&font_face->base);
2890 	    }
2891 
2892 	    CAIRO_MUTEX_UNLOCK (unscaled->mutex);
2893 	    return &font_face->base;
2894 	}
2895     }
2896 
2897     /* No match found, create a new one */
2898     font_face = malloc (sizeof (cairo_ft_font_face_t));
2899     if (unlikely (!font_face)) {
2900 	CAIRO_MUTEX_UNLOCK (unscaled->mutex);
2901 	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
2902 	return (cairo_font_face_t *)&_cairo_font_face_nil;
2903     }
2904 
2905     font_face->unscaled = unscaled;
2906     _cairo_unscaled_font_reference (&unscaled->base);
2907 
2908     font_face->ft_options = *ft_options;
2909 
2910     if (unscaled->faces && unscaled->faces->unscaled == NULL) {
2911 	/* This "zombie" font_face (from _cairo_ft_font_face_destroy)
2912 	 * is no longer needed. */
2913 	assert (unscaled->from_face && unscaled->faces->next == NULL);
2914 	cairo_font_face_destroy (&unscaled->faces->base);
2915 	unscaled->faces = NULL;
2916     }
2917 
2918     font_face->next = unscaled->faces;
2919     unscaled->faces = font_face;
2920 
2921 #if CAIRO_HAS_FC_FONT
2922     font_face->pattern = NULL;
2923 #endif
2924 
2925     _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
2926 
2927     CAIRO_MUTEX_UNLOCK (unscaled->mutex);
2928     return &font_face->base;
2929 }
2930 
2931 /* implement the platform-specific interface */
2932 
2933 #if CAIRO_HAS_FC_FONT
2934 static cairo_status_t
_cairo_ft_font_options_substitute(const cairo_font_options_t * options,FcPattern * pattern)2935 _cairo_ft_font_options_substitute (const cairo_font_options_t *options,
2936 				   FcPattern                  *pattern)
2937 {
2938     FcValue v;
2939 
2940     if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
2941     {
2942 	if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch)
2943 	{
2944 	    if (! FcPatternAddBool (pattern,
2945 			            FC_ANTIALIAS,
2946 				    options->antialias != CAIRO_ANTIALIAS_NONE))
2947 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2948 
2949 	    if (options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
2950 		FcPatternDel (pattern, FC_RGBA);
2951 		if (! FcPatternAddInteger (pattern, FC_RGBA, FC_RGBA_NONE))
2952 		    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2953 	    }
2954 	}
2955     }
2956 
2957     if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
2958     {
2959 	if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch)
2960 	{
2961 	    int rgba;
2962 
2963 	    if (options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
2964 		switch (options->subpixel_order) {
2965 		case CAIRO_SUBPIXEL_ORDER_DEFAULT:
2966 		case CAIRO_SUBPIXEL_ORDER_RGB:
2967 		default:
2968 		    rgba = FC_RGBA_RGB;
2969 		    break;
2970 		case CAIRO_SUBPIXEL_ORDER_BGR:
2971 		    rgba = FC_RGBA_BGR;
2972 		    break;
2973 		case CAIRO_SUBPIXEL_ORDER_VRGB:
2974 		    rgba = FC_RGBA_VRGB;
2975 		    break;
2976 		case CAIRO_SUBPIXEL_ORDER_VBGR:
2977 		    rgba = FC_RGBA_VBGR;
2978 		    break;
2979 		}
2980 	    } else {
2981 		rgba = FC_RGBA_NONE;
2982 	    }
2983 
2984 	    if (! FcPatternAddInteger (pattern, FC_RGBA, rgba))
2985 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2986 	}
2987     }
2988 
2989     if (options->lcd_filter != CAIRO_LCD_FILTER_DEFAULT)
2990     {
2991 	if (FcPatternGet (pattern, FC_LCD_FILTER, 0, &v) == FcResultNoMatch)
2992 	{
2993 	    int lcd_filter;
2994 
2995 	    switch (options->lcd_filter) {
2996 	    case CAIRO_LCD_FILTER_NONE:
2997 		lcd_filter = FT_LCD_FILTER_NONE;
2998 		break;
2999 	    case CAIRO_LCD_FILTER_DEFAULT:
3000 	    case CAIRO_LCD_FILTER_INTRA_PIXEL:
3001 		lcd_filter = FT_LCD_FILTER_LEGACY;
3002 		break;
3003 	    case CAIRO_LCD_FILTER_FIR3:
3004 		lcd_filter = FT_LCD_FILTER_LIGHT;
3005 		break;
3006 	    default:
3007 	    case CAIRO_LCD_FILTER_FIR5:
3008 		lcd_filter = FT_LCD_FILTER_DEFAULT;
3009 		break;
3010 	    }
3011 
3012 	    if (! FcPatternAddInteger (pattern, FC_LCD_FILTER, lcd_filter))
3013 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3014 	}
3015     }
3016 
3017     if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
3018     {
3019 	if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
3020 	{
3021 	    if (! FcPatternAddBool (pattern,
3022 			            FC_HINTING,
3023 				    options->hint_style != CAIRO_HINT_STYLE_NONE))
3024 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3025 	}
3026 
3027 #ifdef FC_HINT_STYLE
3028 	if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch)
3029 	{
3030 	    int hint_style;
3031 
3032 	    switch (options->hint_style) {
3033 	    case CAIRO_HINT_STYLE_NONE:
3034 		hint_style = FC_HINT_NONE;
3035 		break;
3036 	    case CAIRO_HINT_STYLE_SLIGHT:
3037 		hint_style = FC_HINT_SLIGHT;
3038 		break;
3039 	    case CAIRO_HINT_STYLE_MEDIUM:
3040 		hint_style = FC_HINT_MEDIUM;
3041 		break;
3042 	    case CAIRO_HINT_STYLE_FULL:
3043 	    case CAIRO_HINT_STYLE_DEFAULT:
3044 	    default:
3045 		hint_style = FC_HINT_FULL;
3046 		break;
3047 	    }
3048 
3049 	    if (! FcPatternAddInteger (pattern, FC_HINT_STYLE, hint_style))
3050 		return _cairo_error (CAIRO_STATUS_NO_MEMORY);
3051 	}
3052 #endif
3053     }
3054 
3055     return CAIRO_STATUS_SUCCESS;
3056 }
3057 
3058 /**
3059  * cairo_ft_font_options_substitute:
3060  * @options: a #cairo_font_options_t object
3061  * @pattern: an existing #FcPattern
3062  *
3063  * Add options to a #FcPattern based on a #cairo_font_options_t font
3064  * options object. Options that are already in the pattern, are not overridden,
3065  * so you should call this function after calling FcConfigSubstitute() (the
3066  * user's settings should override options based on the surface type), but
3067  * before calling FcDefaultSubstitute().
3068  **/
3069 void
cairo_ft_font_options_substitute(const cairo_font_options_t * options,FcPattern * pattern)3070 cairo_ft_font_options_substitute (const cairo_font_options_t *options,
3071 				  FcPattern                  *pattern)
3072 {
3073     if (cairo_font_options_status ((cairo_font_options_t *) options))
3074 	return;
3075 
3076     _cairo_ft_font_options_substitute (options, pattern);
3077 }
3078 
3079 static cairo_font_face_t *
_cairo_ft_resolve_pattern(FcPattern * pattern,const cairo_matrix_t * font_matrix,const cairo_matrix_t * ctm,const cairo_font_options_t * font_options)3080 _cairo_ft_resolve_pattern (FcPattern		      *pattern,
3081 			   const cairo_matrix_t       *font_matrix,
3082 			   const cairo_matrix_t       *ctm,
3083 			   const cairo_font_options_t *font_options)
3084 {
3085     cairo_status_t status;
3086 
3087     cairo_matrix_t scale;
3088     FcPattern *resolved;
3089     cairo_ft_font_transform_t sf;
3090     FcResult result;
3091     cairo_ft_unscaled_font_t *unscaled;
3092     cairo_ft_options_t ft_options;
3093     cairo_font_face_t *font_face;
3094 
3095     scale = *ctm;
3096     scale.x0 = scale.y0 = 0;
3097     cairo_matrix_multiply (&scale,
3098                            font_matrix,
3099                            &scale);
3100 
3101     status = _compute_transform (&sf, &scale, NULL);
3102     if (unlikely (status))
3103 	return (cairo_font_face_t *)&_cairo_font_face_nil;
3104 
3105     pattern = FcPatternDuplicate (pattern);
3106     if (pattern == NULL)
3107 	return (cairo_font_face_t *)&_cairo_font_face_nil;
3108 
3109     if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE, sf.y_scale)) {
3110 	font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
3111 	goto FREE_PATTERN;
3112     }
3113 
3114     if (! FcConfigSubstitute (NULL, pattern, FcMatchPattern)) {
3115 	font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
3116 	goto FREE_PATTERN;
3117     }
3118 
3119     status = _cairo_ft_font_options_substitute (font_options, pattern);
3120     if (status) {
3121 	font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
3122 	goto FREE_PATTERN;
3123     }
3124 
3125     FcDefaultSubstitute (pattern);
3126 
3127     resolved = FcFontMatch (NULL, pattern, &result);
3128     if (!resolved) {
3129 	/* We failed to find any font. Substitute twin so that the user can
3130 	 * see something (and hopefully recognise that the font is missing)
3131 	 * and not just receive a NO_MEMORY error during rendering.
3132 	 */
3133 	font_face = _cairo_font_face_twin_create_fallback ();
3134 	goto FREE_PATTERN;
3135     }
3136 
3137     status = _cairo_ft_unscaled_font_create_for_pattern (resolved, NULL, 0, &unscaled);
3138     if (unlikely (status || unscaled == NULL)) {
3139 	font_face = (cairo_font_face_t *)&_cairo_font_face_nil;
3140 	goto FREE_RESOLVED;
3141     }
3142 
3143     _get_pattern_ft_options (resolved, &ft_options);
3144     font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
3145     _cairo_unscaled_font_destroy (&unscaled->base);
3146 
3147 FREE_RESOLVED:
3148     FcPatternDestroy (resolved);
3149 
3150 FREE_PATTERN:
3151     FcPatternDestroy (pattern);
3152 
3153     return font_face;
3154 }
3155 
3156 /**
3157  * cairo_ft_font_face_create_for_pattern:
3158  * @pattern: A fontconfig pattern.  Cairo makes a copy of the pattern
3159  * if it needs to.  You are free to modify or free @pattern after this call.
3160  *
3161  * Creates a new font face for the FreeType font backend based on a
3162  * fontconfig pattern. This font can then be used with
3163  * cairo_set_font_face() or cairo_scaled_font_create(). The
3164  * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
3165  * also for the FreeType backend and can be used with functions such
3166  * as cairo_ft_scaled_font_lock_face().
3167  *
3168  * Font rendering options are represented both here and when you
3169  * call cairo_scaled_font_create(). Font options that have a representation
3170  * in a #FcPattern must be passed in here; to modify #FcPattern
3171  * appropriately to reflect the options in a #cairo_font_options_t, call
3172  * cairo_ft_font_options_substitute().
3173  *
3174  * The pattern's FC_FT_FACE element is inspected first and if that is set,
3175  * that will be the FreeType font face associated with the returned cairo
3176  * font face.  Otherwise the FC_FILE element is checked.  If it's set,
3177  * that and the value of the FC_INDEX element (defaults to zero) of @pattern
3178  * are used to load a font face from file.
3179  *
3180  * If both steps from the previous paragraph fails, @pattern will be passed
3181  * to FcConfigSubstitute, FcDefaultSubstitute, and finally FcFontMatch,
3182  * and the resulting font pattern is used.
3183  *
3184  * If the FC_FT_FACE element of @pattern is set, the user is responsible
3185  * for making sure that the referenced FT_Face remains valid for the life
3186  * time of the returned #cairo_font_face_t.  See
3187  * cairo_ft_font_face_create_for_ft_face() for an exmaple of how to couple
3188  * the life time of the FT_Face to that of the cairo font-face.
3189  *
3190  * Return value: a newly created #cairo_font_face_t. Free with
3191  *  cairo_font_face_destroy() when you are done using it.
3192  **/
3193 cairo_font_face_t *
cairo_ft_font_face_create_for_pattern(FcPattern * pattern,const FT_Fixed * var_coords,int num_var_coords)3194 cairo_ft_font_face_create_for_pattern (FcPattern *pattern,
3195                                        const FT_Fixed *var_coords, int num_var_coords)
3196 {
3197     cairo_ft_unscaled_font_t *unscaled;
3198     cairo_font_face_t *font_face;
3199     cairo_ft_options_t ft_options;
3200     cairo_status_t status;
3201 
3202     status = _cairo_ft_unscaled_font_create_for_pattern (pattern,
3203                                                          var_coords, num_var_coords,
3204                                                          &unscaled);
3205     if (unlikely (status))
3206 	return (cairo_font_face_t *) &_cairo_font_face_nil;
3207     if (unlikely (unscaled == NULL)) {
3208 	/* Store the pattern.  We will resolve it and create unscaled
3209 	 * font when creating scaled fonts */
3210 	status = _cairo_ft_font_face_create_for_pattern (pattern,
3211 							 &font_face);
3212 	if (unlikely (status))
3213 	    return (cairo_font_face_t *) &_cairo_font_face_nil;
3214 
3215 	return font_face;
3216     }
3217 
3218     _get_pattern_ft_options (pattern, &ft_options);
3219     font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
3220     _cairo_unscaled_font_destroy (&unscaled->base);
3221 
3222     return font_face;
3223 }
3224 #endif
3225 
3226 /**
3227  * cairo_ft_font_face_create_for_ft_face:
3228  * @face: A FreeType face object, already opened. This must
3229  *   be kept around until the face's ref_count drops to
3230  *   zero and it is freed. Since the face may be referenced
3231  *   internally to Cairo, the best way to determine when it
3232  *   is safe to free the face is to pass a
3233  *   #cairo_destroy_func_t to cairo_font_face_set_user_data()
3234  * @load_flags: flags to pass to FT_Load_Glyph when loading
3235  *   glyphs from the font. These flags are OR'ed together with
3236  *   the flags derived from the #cairo_font_options_t passed
3237  *   to cairo_scaled_font_create(), so only a few values such
3238  *   as %FT_LOAD_VERTICAL_LAYOUT, and %FT_LOAD_FORCE_AUTOHINT
3239  *   are useful. You should not pass any of the flags affecting
3240  *   the load target, such as %FT_LOAD_TARGET_LIGHT.
3241  *
3242  * Creates a new font face for the FreeType font backend from a
3243  * pre-opened FreeType face. This font can then be used with
3244  * cairo_set_font_face() or cairo_scaled_font_create(). The
3245  * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
3246  * also for the FreeType backend and can be used with functions such
3247  * as cairo_ft_scaled_font_lock_face(). Note that Cairo may keep a reference
3248  * to the FT_Face alive in a font-cache and the exact lifetime of the reference
3249  * depends highly upon the exact usage pattern and is subject to external
3250  * factors. You must not call FT_Done_Face() before the last reference to the
3251  * #cairo_font_face_t has been dropped.
3252  *
3253  * As an example, below is how one might correctly couple the lifetime of
3254  * the FreeType face object to the #cairo_font_face_t.
3255  *
3256  * <informalexample><programlisting>
3257  * static const cairo_user_data_key_t key;
3258  *
3259  * font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
3260  * status = cairo_font_face_set_user_data (font_face, &key,
3261  *                                ft_face, (cairo_destroy_func_t) FT_Done_Face);
3262  * if (status) {
3263  *    cairo_font_face_destroy (font_face);
3264  *    FT_Done_Face (ft_face);
3265  *    return ERROR;
3266  * }
3267  * </programlisting></informalexample>
3268  *
3269  * Return value: a newly created #cairo_font_face_t. Free with
3270  *  cairo_font_face_destroy() when you are done using it.
3271  **/
3272 cairo_font_face_t *
cairo_ft_font_face_create_for_ft_face(FT_Face face,int load_flags,const FT_Fixed * var_coords,int num_var_coords)3273 cairo_ft_font_face_create_for_ft_face (FT_Face         face,
3274 				       int             load_flags,
3275                                        const FT_Fixed *var_coords,
3276                                        int             num_var_coords)
3277 {
3278     cairo_ft_unscaled_font_t *unscaled;
3279     cairo_font_face_t *font_face;
3280     cairo_ft_options_t ft_options;
3281     cairo_status_t status;
3282 
3283     status = _cairo_ft_unscaled_font_create_from_face (face,
3284                                                        var_coords, num_var_coords,
3285                                                        &unscaled);
3286     if (unlikely (status))
3287 	return (cairo_font_face_t *)&_cairo_font_face_nil;
3288 
3289     ft_options.load_flags = load_flags;
3290     ft_options.extra_flags = 0;
3291     _cairo_font_options_init_default (&ft_options.base);
3292 
3293     font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
3294     _cairo_unscaled_font_destroy (&unscaled->base);
3295 
3296     return font_face;
3297 }
3298 
3299 /**
3300  * cairo_ft_scaled_font_lock_face:
3301  * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
3302  *   object can be created by calling cairo_scaled_font_create() on a
3303  *   FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
3304  *   cairo_ft_font_face_create_for_ft_face()).
3305  *
3306  * cairo_ft_scaled_font_lock_face() gets the #FT_Face object from a FreeType
3307  * backend font and scales it appropriately for the font. You must
3308  * release the face with cairo_ft_scaled_font_unlock_face()
3309  * when you are done using it.  Since the #FT_Face object can be
3310  * shared between multiple #cairo_scaled_font_t objects, you must not
3311  * lock any other font objects until you unlock this one. A count is
3312  * kept of the number of times cairo_ft_scaled_font_lock_face() is
3313  * called. cairo_ft_scaled_font_unlock_face() must be called the same number
3314  * of times.
3315  *
3316  * You must be careful when using this function in a library or in a
3317  * threaded application, because freetype's design makes it unsafe to
3318  * call freetype functions simultaneously from multiple threads, (even
3319  * if using distinct FT_Face objects). Because of this, application
3320  * code that acquires an FT_Face object with this call must add its
3321  * own locking to protect any use of that object, (and which also must
3322  * protect any other calls into cairo as almost any cairo function
3323  * might result in a call into the freetype library).
3324  *
3325  * Return value: The #FT_Face object for @font, scaled appropriately,
3326  * or %NULL if @scaled_font is in an error state (see
3327  * cairo_scaled_font_status()) or there is insufficient memory.
3328  **/
3329 FT_Face
cairo_ft_scaled_font_lock_face(cairo_scaled_font_t * abstract_font)3330 cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
3331 {
3332     cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
3333     FT_Face face;
3334     cairo_status_t status;
3335 
3336     if (! _cairo_scaled_font_is_ft (abstract_font)) {
3337 	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
3338 	return NULL;
3339     }
3340 
3341     if (scaled_font->base.status)
3342 	return NULL;
3343 
3344     face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
3345     if (unlikely (face == NULL)) {
3346 	status = _cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
3347 	return NULL;
3348     }
3349 
3350     status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
3351 				                &scaled_font->base.scale);
3352     if (unlikely (status)) {
3353 	_cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
3354 	status = _cairo_scaled_font_set_error (&scaled_font->base, status);
3355 	return NULL;
3356     }
3357 
3358     /* Note: We deliberately release the unscaled font's mutex here,
3359      * so that we are not holding a lock across two separate calls to
3360      * cairo function, (which would give the application some
3361      * opportunity for creating deadlock. This is obviously unsafe,
3362      * but as documented, the user must add manual locking when using
3363      * this function. */
3364     // BEWARE: Mozilla's tree Cairo keeps the lock across calls for thread-safety.
3365     // CAIRO_MUTEX_UNLOCK (scaled_font->unscaled->mutex);
3366 
3367     return face;
3368 }
3369 
3370 /**
3371  * cairo_ft_scaled_font_unlock_face:
3372  * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
3373  *   object can be created by calling cairo_scaled_font_create() on a
3374  *   FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
3375  *   cairo_ft_font_face_create_for_ft_face()).
3376  *
3377  * Releases a face obtained with cairo_ft_scaled_font_lock_face().
3378  **/
3379 void
cairo_ft_scaled_font_unlock_face(cairo_scaled_font_t * abstract_font)3380 cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
3381 {
3382     cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
3383 
3384     if (! _cairo_scaled_font_is_ft (abstract_font)) {
3385 	_cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
3386 	return;
3387     }
3388 
3389     if (scaled_font->base.status)
3390 	return;
3391 
3392     /* Note: We released the unscaled font's mutex at the end of
3393      * cairo_ft_scaled_font_lock_face, so we have to acquire it again
3394      * as _cairo_ft_unscaled_font_unlock_face expects it to be held
3395      * when we call into it. */
3396     // BEWARE: Mozilla's tree Cairo keeps the lock across calls for thread-safety.
3397     //CAIRO_MUTEX_LOCK (scaled_font->unscaled->mutex);
3398 
3399     _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
3400 }
3401 
3402 /* We expose our unscaled font implementation internally for the the
3403  * PDF backend, which needs to keep track of the the different
3404  * fonts-on-disk used by a document, so it can embed them.
3405  */
3406 cairo_unscaled_font_t *
_cairo_ft_scaled_font_get_unscaled_font(cairo_scaled_font_t * abstract_font)3407 _cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t *abstract_font)
3408 {
3409     cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
3410 
3411     return &scaled_font->unscaled->base;
3412 }
3413 
3414 cairo_bool_t
_cairo_ft_scaled_font_is_vertical(cairo_scaled_font_t * scaled_font)3415 _cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font)
3416 {
3417     cairo_ft_scaled_font_t *ft_scaled_font;
3418 
3419     if (!_cairo_scaled_font_is_ft (scaled_font))
3420 	return FALSE;
3421 
3422     ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
3423     if (ft_scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)
3424 	return TRUE;
3425     return FALSE;
3426 }
3427 
3428 unsigned int
_cairo_ft_scaled_font_get_load_flags(cairo_scaled_font_t * scaled_font)3429 _cairo_ft_scaled_font_get_load_flags (cairo_scaled_font_t *scaled_font)
3430 {
3431     cairo_ft_scaled_font_t *ft_scaled_font;
3432 
3433     if (! _cairo_scaled_font_is_ft (scaled_font))
3434 	return 0;
3435 
3436     ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
3437     return ft_scaled_font->ft_options.load_flags;
3438 }
3439 
3440 void
_cairo_ft_font_reset_static_data(void)3441 _cairo_ft_font_reset_static_data (void)
3442 {
3443     _cairo_ft_unscaled_font_map_destroy ();
3444 }
3445