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