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