[cairo-ft] Add a demonstration of how to handle the lifetime of the FT_Face.
[cairo/haiku.git] / src / cairo-ft-font.c
blob95da10b51482cf3b291692468a88346c9bb44981
1 /* cairo - a vector graphics library with display and print output
3 * Copyright © 2000 Keith Packard
4 * Copyright © 2005 Red Hat, Inc
6 * This library is free software; you can redistribute it and/or
7 * modify it either under the terms of the GNU Lesser General Public
8 * License version 2.1 as published by the Free Software Foundation
9 * (the "LGPL") or, at your option, under the terms of the Mozilla
10 * Public License Version 1.1 (the "MPL"). If you do not alter this
11 * notice, a recipient may use your version of this file under either
12 * the MPL or the LGPL.
14 * You should have received a copy of the LGPL along with this library
15 * in the file COPYING-LGPL-2.1; if not, write to the Free Software
16 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 * You should have received a copy of the MPL along with this library
18 * in the file COPYING-MPL-1.1
20 * The contents of this file are subject to the Mozilla Public License
21 * Version 1.1 (the "License"); you may not use this file except in
22 * compliance with the License. You may obtain a copy of the License at
23 * http://www.mozilla.org/MPL/
25 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
26 * OF ANY KIND, either express or implied. See the LGPL or the MPL for
27 * the specific language governing rights and limitations.
29 * The Original Code is the cairo graphics library.
31 * The Initial Developer of the Original Code is Red Hat, Inc.
33 * Contributor(s):
34 * Graydon Hoare <graydon@redhat.com>
35 * Owen Taylor <otaylor@redhat.com>
36 * Keith Packard <keithp@keithp.com>
37 * Carl Worth <cworth@cworth.org>
40 #define _BSD_SOURCE /* for strdup() */
41 #include "cairoint.h"
43 #include "cairo-ft-private.h"
45 #include <float.h>
47 #include <fontconfig/fontconfig.h>
48 #include <fontconfig/fcfreetype.h>
50 #include <ft2build.h>
51 #include FT_FREETYPE_H
52 #include FT_OUTLINE_H
53 #include FT_IMAGE_H
54 #include FT_TRUETYPE_TABLES_H
55 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
56 #include FT_SYNTHESIS_H
57 #endif
59 #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
60 #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
61 #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
62 #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
64 /* This is the max number of FT_face objects we keep open at once
66 #define MAX_OPEN_FACES 10
69 * The simple 2x2 matrix is converted into separate scale and shape
70 * factors so that hinting works right
73 typedef struct _cairo_ft_font_transform {
74 double x_scale, y_scale;
75 double shape[2][2];
76 } cairo_ft_font_transform_t;
79 * We create an object that corresponds to a single font on the disk;
80 * (identified by a filename/id pair) these are shared between all
81 * fonts using that file. For cairo_ft_font_face_create_for_ft_face(), we
82 * just create a one-off version with a permanent face value.
85 typedef struct _cairo_ft_font_face cairo_ft_font_face_t;
87 struct _cairo_ft_unscaled_font {
88 cairo_unscaled_font_t base;
90 cairo_bool_t from_face; /* from cairo_ft_font_face_create_for_ft_face()? */
91 FT_Face face; /* provided or cached face */
93 /* only set if from_face is false */
94 char *filename;
95 int id;
97 /* We temporarily scale the unscaled font as needed */
98 cairo_bool_t have_scale;
99 cairo_matrix_t current_scale;
100 double x_scale; /* Extracted X scale factor */
101 double y_scale; /* Extracted Y scale factor */
102 cairo_bool_t have_shape; /* true if the current scale has a non-scale component*/
103 cairo_matrix_t current_shape;
104 FT_Matrix Current_Shape;
106 cairo_mutex_t mutex;
107 int lock_count;
109 cairo_ft_font_face_t *faces; /* Linked list of faces for this font */
112 static int
113 _cairo_ft_unscaled_font_keys_equal (const void *key_a,
114 const void *key_b);
116 static void
117 _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled);
119 static cairo_status_t
120 _cairo_ft_font_options_substitute (const cairo_font_options_t *options,
121 FcPattern *pattern);
123 typedef enum _cairo_ft_extra_flags {
124 CAIRO_FT_OPTIONS_HINT_METRICS = (1 << 0),
125 CAIRO_FT_OPTIONS_EMBOLDEN = (1 << 1)
126 } cairo_ft_extra_flags_t;
128 typedef struct _cairo_ft_options {
129 cairo_font_options_t base;
130 int load_flags; /* flags for FT_Load_Glyph */
131 cairo_ft_extra_flags_t extra_flags; /* other flags that affect results */
132 } cairo_ft_options_t;
134 struct _cairo_ft_font_face {
135 cairo_font_face_t base;
136 cairo_ft_unscaled_font_t *unscaled;
137 cairo_ft_options_t ft_options;
138 cairo_ft_font_face_t *next;
141 static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;
144 * We maintain a hash table to map file/id => #cairo_ft_unscaled_font_t.
145 * The hash table itself isn't limited in size. However, we limit the
146 * number of FT_Face objects we keep around; when we've exceeded that
147 * limit and need to create a new FT_Face, we dump the FT_Face from a
148 * random #cairo_ft_unscaled_font_t which has an unlocked FT_Face, (if
149 * there are any).
152 typedef struct _cairo_ft_unscaled_font_map {
153 cairo_hash_table_t *hash_table;
154 FT_Library ft_library;
155 int num_open_faces;
156 } cairo_ft_unscaled_font_map_t;
158 static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;
160 static void
161 _font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
162 cairo_ft_unscaled_font_t *unscaled)
164 if (unscaled->face) {
165 FT_Done_Face (unscaled->face);
166 unscaled->face = NULL;
167 unscaled->have_scale = FALSE;
169 font_map->num_open_faces--;
173 static void
174 _cairo_ft_unscaled_font_map_create (void)
176 cairo_ft_unscaled_font_map_t *font_map;
178 /* This function is only intended to be called from
179 * _cairo_ft_unscaled_font_map_lock. So we'll crash if we can
180 * detect some other call path. */
181 assert (cairo_ft_unscaled_font_map == NULL);
183 font_map = malloc (sizeof (cairo_ft_unscaled_font_map_t));
184 if (font_map == NULL) {
185 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
186 goto FAIL;
189 font_map->hash_table =
190 _cairo_hash_table_create (_cairo_ft_unscaled_font_keys_equal);
192 if (font_map->hash_table == NULL)
193 goto FAIL;
195 if (FT_Init_FreeType (&font_map->ft_library))
196 goto FAIL;
198 font_map->num_open_faces = 0;
200 cairo_ft_unscaled_font_map = font_map;
201 return;
203 FAIL:
204 if (font_map) {
205 if (font_map->hash_table)
206 _cairo_hash_table_destroy (font_map->hash_table);
207 free (font_map);
209 cairo_ft_unscaled_font_map = NULL;
212 static void
213 _cairo_ft_unscaled_font_map_destroy (void)
215 cairo_ft_unscaled_font_t *unscaled;
216 cairo_ft_unscaled_font_map_t *font_map;
218 CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
220 if (cairo_ft_unscaled_font_map) {
221 font_map = cairo_ft_unscaled_font_map;
223 /* This is rather inefficient, but destroying the hash table
224 * is something we only do during debugging, (during
225 * cairo_debug_reset_static_data), when efficiency is not
226 * relevant. */
227 while (1) {
228 unscaled = _cairo_hash_table_random_entry (font_map->hash_table,
229 NULL);
230 if (unscaled == NULL)
231 break;
232 _cairo_hash_table_remove (font_map->hash_table,
233 &unscaled->base.hash_entry);
235 _font_map_release_face_lock_held (font_map, unscaled);
236 _cairo_ft_unscaled_font_fini (unscaled);
237 free (unscaled);
240 assert (font_map->num_open_faces == 0);
242 FT_Done_FreeType (font_map->ft_library);
244 _cairo_hash_table_destroy (font_map->hash_table);
246 free (font_map);
248 cairo_ft_unscaled_font_map = NULL;
251 CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
254 static cairo_ft_unscaled_font_map_t *
255 _cairo_ft_unscaled_font_map_lock (void)
257 CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
259 if (cairo_ft_unscaled_font_map == NULL)
261 _cairo_ft_unscaled_font_map_create ();
263 if (cairo_ft_unscaled_font_map == NULL) {
264 CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
265 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
266 return NULL;
270 return cairo_ft_unscaled_font_map;
273 static void
274 _cairo_ft_unscaled_font_map_unlock (void)
276 CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
279 static void
280 _cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
281 char *filename,
282 int id)
284 unsigned long hash;
286 key->filename = filename;
287 key->id = id;
289 /* 1607 is just an arbitrary prime. */
290 hash = _cairo_hash_string (filename);
291 hash += ((unsigned long) id) * 1607;
293 key->base.hash_entry.hash = hash;
297 * _cairo_ft_unscaled_font_init:
299 * Initialize a #cairo_ft_unscaled_font_t.
301 * There are two basic flavors of #cairo_ft_unscaled_font_t, one
302 * created from an FT_Face and the other created from a filename/id
303 * pair. These two flavors are identified as from_face and !from_face.
305 * To initialize a from_face font, pass filename==%NULL, id=0 and the
306 * desired face.
308 * To initialize a !from_face font, pass the filename/id as desired
309 * and face==%NULL.
311 * Note that the code handles these two flavors in very distinct
312 * ways. For example there is a hash_table mapping
313 * filename/id->#cairo_unscaled_font_t in the !from_face case, but no
314 * parallel in the from_face case, (where the calling code would have
315 * to do its own mapping to ensure similar sharing).
317 static cairo_status_t
318 _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
319 const char *filename,
320 int id,
321 FT_Face face)
323 _cairo_unscaled_font_init (&unscaled->base,
324 &cairo_ft_unscaled_font_backend);
326 if (face) {
327 unscaled->from_face = TRUE;
328 unscaled->face = face;
329 unscaled->filename = NULL;
330 unscaled->id = 0;
331 } else {
332 char *filename_copy;
334 unscaled->from_face = FALSE;
335 unscaled->face = NULL;
337 filename_copy = strdup (filename);
338 if (filename_copy == NULL)
339 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
341 _cairo_ft_unscaled_font_init_key (unscaled, filename_copy, id);
344 unscaled->have_scale = FALSE;
345 CAIRO_MUTEX_INIT (unscaled->mutex);
346 unscaled->lock_count = 0;
348 unscaled->faces = NULL;
350 return CAIRO_STATUS_SUCCESS;
353 cairo_bool_t
354 _cairo_unscaled_font_is_ft (cairo_unscaled_font_t *unscaled_font)
356 return unscaled_font->backend == &cairo_ft_unscaled_font_backend;
360 * _cairo_ft_unscaled_font_fini:
362 * Free all data associated with a #cairo_ft_unscaled_font_t.
364 * CAUTION: The unscaled->face field must be %NULL before calling this
365 * function. This is because the #cairo_ft_unscaled_font_t_map keeps a
366 * count of these faces (font_map->num_open_faces) so it maintains the
367 * unscaled->face field while it has its lock held. See
368 * _font_map_release_face_lock_held().
370 static void
371 _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
373 assert (unscaled->face == NULL);
375 if (unscaled->filename) {
376 free (unscaled->filename);
377 unscaled->filename = NULL;
380 CAIRO_MUTEX_FINI (unscaled->mutex);
383 static int
384 _cairo_ft_unscaled_font_keys_equal (const void *key_a,
385 const void *key_b)
387 const cairo_ft_unscaled_font_t *unscaled_a = key_a;
388 const cairo_ft_unscaled_font_t *unscaled_b = key_b;
390 return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0 &&
391 unscaled_a->id == unscaled_b->id);
394 /* Finds or creates a #cairo_ft_unscaled_font_t for the filename/id from
395 * pattern. Returns a new reference to the unscaled font.
397 static cairo_ft_unscaled_font_t *
398 _cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
400 cairo_ft_unscaled_font_t key, *unscaled;
401 cairo_ft_unscaled_font_map_t *font_map;
402 cairo_status_t status;
403 FcChar8 *fc_filename;
404 char *filename;
405 int id;
407 if (FcPatternGetString (pattern, FC_FILE, 0, &fc_filename) != FcResultMatch)
408 goto UNWIND;
409 filename = (char *) fc_filename;
411 if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
412 goto UNWIND;
414 font_map = _cairo_ft_unscaled_font_map_lock ();
415 if (font_map == NULL)
416 goto UNWIND;
418 _cairo_ft_unscaled_font_init_key (&key, filename, id);
420 /* Return existing unscaled font if it exists in the hash table. */
421 if (_cairo_hash_table_lookup (font_map->hash_table, &key.base.hash_entry,
422 (cairo_hash_entry_t **) &unscaled))
424 _cairo_unscaled_font_reference (&unscaled->base);
425 _cairo_ft_unscaled_font_map_unlock ();
426 return unscaled;
429 /* Otherwise create it and insert into hash table. */
430 unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
431 if (unscaled == NULL) {
432 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
433 goto UNWIND_FONT_MAP_LOCK;
436 status = _cairo_ft_unscaled_font_init (unscaled, filename, id, NULL);
437 if (status)
438 goto UNWIND_UNSCALED_MALLOC;
440 status = _cairo_hash_table_insert (font_map->hash_table,
441 &unscaled->base.hash_entry);
442 if (status)
443 goto UNWIND_UNSCALED_FONT_INIT;
445 _cairo_ft_unscaled_font_map_unlock ();
447 return unscaled;
449 UNWIND_UNSCALED_FONT_INIT:
450 _cairo_ft_unscaled_font_fini (unscaled);
451 UNWIND_UNSCALED_MALLOC:
452 free (unscaled);
453 UNWIND_FONT_MAP_LOCK:
454 _cairo_ft_unscaled_font_map_unlock ();
455 UNWIND:
456 return NULL;
459 static cairo_ft_unscaled_font_t *
460 _cairo_ft_unscaled_font_create_from_face (FT_Face face)
462 cairo_status_t status;
463 cairo_ft_unscaled_font_t *unscaled;
465 unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
466 if (unscaled == NULL) {
467 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
468 return NULL;
471 status = _cairo_ft_unscaled_font_init (unscaled, NULL, 0, face);
472 if (status) {
473 free (unscaled);
474 return NULL;
477 return unscaled;
480 static void
481 _cairo_ft_unscaled_font_destroy (void *abstract_font)
483 cairo_ft_unscaled_font_t *unscaled = abstract_font;
485 if (unscaled == NULL)
486 return;
488 if (unscaled->from_face) {
489 /* See comments in _ft_font_face_destroy about the "zombie" state
490 * for a _ft_font_face.
492 if (unscaled->faces && !unscaled->faces->unscaled)
493 cairo_font_face_destroy (&unscaled->faces->base);
495 unscaled->face = NULL;
496 } else {
497 cairo_ft_unscaled_font_map_t *font_map;
499 font_map = _cairo_ft_unscaled_font_map_lock ();
500 /* All created objects must have been mapped in the font map. */
501 assert (font_map != NULL);
503 _cairo_hash_table_remove (font_map->hash_table,
504 &unscaled->base.hash_entry);
506 _font_map_release_face_lock_held (font_map, unscaled);
508 _cairo_ft_unscaled_font_map_unlock ();
510 _cairo_ft_unscaled_font_fini (unscaled);
513 static cairo_bool_t
514 _has_unlocked_face (void *entry)
516 cairo_ft_unscaled_font_t *unscaled = entry;
518 return (unscaled->lock_count == 0 && unscaled->face);
521 /* Ensures that an unscaled font has a face object. If we exceed
522 * MAX_OPEN_FACES, try to close some.
524 * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
525 * set the scale on the face, but just returns it at the last scale.
527 FT_Face
528 _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
530 cairo_ft_unscaled_font_map_t *font_map;
531 FT_Face face = NULL;
533 CAIRO_MUTEX_LOCK (unscaled->mutex);
534 unscaled->lock_count++;
536 if (unscaled->face)
537 return unscaled->face;
539 /* If this unscaled font was created from an FT_Face then we just
540 * returned it above. */
541 assert (!unscaled->from_face);
543 font_map = _cairo_ft_unscaled_font_map_lock ();
545 assert (font_map != NULL);
547 while (font_map->num_open_faces >= MAX_OPEN_FACES)
549 cairo_ft_unscaled_font_t *entry;
551 entry = _cairo_hash_table_random_entry (font_map->hash_table,
552 _has_unlocked_face);
553 if (entry == NULL)
554 break;
556 _font_map_release_face_lock_held (font_map, entry);
559 _cairo_ft_unscaled_font_map_unlock ();
561 if (FT_New_Face (font_map->ft_library,
562 unscaled->filename,
563 unscaled->id,
564 &face) != FT_Err_Ok)
566 unscaled->lock_count--;
567 CAIRO_MUTEX_UNLOCK (unscaled->mutex);
568 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
569 return NULL;
572 unscaled->face = face;
574 font_map->num_open_faces++;
576 return face;
580 /* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face
582 void
583 _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
585 assert (unscaled->lock_count > 0);
587 unscaled->lock_count--;
589 CAIRO_MUTEX_UNLOCK (unscaled->mutex);
593 static cairo_status_t
594 _compute_transform (cairo_ft_font_transform_t *sf,
595 cairo_matrix_t *scale)
597 cairo_status_t status;
598 double x_scale, y_scale;
599 cairo_matrix_t normalized = *scale;
601 /* The font matrix has x and y "scale" components which we extract and
602 * use as character scale values. These influence the way freetype
603 * chooses hints, as well as selecting different bitmaps in
604 * hand-rendered fonts. We also copy the normalized matrix to
605 * freetype's transformation.
608 status = _cairo_matrix_compute_scale_factors (scale,
609 &x_scale, &y_scale,
610 /* XXX */ 1);
611 if (status)
612 return status;
614 /* FreeType docs say this about x_scale and y_scale:
615 * "A character width or height smaller than 1pt is set to 1pt;"
616 * So, we cap them from below at 1.0 and let the FT transform
617 * take care of sub-1.0 scaling. */
618 if (x_scale < 1.0)
619 x_scale = 1.0;
620 if (y_scale < 1.0)
621 y_scale = 1.0;
623 sf->x_scale = x_scale;
624 sf->y_scale = y_scale;
626 cairo_matrix_scale (&normalized, 1.0 / x_scale, 1.0 / y_scale);
628 _cairo_matrix_get_affine (&normalized,
629 &sf->shape[0][0], &sf->shape[0][1],
630 &sf->shape[1][0], &sf->shape[1][1],
631 NULL, NULL);
633 return CAIRO_STATUS_SUCCESS;
636 /* Temporarily scales an unscaled font to the give scale. We catch
637 * scaling to the same size, since changing a FT_Face is expensive.
639 static cairo_status_t
640 _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
641 cairo_matrix_t *scale)
643 cairo_status_t status;
644 cairo_ft_font_transform_t sf;
645 FT_Matrix mat;
646 FT_Error error;
648 assert (unscaled->face != NULL);
650 if (unscaled->have_scale &&
651 scale->xx == unscaled->current_scale.xx &&
652 scale->yx == unscaled->current_scale.yx &&
653 scale->xy == unscaled->current_scale.xy &&
654 scale->yy == unscaled->current_scale.yy)
655 return CAIRO_STATUS_SUCCESS;
657 unscaled->have_scale = TRUE;
658 unscaled->current_scale = *scale;
660 status = _compute_transform (&sf, scale);
661 if (status)
662 return status;
664 unscaled->x_scale = sf.x_scale;
665 unscaled->y_scale = sf.y_scale;
667 mat.xx = DOUBLE_TO_16_16(sf.shape[0][0]);
668 mat.yx = - DOUBLE_TO_16_16(sf.shape[0][1]);
669 mat.xy = - DOUBLE_TO_16_16(sf.shape[1][0]);
670 mat.yy = DOUBLE_TO_16_16(sf.shape[1][1]);
672 unscaled->have_shape = (mat.xx != 0x10000 ||
673 mat.yx != 0x00000 ||
674 mat.xy != 0x00000 ||
675 mat.yy != 0x10000);
677 unscaled->Current_Shape = mat;
678 cairo_matrix_init (&unscaled->current_shape,
679 sf.shape[0][0], sf.shape[0][1],
680 sf.shape[1][0], sf.shape[1][1],
681 0.0, 0.0);
683 FT_Set_Transform(unscaled->face, &mat, NULL);
685 if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
686 error = FT_Set_Char_Size (unscaled->face,
687 sf.x_scale * 64.0 + .5,
688 sf.y_scale * 64.0 + .5,
689 0, 0);
690 if (error)
691 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
692 } else {
693 double min_distance = DBL_MAX;
694 int i;
695 int best_i = 0;
697 for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
698 #if HAVE_FT_BITMAP_SIZE_Y_PPEM
699 double size = unscaled->face->available_sizes[i].y_ppem / 64.;
700 #else
701 double size = unscaled->face->available_sizes[i].height;
702 #endif
703 double distance = fabs (size - sf.y_scale);
705 if (distance <= min_distance) {
706 min_distance = distance;
707 best_i = i;
710 #if HAVE_FT_BITMAP_SIZE_Y_PPEM
711 error = FT_Set_Char_Size (unscaled->face,
712 unscaled->face->available_sizes[best_i].x_ppem,
713 unscaled->face->available_sizes[best_i].y_ppem,
714 0, 0);
715 if (error)
716 #endif
717 error = FT_Set_Pixel_Sizes (unscaled->face,
718 unscaled->face->available_sizes[best_i].width,
719 unscaled->face->available_sizes[best_i].height);
720 if (error)
721 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
724 return CAIRO_STATUS_SUCCESS;
727 /* Empirically-derived subpixel filtering values thanks to Keith
728 * Packard and libXft. */
729 static const int filters[3][3] = {
730 /* red */
731 #if 0
732 { 65538*4/7,65538*2/7,65538*1/7 },
733 /* green */
734 { 65536*1/4, 65536*2/4, 65537*1/4 },
735 /* blue */
736 { 65538*1/7,65538*2/7,65538*4/7 },
737 #endif
738 { 65538*9/13,65538*3/13,65538*1/13 },
739 /* green */
740 { 65538*1/6, 65538*4/6, 65538*1/6 },
741 /* blue */
742 { 65538*1/13,65538*3/13,65538*9/13 },
745 /* Fills in val->image with an image surface created from @bitmap
747 static cairo_status_t
748 _get_bitmap_surface (FT_Bitmap *bitmap,
749 cairo_bool_t own_buffer,
750 cairo_font_options_t *font_options,
751 cairo_image_surface_t **surface)
753 int width, height, stride;
754 unsigned char *data;
755 int format = CAIRO_FORMAT_A8;
756 cairo_bool_t subpixel = FALSE;
758 width = bitmap->width;
759 height = bitmap->rows;
761 if (width == 0 || height == 0) {
762 *surface = (cairo_image_surface_t *)
763 cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
764 return (*surface)->base.status;
767 switch (bitmap->pixel_mode) {
768 case FT_PIXEL_MODE_MONO:
769 stride = (((width + 31) & ~31) >> 3);
770 if (own_buffer) {
771 data = bitmap->buffer;
772 assert (stride == bitmap->pitch);
773 } else {
774 data = _cairo_malloc_ab (height, stride);
775 if (!data)
776 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
778 if (stride == bitmap->pitch) {
779 memcpy (data, bitmap->buffer, stride * height);
780 } else {
781 int i;
782 unsigned char *source, *dest;
784 source = bitmap->buffer;
785 dest = data;
786 for (i = height; i; i--) {
787 memcpy (dest, source, bitmap->pitch);
788 memset (dest + bitmap->pitch, '\0', stride - bitmap->pitch);
790 source += bitmap->pitch;
791 dest += stride;
796 #ifndef WORDS_BIGENDIAN
798 unsigned char *d = data;
799 int count = stride * height;
801 while (count--) {
802 *d = CAIRO_BITSWAP8 (*d);
803 d++;
806 #endif
807 format = CAIRO_FORMAT_A1;
808 break;
810 case FT_PIXEL_MODE_LCD:
811 case FT_PIXEL_MODE_LCD_V:
812 case FT_PIXEL_MODE_GRAY:
813 switch (font_options->antialias) {
814 case CAIRO_ANTIALIAS_DEFAULT:
815 case CAIRO_ANTIALIAS_GRAY:
816 case CAIRO_ANTIALIAS_NONE:
817 default:
818 stride = bitmap->pitch;
819 if (own_buffer) {
820 data = bitmap->buffer;
821 } else {
822 data = _cairo_malloc_ab (height, stride);
823 if (!data)
824 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
826 memcpy (data, bitmap->buffer, stride * height);
828 format = CAIRO_FORMAT_A8;
829 break;
830 case CAIRO_ANTIALIAS_SUBPIXEL: {
831 int x, y;
832 unsigned char *in_line, *out_line, *in;
833 unsigned int *out;
834 unsigned int red, green, blue;
835 int rf, gf, bf;
836 int s;
837 int o, os;
838 unsigned char *data_rgba;
839 unsigned int width_rgba, stride_rgba;
840 int vmul = 1;
841 int hmul = 1;
843 switch (font_options->subpixel_order) {
844 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
845 case CAIRO_SUBPIXEL_ORDER_RGB:
846 case CAIRO_SUBPIXEL_ORDER_BGR:
847 default:
848 width /= 3;
849 hmul = 3;
850 break;
851 case CAIRO_SUBPIXEL_ORDER_VRGB:
852 case CAIRO_SUBPIXEL_ORDER_VBGR:
853 vmul = 3;
854 height /= 3;
855 break;
858 * Filter the glyph to soften the color fringes
860 width_rgba = width;
861 stride = bitmap->pitch;
862 stride_rgba = (width_rgba * 4 + 3) & ~3;
863 data_rgba = calloc (stride_rgba, height);
864 if (data_rgba == NULL) {
865 if (own_buffer)
866 free (bitmap->buffer);
867 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
870 os = 1;
871 switch (font_options->subpixel_order) {
872 case CAIRO_SUBPIXEL_ORDER_VRGB:
873 os = stride;
874 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
875 case CAIRO_SUBPIXEL_ORDER_RGB:
876 default:
877 rf = 0;
878 gf = 1;
879 bf = 2;
880 break;
881 case CAIRO_SUBPIXEL_ORDER_VBGR:
882 os = stride;
883 case CAIRO_SUBPIXEL_ORDER_BGR:
884 bf = 0;
885 gf = 1;
886 rf = 2;
887 break;
889 in_line = bitmap->buffer;
890 out_line = data_rgba;
891 for (y = 0; y < height; y++)
893 in = in_line;
894 out = (unsigned int *) out_line;
895 in_line += stride * vmul;
896 out_line += stride_rgba;
897 for (x = 0; x < width * hmul; x += hmul)
899 red = green = blue = 0;
900 o = 0;
901 for (s = 0; s < 3; s++)
903 red += filters[rf][s]*in[x+o];
904 green += filters[gf][s]*in[x+o];
905 blue += filters[bf][s]*in[x+o];
906 o += os;
908 red = red / 65536;
909 green = green / 65536;
910 blue = blue / 65536;
911 *out++ = (green << 24) | (red << 16) | (green << 8) | blue;
915 /* Images here are stored in native format. The
916 * backend must convert to its own format as needed
919 if (own_buffer)
920 free (bitmap->buffer);
921 data = data_rgba;
922 stride = stride_rgba;
923 format = CAIRO_FORMAT_ARGB32;
924 subpixel = TRUE;
925 break;
928 break;
929 case FT_PIXEL_MODE_GRAY2:
930 case FT_PIXEL_MODE_GRAY4:
931 /* These could be triggered by very rare types of TrueType fonts */
932 default:
933 if (own_buffer)
934 free (bitmap->buffer);
935 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
938 *surface = (cairo_image_surface_t *)
939 cairo_image_surface_create_for_data (data,
940 format,
941 width, height, stride);
942 if ((*surface)->base.status) {
943 free (data);
944 return (*surface)->base.status;
947 if (subpixel)
948 pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE);
950 _cairo_image_surface_assume_ownership_of_data ((*surface));
952 return CAIRO_STATUS_SUCCESS;
955 /* Converts an outline FT_GlyphSlot into an image
957 * This could go through _render_glyph_bitmap as well, letting
958 * FreeType convert the outline to a bitmap, but doing it ourselves
959 * has two minor advantages: first, we save a copy of the bitmap
960 * buffer: we can directly use the buffer that FreeType renders
961 * into.
963 * Second, it may help when we add support for subpixel
964 * rendering: the Xft code does it this way. (Keith thinks that
965 * it may also be possible to get the subpixel rendering with
966 * FT_Render_Glyph: something worth looking into in more detail
967 * when we add subpixel support. If so, we may want to eliminate
968 * this version of the code path entirely.
970 static cairo_status_t
971 _render_glyph_outline (FT_Face face,
972 cairo_font_options_t *font_options,
973 cairo_image_surface_t **surface)
975 FT_GlyphSlot glyphslot = face->glyph;
976 FT_Outline *outline = &glyphslot->outline;
977 FT_Bitmap bitmap;
978 FT_BBox cbox;
979 FT_Matrix matrix;
980 int hmul = 1;
981 int vmul = 1;
982 unsigned int width, height, stride;
983 cairo_bool_t subpixel = FALSE;
984 cairo_status_t status;
986 FT_Outline_Get_CBox (outline, &cbox);
988 cbox.xMin &= -64;
989 cbox.yMin &= -64;
990 cbox.xMax = (cbox.xMax + 63) & -64;
991 cbox.yMax = (cbox.yMax + 63) & -64;
993 width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
994 height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
995 stride = (width * hmul + 3) & ~3;
997 if (width * height == 0) {
998 cairo_format_t format;
999 /* Looks like fb handles zero-sized images just fine */
1000 switch (font_options->antialias) {
1001 case CAIRO_ANTIALIAS_NONE:
1002 format = CAIRO_FORMAT_A1;
1003 break;
1004 case CAIRO_ANTIALIAS_SUBPIXEL:
1005 format= CAIRO_FORMAT_ARGB32;
1006 break;
1007 case CAIRO_ANTIALIAS_DEFAULT:
1008 case CAIRO_ANTIALIAS_GRAY:
1009 default:
1010 format = CAIRO_FORMAT_A8;
1011 break;
1014 (*surface) = (cairo_image_surface_t *)
1015 cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
1016 if ((*surface)->base.status)
1017 return (*surface)->base.status;
1018 } else {
1020 matrix.xx = matrix.yy = 0x10000L;
1021 matrix.xy = matrix.yx = 0;
1023 switch (font_options->antialias) {
1024 case CAIRO_ANTIALIAS_NONE:
1025 bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
1026 bitmap.num_grays = 1;
1027 stride = ((width + 31) & -32) >> 3;
1028 break;
1029 case CAIRO_ANTIALIAS_DEFAULT:
1030 case CAIRO_ANTIALIAS_GRAY:
1031 bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
1032 bitmap.num_grays = 256;
1033 stride = (width + 3) & -4;
1034 break;
1035 case CAIRO_ANTIALIAS_SUBPIXEL:
1036 switch (font_options->subpixel_order) {
1037 case CAIRO_SUBPIXEL_ORDER_RGB:
1038 case CAIRO_SUBPIXEL_ORDER_BGR:
1039 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1040 default:
1041 matrix.xx *= 3;
1042 hmul = 3;
1043 subpixel = TRUE;
1044 break;
1045 case CAIRO_SUBPIXEL_ORDER_VRGB:
1046 case CAIRO_SUBPIXEL_ORDER_VBGR:
1047 matrix.yy *= 3;
1048 vmul = 3;
1049 subpixel = TRUE;
1050 break;
1052 FT_Outline_Transform (outline, &matrix);
1054 bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
1055 bitmap.num_grays = 256;
1056 stride = (width * hmul + 3) & -4;
1059 bitmap.pitch = stride;
1060 bitmap.width = width * hmul;
1061 bitmap.rows = height * vmul;
1062 bitmap.buffer = calloc (stride, bitmap.rows);
1063 if (bitmap.buffer == NULL)
1064 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1066 FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
1068 if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
1069 free (bitmap.buffer);
1070 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1073 status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
1074 if (status)
1075 return status;
1079 * Note: the font's coordinate system is upside down from ours, so the
1080 * Y coordinate of the control box needs to be negated. Moreover, device
1081 * offsets are position of glyph origin relative to top left while xMin
1082 * and yMax are offsets of top left relative to origin. Another negation.
1084 cairo_surface_set_device_offset (&(*surface)->base,
1085 floor (-(double) cbox.xMin / 64.0),
1086 floor (+(double) cbox.yMax / 64.0));
1088 return CAIRO_STATUS_SUCCESS;
1091 /* Converts a bitmap (or other) FT_GlyphSlot into an image */
1092 static cairo_status_t
1093 _render_glyph_bitmap (FT_Face face,
1094 cairo_font_options_t *font_options,
1095 cairo_image_surface_t **surface)
1097 FT_GlyphSlot glyphslot = face->glyph;
1098 cairo_status_t status = CAIRO_STATUS_SUCCESS;
1099 FT_Error error;
1101 /* According to the FreeType docs, glyphslot->format could be
1102 * something other than FT_GLYPH_FORMAT_OUTLINE or
1103 * FT_GLYPH_FORMAT_BITMAP. Calling FT_Render_Glyph gives FreeType
1104 * the opportunity to convert such to
1105 * bitmap. FT_GLYPH_FORMAT_COMPOSITE will not be encountered since
1106 * we avoid the FT_LOAD_NO_RECURSE flag.
1108 error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
1109 /* XXX ignoring all other errors for now. They are not fatal, typically
1110 * just a glyph-not-found. */
1111 if (error == FT_Err_Out_Of_Memory)
1112 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1114 status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
1115 if (status)
1116 return status;
1119 * Note: the font's coordinate system is upside down from ours, so the
1120 * Y coordinate of the control box needs to be negated. Moreover, device
1121 * offsets are position of glyph origin relative to top left while
1122 * bitmap_left and bitmap_top are offsets of top left relative to origin.
1123 * Another negation.
1125 cairo_surface_set_device_offset (&(*surface)->base,
1126 -glyphslot->bitmap_left,
1127 +glyphslot->bitmap_top);
1129 return status;
1132 static cairo_status_t
1133 _transform_glyph_bitmap (cairo_matrix_t * shape,
1134 cairo_image_surface_t ** surface)
1136 cairo_matrix_t original_to_transformed;
1137 cairo_matrix_t transformed_to_original;
1138 cairo_image_surface_t *old_image;
1139 cairo_surface_t *image;
1140 double x[4], y[4];
1141 double origin_x, origin_y;
1142 int orig_width, orig_height;
1143 int i;
1144 int x_min, y_min, x_max, y_max;
1145 int width, height;
1146 cairo_status_t status;
1147 cairo_surface_pattern_t pattern;
1149 /* We want to compute a transform that takes the origin
1150 * (device_x_offset, device_y_offset) to 0,0, then applies
1151 * the "shape" portion of the font transform
1153 original_to_transformed = *shape;
1155 cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y);
1156 orig_width = cairo_image_surface_get_width (&(*surface)->base);
1157 orig_height = cairo_image_surface_get_height (&(*surface)->base);
1159 cairo_matrix_translate (&original_to_transformed,
1160 -origin_x, -origin_y);
1162 /* Find the bounding box of the original bitmap under that
1163 * transform
1165 x[0] = 0; y[0] = 0;
1166 x[1] = orig_width; y[1] = 0;
1167 x[2] = orig_width; y[2] = orig_height;
1168 x[3] = 0; y[3] = orig_height;
1170 for (i = 0; i < 4; i++)
1171 cairo_matrix_transform_point (&original_to_transformed,
1172 &x[i], &y[i]);
1174 x_min = floor (x[0]); y_min = floor (y[0]);
1175 x_max = ceil (x[0]); y_max = ceil (y[0]);
1177 for (i = 1; i < 4; i++) {
1178 if (x[i] < x_min)
1179 x_min = floor (x[i]);
1180 else if (x[i] > x_max)
1181 x_max = ceil (x[i]);
1182 if (y[i] < y_min)
1183 y_min = floor (y[i]);
1184 else if (y[i] > y_max)
1185 y_max = ceil (y[i]);
1188 /* Adjust the transform so that the bounding box starts at 0,0 ...
1189 * this gives our final transform from original bitmap to transformed
1190 * bitmap.
1192 original_to_transformed.x0 -= x_min;
1193 original_to_transformed.y0 -= y_min;
1195 /* Create the transformed bitmap
1197 width = x_max - x_min;
1198 height = y_max - y_min;
1200 transformed_to_original = original_to_transformed;
1201 status = cairo_matrix_invert (&transformed_to_original);
1202 if (status)
1203 return status;
1205 /* We need to pad out the width to 32-bit intervals for cairo-xlib-surface.c */
1206 width = (width + 3) & ~3;
1207 image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
1208 if (image->status)
1209 return image->status;
1211 /* Initialize it to empty
1213 status = _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
1214 CAIRO_COLOR_TRANSPARENT,
1215 0, 0,
1216 width, height);
1217 if (status) {
1218 cairo_surface_destroy (image);
1219 return status;
1222 /* Draw the original bitmap transformed into the new bitmap
1224 _cairo_pattern_init_for_surface (&pattern, &(*surface)->base);
1225 cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
1227 status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
1228 &pattern.base, NULL, image,
1229 0, 0, 0, 0, 0, 0,
1230 width,
1231 height);
1233 _cairo_pattern_fini (&pattern.base);
1235 if (status) {
1236 cairo_surface_destroy (image);
1237 return status;
1240 /* Now update the cache entry for the new bitmap, recomputing
1241 * the origin based on the final transform.
1243 cairo_matrix_transform_point (&original_to_transformed,
1244 &origin_x, &origin_y);
1246 old_image = (*surface);
1247 (*surface) = (cairo_image_surface_t *)image;
1248 cairo_surface_destroy (&old_image->base);
1250 cairo_surface_set_device_offset (&(*surface)->base,
1251 _cairo_lround (origin_x),
1252 _cairo_lround (origin_y));
1253 return status;
1256 static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = {
1257 _cairo_ft_unscaled_font_destroy,
1258 #if 0
1259 _cairo_ft_unscaled_font_create_glyph
1260 #endif
1263 /* #cairo_ft_scaled_font_t */
1265 typedef struct _cairo_ft_scaled_font {
1266 cairo_scaled_font_t base;
1267 cairo_ft_unscaled_font_t *unscaled;
1268 cairo_ft_options_t ft_options;
1269 } cairo_ft_scaled_font_t;
1271 const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend;
1273 /* The load flags passed to FT_Load_Glyph control aspects like hinting and
1274 * antialiasing. Here we compute them from the fields of a FcPattern.
1276 static void
1277 _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
1279 FcBool antialias, vertical_layout, hinting, autohint, bitmap, embolden;
1280 cairo_ft_options_t ft_options;
1281 int rgba;
1282 #ifdef FC_HINT_STYLE
1283 int hintstyle;
1284 #endif
1286 _cairo_font_options_init_default (&ft_options.base);
1287 ft_options.load_flags = FT_LOAD_DEFAULT;
1288 ft_options.extra_flags = 0;
1290 #ifndef FC_EMBEDDED_BITMAP
1291 #define FC_EMBEDDED_BITMAP "embeddedbitmap"
1292 #endif
1294 /* Check whether to force use of embedded bitmaps */
1295 if (FcPatternGetBool (pattern,
1296 FC_EMBEDDED_BITMAP, 0, &bitmap) != FcResultMatch)
1297 bitmap = FcFalse;
1299 /* disable antialiasing if requested */
1300 if (FcPatternGetBool (pattern,
1301 FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
1302 antialias = FcTrue;
1304 if (antialias) {
1305 cairo_subpixel_order_t subpixel_order;
1307 /* disable hinting if requested */
1308 if (FcPatternGetBool (pattern,
1309 FC_HINTING, 0, &hinting) != FcResultMatch)
1310 hinting = FcTrue;
1312 if (FcPatternGetInteger (pattern,
1313 FC_RGBA, 0, &rgba) != FcResultMatch)
1314 rgba = FC_RGBA_UNKNOWN;
1316 switch (rgba) {
1317 case FC_RGBA_RGB:
1318 subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
1319 break;
1320 case FC_RGBA_BGR:
1321 subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
1322 break;
1323 case FC_RGBA_VRGB:
1324 subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
1325 break;
1326 case FC_RGBA_VBGR:
1327 subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
1328 break;
1329 case FC_RGBA_UNKNOWN:
1330 case FC_RGBA_NONE:
1331 default:
1332 subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
1333 break;
1336 if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) {
1337 ft_options.base.subpixel_order = subpixel_order;
1338 ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
1341 #ifdef FC_HINT_STYLE
1342 if (FcPatternGetInteger (pattern,
1343 FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
1344 hintstyle = FC_HINT_FULL;
1346 if (!hinting)
1347 hintstyle = FC_HINT_NONE;
1349 switch (hintstyle) {
1350 case FC_HINT_NONE:
1351 ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
1352 break;
1353 case FC_HINT_SLIGHT:
1354 ft_options.base.hint_style = CAIRO_HINT_STYLE_SLIGHT;
1355 break;
1356 case FC_HINT_MEDIUM:
1357 default:
1358 ft_options.base.hint_style = CAIRO_HINT_STYLE_MEDIUM;
1359 break;
1360 case FC_HINT_FULL:
1361 ft_options.base.hint_style = CAIRO_HINT_STYLE_FULL;
1362 break;
1364 #else /* !FC_HINT_STYLE */
1365 if (!hinting) {
1366 ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
1368 #endif /* FC_HINT_STYLE */
1370 /* Force embedded bitmaps off if no hinting requested */
1371 if (ft_options.base.hint_style == CAIRO_HINT_STYLE_NONE)
1372 bitmap = FcFalse;
1374 if (!bitmap)
1375 ft_options.load_flags |= FT_LOAD_NO_BITMAP;
1377 } else {
1378 ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
1381 /* force autohinting if requested */
1382 if (FcPatternGetBool (pattern,
1383 FC_AUTOHINT, 0, &autohint) != FcResultMatch)
1384 autohint = FcFalse;
1386 if (autohint)
1387 ft_options.load_flags |= FT_LOAD_FORCE_AUTOHINT;
1389 if (FcPatternGetBool (pattern,
1390 FC_VERTICAL_LAYOUT, 0, &vertical_layout) != FcResultMatch)
1391 vertical_layout = FcFalse;
1393 if (vertical_layout)
1394 ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT;
1396 #ifndef FC_EMBOLDEN
1397 #define FC_EMBOLDEN "embolden"
1398 #endif
1399 if (FcPatternGetBool (pattern,
1400 FC_EMBOLDEN, 0, &embolden) != FcResultMatch)
1401 embolden = FcFalse;
1403 if (embolden)
1404 ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN;
1406 *ret = ft_options;
1409 static void
1410 _cairo_ft_options_merge (cairo_ft_options_t *options,
1411 cairo_ft_options_t *other)
1413 int load_flags = other->load_flags;
1414 int load_target = FT_LOAD_TARGET_NORMAL;
1416 /* clear load target mode */
1417 load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(other->load_flags)));
1419 if (load_flags & FT_LOAD_NO_HINTING)
1420 other->base.hint_style = CAIRO_HINT_STYLE_NONE;
1422 if (other->base.antialias == CAIRO_ANTIALIAS_NONE ||
1423 options->base.antialias == CAIRO_ANTIALIAS_NONE) {
1424 options->base.antialias = CAIRO_ANTIALIAS_NONE;
1425 options->base.subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
1428 if (other->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL &&
1429 (options->base.antialias == CAIRO_ANTIALIAS_DEFAULT ||
1430 options->base.antialias == CAIRO_ANTIALIAS_GRAY)) {
1431 options->base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
1432 options->base.subpixel_order = other->base.subpixel_order;
1435 if (options->base.hint_style == CAIRO_HINT_STYLE_DEFAULT)
1436 options->base.hint_style = other->base.hint_style;
1438 if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
1439 options->base.hint_style = CAIRO_HINT_STYLE_NONE;
1441 if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
1442 if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
1443 load_flags |= FT_LOAD_NO_HINTING;
1444 else
1445 load_target = FT_LOAD_TARGET_MONO;
1446 load_flags |= FT_LOAD_MONOCHROME;
1447 } else {
1448 switch (options->base.hint_style) {
1449 case CAIRO_HINT_STYLE_NONE:
1450 load_flags |= FT_LOAD_NO_HINTING;
1451 break;
1452 case CAIRO_HINT_STYLE_SLIGHT:
1453 load_target = FT_LOAD_TARGET_LIGHT;
1454 break;
1455 case CAIRO_HINT_STYLE_MEDIUM:
1456 break;
1457 case CAIRO_HINT_STYLE_FULL:
1458 case CAIRO_HINT_STYLE_DEFAULT:
1459 if (options->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
1460 switch (options->base.subpixel_order) {
1461 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1462 case CAIRO_SUBPIXEL_ORDER_RGB:
1463 case CAIRO_SUBPIXEL_ORDER_BGR:
1464 load_target |= FT_LOAD_TARGET_LCD;
1465 break;
1466 case CAIRO_SUBPIXEL_ORDER_VRGB:
1467 case CAIRO_SUBPIXEL_ORDER_VBGR:
1468 load_target |= FT_LOAD_TARGET_LCD_V;
1469 break;
1472 break;
1476 options->load_flags = load_flags | load_target;
1477 options->extra_flags = other->extra_flags;
1478 if (options->base.hint_metrics != CAIRO_HINT_METRICS_OFF)
1479 options->extra_flags |= CAIRO_FT_OPTIONS_HINT_METRICS;
1482 static cairo_status_t
1483 _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
1484 cairo_font_face_t *font_face,
1485 const cairo_matrix_t *font_matrix,
1486 const cairo_matrix_t *ctm,
1487 const cairo_font_options_t *options,
1488 cairo_ft_options_t ft_options,
1489 cairo_scaled_font_t **font_out)
1491 cairo_ft_scaled_font_t *scaled_font;
1492 FT_Face face;
1493 FT_Size_Metrics *metrics;
1494 cairo_font_extents_t fs_metrics;
1495 cairo_status_t status;
1497 face = _cairo_ft_unscaled_font_lock_face (unscaled);
1498 if (!face)
1499 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1501 scaled_font = malloc (sizeof(cairo_ft_scaled_font_t));
1502 if (scaled_font == NULL) {
1503 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1504 goto FAIL;
1507 _cairo_unscaled_font_reference (&unscaled->base);
1508 scaled_font->unscaled = unscaled;
1510 _cairo_font_options_init_copy (&scaled_font->ft_options.base, options);
1511 _cairo_ft_options_merge (&scaled_font->ft_options, &ft_options);
1513 status = _cairo_scaled_font_init (&scaled_font->base,
1514 font_face,
1515 font_matrix, ctm, options,
1516 &cairo_ft_scaled_font_backend);
1517 if (status) {
1518 _cairo_unscaled_font_destroy (&unscaled->base);
1519 free (scaled_font);
1520 goto FAIL;
1523 status = _cairo_ft_unscaled_font_set_scale (unscaled,
1524 &scaled_font->base.scale);
1525 if (status) {
1526 _cairo_unscaled_font_destroy (&unscaled->base);
1527 free (scaled_font);
1528 goto FAIL;
1532 metrics = &face->size->metrics;
1535 * Get to unscaled metrics so that the upper level can get back to
1536 * user space
1538 * Also use this path for bitmap-only fonts. The other branch uses
1539 * face members that are only relevant for scalable fonts. This is
1540 * detected by simply checking for units_per_EM==0.
1542 if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF ||
1543 face->units_per_EM == 0) {
1544 double x_factor, y_factor;
1546 if (unscaled->x_scale == 0)
1547 x_factor = 0;
1548 else
1549 x_factor = 1 / unscaled->x_scale;
1551 if (unscaled->y_scale == 0)
1552 y_factor = 0;
1553 else
1554 y_factor = 1 / unscaled->y_scale;
1556 fs_metrics.ascent = DOUBLE_FROM_26_6(metrics->ascender) * y_factor;
1557 fs_metrics.descent = DOUBLE_FROM_26_6(- metrics->descender) * y_factor;
1558 fs_metrics.height = DOUBLE_FROM_26_6(metrics->height) * y_factor;
1559 if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
1560 fs_metrics.max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) * x_factor;
1561 fs_metrics.max_y_advance = 0;
1562 } else {
1563 fs_metrics.max_x_advance = 0;
1564 fs_metrics.max_y_advance = DOUBLE_FROM_26_6(metrics->max_advance) * y_factor;
1566 } else {
1567 double scale = face->units_per_EM;
1569 fs_metrics.ascent = face->ascender / scale;
1570 fs_metrics.descent = - face->descender / scale;
1571 fs_metrics.height = face->height / scale;
1572 if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
1573 fs_metrics.max_x_advance = face->max_advance_width / scale;
1574 fs_metrics.max_y_advance = 0;
1575 } else {
1576 fs_metrics.max_x_advance = 0;
1577 fs_metrics.max_y_advance = face->max_advance_height / scale;
1581 status = _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics);
1583 *font_out = &scaled_font->base;
1585 FAIL:
1586 _cairo_ft_unscaled_font_unlock_face (unscaled);
1588 return status;
1591 cairo_bool_t
1592 _cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
1594 return scaled_font->backend == &cairo_ft_scaled_font_backend;
1597 static cairo_status_t
1598 _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
1599 const cairo_matrix_t *font_matrix,
1600 const cairo_matrix_t *ctm,
1601 const cairo_font_options_t *font_options,
1602 cairo_scaled_font_t **font)
1604 FcPattern *pattern, *resolved;
1605 cairo_ft_unscaled_font_t *unscaled;
1606 FcResult result;
1607 int fcslant;
1608 int fcweight;
1609 cairo_matrix_t scale;
1610 cairo_status_t status;
1611 cairo_ft_font_transform_t sf;
1612 cairo_ft_options_t ft_options;
1614 cairo_matrix_multiply (&scale, font_matrix, ctm);
1615 status = _compute_transform (&sf, &scale);
1616 if (status)
1617 return status;
1619 pattern = FcPatternCreate ();
1620 if (!pattern)
1621 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1623 if (!FcPatternAddString (pattern,
1624 FC_FAMILY, (unsigned char *) toy_face->family))
1626 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1627 goto FREE_PATTERN;
1630 switch (toy_face->slant)
1632 case CAIRO_FONT_SLANT_ITALIC:
1633 fcslant = FC_SLANT_ITALIC;
1634 break;
1635 case CAIRO_FONT_SLANT_OBLIQUE:
1636 fcslant = FC_SLANT_OBLIQUE;
1637 break;
1638 case CAIRO_FONT_SLANT_NORMAL:
1639 default:
1640 fcslant = FC_SLANT_ROMAN;
1641 break;
1644 if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant)) {
1645 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1646 goto FREE_PATTERN;
1649 switch (toy_face->weight)
1651 case CAIRO_FONT_WEIGHT_BOLD:
1652 fcweight = FC_WEIGHT_BOLD;
1653 break;
1654 case CAIRO_FONT_WEIGHT_NORMAL:
1655 default:
1656 fcweight = FC_WEIGHT_MEDIUM;
1657 break;
1660 if (!FcPatternAddInteger (pattern, FC_WEIGHT, fcweight)) {
1661 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1662 goto FREE_PATTERN;
1665 if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE, sf.y_scale)) {
1666 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1667 goto FREE_PATTERN;
1670 if (! FcConfigSubstitute (NULL, pattern, FcMatchPattern)) {
1671 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1672 goto FREE_PATTERN;
1675 status = _cairo_ft_font_options_substitute (font_options, pattern);
1676 if (status)
1677 goto FREE_PATTERN;
1679 FcDefaultSubstitute (pattern);
1681 resolved = FcFontMatch (NULL, pattern, &result);
1682 if (!resolved) {
1683 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1684 goto FREE_PATTERN;
1687 unscaled = _cairo_ft_unscaled_font_create_for_pattern (resolved);
1688 if (!unscaled) {
1689 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1690 goto FREE_RESOLVED;
1693 _get_pattern_ft_options (resolved, &ft_options);
1695 status = _cairo_ft_scaled_font_create (unscaled,
1696 &toy_face->base,
1697 font_matrix, ctm,
1698 font_options, ft_options,
1699 font);
1701 _cairo_unscaled_font_destroy (&unscaled->base);
1703 FREE_RESOLVED:
1704 FcPatternDestroy (resolved);
1706 FREE_PATTERN:
1707 FcPatternDestroy (pattern);
1709 return status;
1712 static void
1713 _cairo_ft_scaled_font_fini (void *abstract_font)
1715 cairo_ft_scaled_font_t *scaled_font = abstract_font;
1717 if (scaled_font == NULL)
1718 return;
1720 _cairo_unscaled_font_destroy (&scaled_font->unscaled->base);
1723 static int
1724 _move_to (FT_Vector *to, void *closure)
1726 cairo_path_fixed_t *path = closure;
1727 cairo_fixed_t x, y;
1729 x = _cairo_fixed_from_26_6 (to->x);
1730 y = _cairo_fixed_from_26_6 (to->y);
1732 if (_cairo_path_fixed_close_path (path) != CAIRO_STATUS_SUCCESS)
1733 return 1;
1734 if (_cairo_path_fixed_move_to (path, x, y) != CAIRO_STATUS_SUCCESS)
1735 return 1;
1737 return 0;
1740 static int
1741 _line_to (FT_Vector *to, void *closure)
1743 cairo_path_fixed_t *path = closure;
1744 cairo_fixed_t x, y;
1746 x = _cairo_fixed_from_26_6 (to->x);
1747 y = _cairo_fixed_from_26_6 (to->y);
1749 if (_cairo_path_fixed_line_to (path, x, y) != CAIRO_STATUS_SUCCESS)
1750 return 1;
1752 return 0;
1755 static int
1756 _conic_to (FT_Vector *control, FT_Vector *to, void *closure)
1758 cairo_path_fixed_t *path = closure;
1760 cairo_fixed_t x0, y0;
1761 cairo_fixed_t x1, y1;
1762 cairo_fixed_t x2, y2;
1763 cairo_fixed_t x3, y3;
1764 cairo_point_t conic;
1766 if (! _cairo_path_fixed_get_current_point (path, &x0, &y0))
1767 return 1;
1769 conic.x = _cairo_fixed_from_26_6 (control->x);
1770 conic.y = _cairo_fixed_from_26_6 (control->y);
1772 x3 = _cairo_fixed_from_26_6 (to->x);
1773 y3 = _cairo_fixed_from_26_6 (to->y);
1775 x1 = x0 + 2.0/3.0 * (conic.x - x0);
1776 y1 = y0 + 2.0/3.0 * (conic.y - y0);
1778 x2 = x3 + 2.0/3.0 * (conic.x - x3);
1779 y2 = y3 + 2.0/3.0 * (conic.y - y3);
1781 if (_cairo_path_fixed_curve_to (path,
1782 x1, y1,
1783 x2, y2,
1784 x3, y3) != CAIRO_STATUS_SUCCESS)
1785 return 1;
1787 return 0;
1790 static int
1791 _cubic_to (FT_Vector *control1, FT_Vector *control2,
1792 FT_Vector *to, void *closure)
1794 cairo_path_fixed_t *path = closure;
1795 cairo_fixed_t x0, y0;
1796 cairo_fixed_t x1, y1;
1797 cairo_fixed_t x2, y2;
1799 x0 = _cairo_fixed_from_26_6 (control1->x);
1800 y0 = _cairo_fixed_from_26_6 (control1->y);
1802 x1 = _cairo_fixed_from_26_6 (control2->x);
1803 y1 = _cairo_fixed_from_26_6 (control2->y);
1805 x2 = _cairo_fixed_from_26_6 (to->x);
1806 y2 = _cairo_fixed_from_26_6 (to->y);
1808 if (_cairo_path_fixed_curve_to (path,
1809 x0, y0,
1810 x1, y1,
1811 x2, y2) != CAIRO_STATUS_SUCCESS)
1812 return 1;
1814 return 0;
1817 static cairo_status_t
1818 _decompose_glyph_outline (FT_Face face,
1819 cairo_font_options_t *options,
1820 cairo_path_fixed_t **pathp)
1822 static const FT_Outline_Funcs outline_funcs = {
1823 (FT_Outline_MoveToFunc)_move_to,
1824 (FT_Outline_LineToFunc)_line_to,
1825 (FT_Outline_ConicToFunc)_conic_to,
1826 (FT_Outline_CubicToFunc)_cubic_to,
1827 0, /* shift */
1828 0, /* delta */
1830 static const FT_Matrix invert_y = {
1831 DOUBLE_TO_16_16 (1.0), 0,
1832 0, DOUBLE_TO_16_16 (-1.0),
1835 FT_GlyphSlot glyph;
1836 cairo_path_fixed_t *path;
1837 cairo_status_t status;
1839 path = _cairo_path_fixed_create ();
1840 if (!path)
1841 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1843 glyph = face->glyph;
1845 /* Font glyphs have an inverted Y axis compared to cairo. */
1846 FT_Outline_Transform (&glyph->outline, &invert_y);
1847 if (FT_Outline_Decompose (&glyph->outline, &outline_funcs, path)) {
1848 _cairo_path_fixed_destroy (path);
1849 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1852 status = _cairo_path_fixed_close_path (path);
1853 if (status) {
1854 _cairo_path_fixed_destroy (path);
1855 return status;
1858 *pathp = path;
1860 return CAIRO_STATUS_SUCCESS;
1864 * Translate glyph to match its metrics.
1866 static void
1867 _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (void *abstract_font,
1868 FT_GlyphSlot glyph)
1870 cairo_ft_scaled_font_t *scaled_font = abstract_font;
1871 FT_Vector vector;
1873 vector.x = glyph->metrics.vertBearingX - glyph->metrics.horiBearingX;
1874 vector.y = -glyph->metrics.vertBearingY - glyph->metrics.horiBearingY;
1876 if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
1877 FT_Vector_Transform (&vector, &scaled_font->unscaled->Current_Shape);
1878 FT_Outline_Translate(&glyph->outline, vector.x, vector.y);
1879 } else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
1880 glyph->bitmap_left += vector.x / 64;
1881 glyph->bitmap_top += vector.y / 64;
1885 static cairo_int_status_t
1886 _cairo_ft_scaled_glyph_init (void *abstract_font,
1887 cairo_scaled_glyph_t *scaled_glyph,
1888 cairo_scaled_glyph_info_t info)
1890 cairo_text_extents_t fs_metrics;
1891 cairo_ft_scaled_font_t *scaled_font = abstract_font;
1892 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
1893 FT_GlyphSlot glyph;
1894 FT_Face face;
1895 FT_Error error;
1896 int load_flags = scaled_font->ft_options.load_flags;
1897 FT_Glyph_Metrics *metrics;
1898 double x_factor, y_factor;
1899 cairo_bool_t vertical_layout = FALSE;
1900 cairo_status_t status;
1902 face = _cairo_ft_unscaled_font_lock_face (unscaled);
1903 if (!face)
1904 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1906 status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
1907 &scaled_font->base.scale);
1908 if (status)
1909 goto FAIL;
1911 /* Ignore global advance unconditionally */
1912 load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
1914 if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
1915 (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0)
1916 load_flags |= FT_LOAD_NO_BITMAP;
1919 * Don't pass FT_LOAD_VERTICAL_LAYOUT to FT_Load_Glyph here as
1920 * suggested by freetype people.
1922 if (load_flags & FT_LOAD_VERTICAL_LAYOUT) {
1923 load_flags &= ~FT_LOAD_VERTICAL_LAYOUT;
1924 vertical_layout = TRUE;
1927 error = FT_Load_Glyph (scaled_font->unscaled->face,
1928 _cairo_scaled_glyph_index(scaled_glyph),
1929 load_flags);
1930 /* XXX ignoring all other errors for now. They are not fatal, typically
1931 * just a glyph-not-found. */
1932 if (error == FT_Err_Out_Of_Memory) {
1933 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1934 goto FAIL;
1937 glyph = face->glyph;
1939 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
1941 * embolden glyphs if requested
1943 if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN)
1944 FT_GlyphSlot_Embolden (glyph);
1945 #endif
1947 if (vertical_layout)
1948 _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph);
1950 if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
1952 cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF;
1954 * Compute font-space metrics
1956 metrics = &glyph->metrics;
1958 if (unscaled->x_scale == 0)
1959 x_factor = 0;
1960 else
1961 x_factor = 1 / unscaled->x_scale;
1963 if (unscaled->y_scale == 0)
1964 y_factor = 0;
1965 else
1966 y_factor = 1 / unscaled->y_scale;
1969 * Note: Y coordinates of the horizontal bearing need to be negated.
1971 * Scale metrics back to glyph space from the scaled glyph space returned
1972 * by FreeType
1974 * If we want hinted metrics but aren't asking for hinted glyphs from
1975 * FreeType, then we need to do the metric hinting ourselves.
1978 if (hint_metrics && (load_flags & FT_LOAD_NO_HINTING))
1980 FT_Pos x1, x2;
1981 FT_Pos y1, y2;
1982 FT_Pos advance;
1984 if (!vertical_layout) {
1985 x1 = (metrics->horiBearingX) & -64;
1986 x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
1987 y1 = (-metrics->horiBearingY) & -64;
1988 y2 = (-metrics->horiBearingY + metrics->height + 63) & -64;
1990 advance = ((metrics->horiAdvance + 32) & -64);
1992 fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor;
1993 fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor;
1995 fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor;
1996 fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
1998 fs_metrics.x_advance = DOUBLE_FROM_26_6 (advance) * x_factor;
1999 fs_metrics.y_advance = 0;
2000 } else {
2001 x1 = (metrics->vertBearingX) & -64;
2002 x2 = (metrics->vertBearingX + metrics->width + 63) & -64;
2003 y1 = (metrics->vertBearingY) & -64;
2004 y2 = (metrics->vertBearingY + metrics->height + 63) & -64;
2006 advance = ((metrics->vertAdvance + 32) & -64);
2008 fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor;
2009 fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor;
2011 fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor;
2012 fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
2014 fs_metrics.x_advance = 0;
2015 fs_metrics.y_advance = DOUBLE_FROM_26_6 (advance) * y_factor;
2017 } else {
2018 fs_metrics.width = DOUBLE_FROM_26_6 (metrics->width) * x_factor;
2019 fs_metrics.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor;
2021 if (!vertical_layout) {
2022 fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor;
2023 fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor;
2025 if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
2026 fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor;
2027 else
2028 fs_metrics.x_advance = DOUBLE_FROM_16_16 (glyph->linearHoriAdvance) * x_factor;
2029 fs_metrics.y_advance = 0 * y_factor;
2030 } else {
2031 fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingX) * x_factor;
2032 fs_metrics.y_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingY) * y_factor;
2034 fs_metrics.x_advance = 0 * x_factor;
2035 if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
2036 fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor;
2037 else
2038 fs_metrics.y_advance = DOUBLE_FROM_26_6 (glyph->linearVertAdvance) * y_factor;
2042 _cairo_scaled_glyph_set_metrics (scaled_glyph,
2043 &scaled_font->base,
2044 &fs_metrics);
2047 if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
2048 cairo_image_surface_t *surface;
2050 if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
2051 status = _render_glyph_outline (face, &scaled_font->ft_options.base,
2052 &surface);
2053 } else {
2054 status = _render_glyph_bitmap (face, &scaled_font->ft_options.base,
2055 &surface);
2056 if (status == CAIRO_STATUS_SUCCESS && unscaled->have_shape) {
2057 status = _transform_glyph_bitmap (&unscaled->current_shape,
2058 &surface);
2059 if (status)
2060 cairo_surface_destroy (&surface->base);
2063 if (status)
2064 goto FAIL;
2066 _cairo_scaled_glyph_set_surface (scaled_glyph,
2067 &scaled_font->base,
2068 surface);
2071 if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
2072 cairo_path_fixed_t *path = NULL; /* hide compiler warning */
2075 * A kludge -- the above code will trash the outline,
2076 * so reload it. This will probably never occur though
2078 if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
2079 error = FT_Load_Glyph (face,
2080 _cairo_scaled_glyph_index(scaled_glyph),
2081 load_flags | FT_LOAD_NO_BITMAP);
2082 /* XXX ignoring all other errors for now. They are not fatal, typically
2083 * just a glyph-not-found. */
2084 if (error == FT_Err_Out_Of_Memory) {
2085 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2086 goto FAIL;
2088 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
2090 * embolden glyphs if requested
2092 if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN)
2093 FT_GlyphSlot_Embolden (glyph);
2094 #endif
2095 if (vertical_layout)
2096 _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph);
2099 if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
2100 status = _decompose_glyph_outline (face, &scaled_font->ft_options.base,
2101 &path);
2102 else
2103 status = CAIRO_INT_STATUS_UNSUPPORTED;
2105 if (status)
2106 goto FAIL;
2108 _cairo_scaled_glyph_set_path (scaled_glyph,
2109 &scaled_font->base,
2110 path);
2112 FAIL:
2113 _cairo_ft_unscaled_font_unlock_face (unscaled);
2115 return status;
2118 static unsigned long
2119 _cairo_ft_ucs4_to_index (void *abstract_font,
2120 uint32_t ucs4)
2122 cairo_ft_scaled_font_t *scaled_font = abstract_font;
2123 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
2124 FT_Face face;
2125 FT_UInt index;
2127 face = _cairo_ft_unscaled_font_lock_face (unscaled);
2128 if (!face)
2129 return 0;
2130 index = FT_Get_Char_Index (face, ucs4);
2131 _cairo_ft_unscaled_font_unlock_face (unscaled);
2132 return index;
2135 static cairo_int_status_t
2136 _cairo_ft_load_truetype_table (void *abstract_font,
2137 unsigned long tag,
2138 long offset,
2139 unsigned char *buffer,
2140 unsigned long *length)
2142 cairo_ft_scaled_font_t *scaled_font = abstract_font;
2143 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
2144 FT_Face face;
2145 cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
2147 if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base))
2148 return CAIRO_INT_STATUS_UNSUPPORTED;
2150 #if HAVE_FT_LOAD_SFNT_TABLE
2151 face = _cairo_ft_unscaled_font_lock_face (unscaled);
2152 if (!face)
2153 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2155 if (FT_IS_SFNT (face) &&
2156 FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0)
2157 status = CAIRO_STATUS_SUCCESS;
2159 _cairo_ft_unscaled_font_unlock_face (unscaled);
2160 #endif
2162 return status;
2165 static cairo_int_status_t
2166 _cairo_ft_map_glyphs_to_unicode (void *abstract_font,
2167 cairo_scaled_font_subset_t *font_subset)
2169 cairo_ft_scaled_font_t *scaled_font = abstract_font;
2170 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
2171 FT_Face face;
2172 FT_UInt glyph;
2173 unsigned long charcode;
2174 unsigned int i;
2175 int count;
2177 face = _cairo_ft_unscaled_font_lock_face (unscaled);
2178 if (!face)
2179 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2181 count = font_subset->num_glyphs;
2182 charcode = FT_Get_First_Char( face, &glyph);
2183 while (glyph != 0 && count > 0)
2185 for (i = 0; i < font_subset->num_glyphs; i++) {
2186 if (font_subset->glyphs[i] == glyph) {
2187 font_subset->to_unicode[i] = charcode;
2188 count--;
2189 break;
2192 charcode = FT_Get_Next_Char (face, charcode, &glyph);
2194 _cairo_ft_unscaled_font_unlock_face (unscaled);
2196 return CAIRO_STATUS_SUCCESS;
2199 const cairo_scaled_font_backend_t cairo_ft_scaled_font_backend = {
2200 CAIRO_FONT_TYPE_FT,
2201 _cairo_ft_scaled_font_create_toy,
2202 _cairo_ft_scaled_font_fini,
2203 _cairo_ft_scaled_glyph_init,
2204 NULL, /* text_to_glyphs */
2205 _cairo_ft_ucs4_to_index,
2206 NULL, /* show_glyphs */
2207 _cairo_ft_load_truetype_table,
2208 _cairo_ft_map_glyphs_to_unicode,
2211 /* #cairo_ft_font_face_t */
2213 static void
2214 _cairo_ft_font_face_destroy (void *abstract_face)
2216 cairo_ft_font_face_t *font_face = abstract_face;
2218 cairo_ft_font_face_t *tmp_face = NULL;
2219 cairo_ft_font_face_t *last_face = NULL;
2221 if (font_face == NULL)
2222 return;
2224 /* When destroying the face created by cairo_ft_font_face_create_for_ft_face,
2225 * we have a special "zombie" state for the face when the unscaled font
2226 * is still alive but there are no public references to the font face.
2228 * We go from:
2230 * font_face ------> unscaled
2231 * <-....weak....../
2233 * To:
2235 * font_face <------- unscaled
2238 if (font_face->unscaled &&
2239 font_face->unscaled->from_face &&
2240 CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1)
2242 cairo_font_face_reference (&font_face->base);
2244 _cairo_unscaled_font_destroy (&font_face->unscaled->base);
2245 font_face->unscaled = NULL;
2247 return;
2250 if (font_face->unscaled) {
2251 /* Remove face from linked list */
2252 for (tmp_face = font_face->unscaled->faces;
2253 tmp_face;
2254 tmp_face = tmp_face->next)
2256 if (tmp_face == font_face) {
2257 if (last_face)
2258 last_face->next = tmp_face->next;
2259 else
2260 font_face->unscaled->faces = tmp_face->next;
2263 last_face = tmp_face;
2266 _cairo_unscaled_font_destroy (&font_face->unscaled->base);
2267 font_face->unscaled = NULL;
2271 static cairo_status_t
2272 _cairo_ft_font_face_scaled_font_create (void *abstract_face,
2273 const cairo_matrix_t *font_matrix,
2274 const cairo_matrix_t *ctm,
2275 const cairo_font_options_t *options,
2276 cairo_scaled_font_t **scaled_font)
2278 cairo_ft_font_face_t *font_face = abstract_face;
2279 cairo_ft_options_t ft_options;
2281 /* The handling of font options is different depending on how the
2282 * font face was created. When the user creates a font face with
2283 * cairo_ft_font_face_create_for_ft_face(), then the load flags
2284 * passed in augment the load flags for the options. But for
2285 * cairo_ft_font_face_create_for_pattern(), the load flags are
2286 * derived from a pattern where the user has called
2287 * cairo_ft_font_options_substitute(), so *just* use those load
2288 * flags and ignore the options.
2291 ft_options = font_face->ft_options;
2293 return _cairo_ft_scaled_font_create (font_face->unscaled,
2294 &font_face->base,
2295 font_matrix, ctm,
2296 options, ft_options,
2297 scaled_font);
2300 static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
2301 CAIRO_FONT_TYPE_FT,
2302 _cairo_ft_font_face_destroy,
2303 _cairo_ft_font_face_scaled_font_create
2306 static cairo_font_face_t *
2307 _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
2308 cairo_ft_options_t *ft_options)
2310 cairo_ft_font_face_t *font_face, **prev_font_face;
2312 /* Looked for an existing matching font face */
2313 for (font_face = unscaled->faces, prev_font_face = &unscaled->faces;
2314 font_face;
2315 prev_font_face = &font_face->next, font_face = font_face->next)
2317 if (font_face->ft_options.load_flags == ft_options->load_flags &&
2318 font_face->ft_options.extra_flags == ft_options->extra_flags &&
2319 cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
2321 if (font_face->base.status == CAIRO_STATUS_SUCCESS)
2322 return cairo_font_face_reference (&font_face->base);
2324 /* The font_face has been left in an error state, abandon it. */
2325 *prev_font_face = font_face->next;
2326 break;
2330 /* No match found, create a new one */
2331 font_face = malloc (sizeof (cairo_ft_font_face_t));
2332 if (!font_face) {
2333 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
2334 return (cairo_font_face_t *)&_cairo_font_face_nil;
2337 font_face->unscaled = unscaled;
2338 _cairo_unscaled_font_reference (&unscaled->base);
2340 font_face->ft_options = *ft_options;
2342 font_face->next = unscaled->faces;
2343 unscaled->faces = font_face;
2345 _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
2347 return &font_face->base;
2350 /* implement the platform-specific interface */
2352 static cairo_status_t
2353 _cairo_ft_font_options_substitute (const cairo_font_options_t *options,
2354 FcPattern *pattern)
2356 FcValue v;
2358 if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
2360 if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch)
2362 if (! FcPatternAddBool (pattern,
2363 FC_ANTIALIAS,
2364 options->antialias != CAIRO_ANTIALIAS_NONE))
2365 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2367 if (options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
2368 FcPatternDel (pattern, FC_RGBA);
2369 if (! FcPatternAddInteger (pattern, FC_RGBA, FC_RGBA_NONE))
2370 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2375 if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
2377 if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch)
2379 int rgba;
2381 if (options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
2382 switch (options->subpixel_order) {
2383 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
2384 case CAIRO_SUBPIXEL_ORDER_RGB:
2385 default:
2386 rgba = FC_RGBA_RGB;
2387 break;
2388 case CAIRO_SUBPIXEL_ORDER_BGR:
2389 rgba = FC_RGBA_BGR;
2390 break;
2391 case CAIRO_SUBPIXEL_ORDER_VRGB:
2392 rgba = FC_RGBA_VRGB;
2393 break;
2394 case CAIRO_SUBPIXEL_ORDER_VBGR:
2395 rgba = FC_RGBA_VBGR;
2396 break;
2398 } else {
2399 rgba = FC_RGBA_NONE;
2402 if (! FcPatternAddInteger (pattern, FC_RGBA, rgba))
2403 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2407 if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
2409 if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
2411 if (! FcPatternAddBool (pattern,
2412 FC_HINTING,
2413 options->hint_style != CAIRO_HINT_STYLE_NONE))
2414 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2417 #ifdef FC_HINT_STYLE
2418 if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch)
2420 int hint_style;
2422 switch (options->hint_style) {
2423 case CAIRO_HINT_STYLE_NONE:
2424 hint_style = FC_HINT_NONE;
2425 break;
2426 case CAIRO_HINT_STYLE_SLIGHT:
2427 hint_style = FC_HINT_SLIGHT;
2428 break;
2429 case CAIRO_HINT_STYLE_MEDIUM:
2430 hint_style = FC_HINT_MEDIUM;
2431 break;
2432 case CAIRO_HINT_STYLE_FULL:
2433 case CAIRO_HINT_STYLE_DEFAULT:
2434 default:
2435 hint_style = FC_HINT_FULL;
2436 break;
2439 if (! FcPatternAddInteger (pattern, FC_HINT_STYLE, hint_style))
2440 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2442 #endif
2445 return CAIRO_STATUS_SUCCESS;
2449 * cairo_ft_font_options_substitute:
2450 * @options: a #cairo_font_options_t object
2451 * @pattern: an existing #FcPattern
2453 * Add options to a #FcPattern based on a #cairo_font_options_t font
2454 * options object. Options that are already in the pattern, are not overridden,
2455 * so you should call this function after calling FcConfigSubstitute() (the
2456 * user's settings should override options based on the surface type), but
2457 * before calling FcDefaultSubstitute().
2459 void
2460 cairo_ft_font_options_substitute (const cairo_font_options_t *options,
2461 FcPattern *pattern)
2463 if (cairo_font_options_status ((cairo_font_options_t *) options))
2464 return;
2466 _cairo_ft_font_options_substitute (options, pattern);
2470 * cairo_ft_font_face_create_for_pattern:
2471 * @pattern: A fully resolved fontconfig
2472 * pattern. A pattern can be resolved, by, among other things, calling
2473 * FcConfigSubstitute(), FcDefaultSubstitute(), then
2474 * FcFontMatch(). Cairo will call FcPatternReference() on this
2475 * pattern, so you should not further modify the pattern, but you can
2476 * release your reference to the pattern with FcPatternDestroy() if
2477 * you no longer need to access it.
2479 * Creates a new font face for the FreeType font backend based on a
2480 * fontconfig pattern. This font can then be used with
2481 * cairo_set_font_face() or cairo_scaled_font_create(). The
2482 * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
2483 * also for the FreeType backend and can be used with functions such
2484 * as cairo_ft_scaled_font_lock_face().
2486 * Font rendering options are represented both here and when you
2487 * call cairo_scaled_font_create(). Font options that have a representation
2488 * in a #FcPattern must be passed in here; to modify #FcPattern
2489 * appropriately to reflect the options in a #cairo_font_options_t, call
2490 * cairo_ft_font_options_substitute().
2492 * Return value: a newly created #cairo_font_face_t. Free with
2493 * cairo_font_face_destroy() when you are done using it.
2495 cairo_font_face_t *
2496 cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
2498 cairo_ft_unscaled_font_t *unscaled;
2499 cairo_font_face_t *font_face;
2500 cairo_ft_options_t ft_options;
2502 unscaled = _cairo_ft_unscaled_font_create_for_pattern (pattern);
2503 if (unscaled == NULL) {
2504 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
2505 return (cairo_font_face_t *)&_cairo_font_face_nil;
2508 _get_pattern_ft_options (pattern, &ft_options);
2509 font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
2510 _cairo_unscaled_font_destroy (&unscaled->base);
2512 return font_face;
2516 * cairo_ft_font_face_create_for_ft_face:
2517 * @face: A FreeType face object, already opened. This must
2518 * be kept around until the face's ref_count drops to
2519 * zero and it is freed. Since the face may be referenced
2520 * internally to Cairo, the best way to determine when it
2521 * is safe to free the face is to pass a
2522 * #cairo_destroy_func_t to cairo_font_face_set_user_data()
2523 * @load_flags: flags to pass to FT_Load_Glyph when loading
2524 * glyphs from the font. These flags are OR'ed together with
2525 * the flags derived from the #cairo_font_options_t passed
2526 * to cairo_scaled_font_create(), so only a few values such
2527 * as %FT_LOAD_VERTICAL_LAYOUT, and %FT_LOAD_FORCE_AUTOHINT
2528 * are useful. You should not pass any of the flags affecting
2529 * the load target, such as %FT_LOAD_TARGET_LIGHT.
2531 * Creates a new font face for the FreeType font backend from a
2532 * pre-opened FreeType face. This font can then be used with
2533 * cairo_set_font_face() or cairo_scaled_font_create(). The
2534 * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
2535 * also for the FreeType backend and can be used with functions such
2536 * as cairo_ft_scaled_font_lock_face().
2538 * As an example, here is how one might correctly couple the lifetime of
2539 * the FreeType face object to the #cairo_font_face_t:
2541 * <informalexample><programlisting>
2542 * static const cairo_user_data_key_t key;
2544 * font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
2545 * status = cairo_font_face_set_user_data (font_face, &key,
2546 * ft_face, (cairo_destroy_func_t) FT_Done_Face);
2547 * if (status) {
2548 * cairo_font_face_destroy (font_face);
2549 * FT_Done_Face (ft_face);
2550 * return ERROR;
2552 * </programlisting></informalexample>
2554 * Return value: a newly created #cairo_font_face_t. Free with
2555 * cairo_font_face_destroy() when you are done using it.
2557 cairo_font_face_t *
2558 cairo_ft_font_face_create_for_ft_face (FT_Face face,
2559 int load_flags)
2561 cairo_ft_unscaled_font_t *unscaled;
2562 cairo_font_face_t *font_face;
2563 cairo_ft_options_t ft_options;
2565 unscaled = _cairo_ft_unscaled_font_create_from_face (face);
2566 if (unscaled == NULL) {
2567 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
2568 return (cairo_font_face_t *)&_cairo_font_face_nil;
2571 ft_options.load_flags = load_flags;
2572 ft_options.extra_flags = 0;
2573 _cairo_font_options_init_default (&ft_options.base);
2575 font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
2576 _cairo_unscaled_font_destroy (&unscaled->base);
2578 return font_face;
2582 * cairo_ft_scaled_font_lock_face:
2583 * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
2584 * object can be created by calling cairo_scaled_font_create() on a
2585 * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
2586 * cairo_ft_font_face_create_for_ft_face()).
2588 * cairo_ft_scaled_font_lock_face() gets the #FT_Face object from a FreeType
2589 * backend font and scales it appropriately for the font. You must
2590 * release the face with cairo_ft_scaled_font_unlock_face()
2591 * when you are done using it. Since the #FT_Face object can be
2592 * shared between multiple #cairo_scaled_font_t objects, you must not
2593 * lock any other font objects until you unlock this one. A count is
2594 * kept of the number of times cairo_ft_scaled_font_lock_face() is
2595 * called. cairo_ft_scaled_font_unlock_face() must be called the same number
2596 * of times.
2598 * You must be careful when using this function in a library or in a
2599 * threaded application, because freetype's design makes it unsafe to
2600 * call freetype functions simultaneously from multiple threads, (even
2601 * if using distinct FT_Face objects). Because of this, application
2602 * code that acquires an FT_Face object with this call must add it's
2603 * own locking to protect any use of that object, (and which also must
2604 * protect any other calls into cairo as almost any cairo function
2605 * might result in a call into the freetype library).
2607 * Return value: The #FT_Face object for @font, scaled appropriately,
2608 * or %NULL if @scaled_font is in an error state (see
2609 * cairo_scaled_font_status()) or there is insufficient memory.
2611 FT_Face
2612 cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
2614 cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
2615 FT_Face face;
2616 cairo_status_t status;
2618 if (scaled_font->base.status)
2619 return NULL;
2621 face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
2622 if (face == NULL) {
2623 status = _cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
2624 return NULL;
2627 status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
2628 &scaled_font->base.scale);
2629 if (status) {
2630 _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
2631 status = _cairo_scaled_font_set_error (&scaled_font->base, status);
2632 return NULL;
2635 /* Note: We deliberately release the unscaled font's mutex here,
2636 * so that we are not holding a lock across two separate calls to
2637 * cairo function, (which would give the application some
2638 * opportunity for creating deadlock. This is obviously unsafe,
2639 * but as documented, the user must add manual locking when using
2640 * this function. */
2641 CAIRO_MUTEX_UNLOCK (scaled_font->unscaled->mutex);
2643 return face;
2647 * cairo_ft_scaled_font_unlock_face:
2648 * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
2649 * object can be created by calling cairo_scaled_font_create() on a
2650 * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
2651 * cairo_ft_font_face_create_for_ft_face()).
2653 * Releases a face obtained with cairo_ft_scaled_font_lock_face().
2655 void
2656 cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
2658 cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
2660 if (scaled_font->base.status)
2661 return;
2663 /* Note: We released the unscaled font's mutex at the end of
2664 * cairo_ft_scaled_font_lock_face, so we have to acquire it again
2665 * as _cairo_ft_unscaled_font_unlock_face expects it to be held
2666 * when we call into it. */
2667 CAIRO_MUTEX_LOCK (scaled_font->unscaled->mutex);
2669 _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
2672 /* We expose our unscaled font implementation internally for the the
2673 * PDF backend, which needs to keep track of the the different
2674 * fonts-on-disk used by a document, so it can embed them.
2676 cairo_unscaled_font_t *
2677 _cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t *abstract_font)
2679 cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
2681 return &scaled_font->unscaled->base;
2684 cairo_bool_t
2685 _cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font)
2687 cairo_ft_scaled_font_t *ft_scaled_font;
2689 if (!_cairo_scaled_font_is_ft (scaled_font))
2690 return FALSE;
2692 ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
2693 if (ft_scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)
2694 return TRUE;
2695 return FALSE;
2698 void
2699 _cairo_ft_font_reset_static_data (void)
2701 _cairo_ft_unscaled_font_map_destroy ();