* MoonlightTypeConverter.cs: Convert CacheMode's from strings.
[moon.git] / cairo / src / cairo-ft-font.c
blobcd1125325bde443351b50d001497d742b12b626e
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
4 * Copyright © 2000 Keith Packard
5 * Copyright © 2005 Red Hat, Inc
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.
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 * You should have received a copy of the MPL along with this library
19 * in the file COPYING-MPL-1.1
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/
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.
30 * The Original Code is the cairo graphics library.
32 * The Initial Developer of the Original Code is Red Hat, Inc.
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>
41 #define _BSD_SOURCE /* for strdup() */
42 #include "cairoint.h"
44 #include "cairo-ft-private.h"
46 #include <float.h>
48 #include <fontconfig/fontconfig.h>
49 #include <fontconfig/fcfreetype.h>
51 #include <ft2build.h>
52 #include FT_FREETYPE_H
53 #include FT_OUTLINE_H
54 #include FT_IMAGE_H
55 #include FT_TRUETYPE_TABLES_H
56 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
57 #include FT_SYNTHESIS_H
58 #endif
60 #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
61 #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
62 #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
63 #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
65 /* This is the max number of FT_face objects we keep open at once
67 #define MAX_OPEN_FACES 10
70 * The simple 2x2 matrix is converted into separate scale and shape
71 * factors so that hinting works right
74 typedef struct _cairo_ft_font_transform {
75 double x_scale, y_scale;
76 double shape[2][2];
77 } cairo_ft_font_transform_t;
80 * We create an object that corresponds to a single font on the disk;
81 * (identified by a filename/id pair) these are shared between all
82 * fonts using that file. For cairo_ft_font_face_create_for_ft_face(), we
83 * just create a one-off version with a permanent face value.
86 typedef struct _cairo_ft_font_face cairo_ft_font_face_t;
88 struct _cairo_ft_unscaled_font {
89 cairo_unscaled_font_t base;
91 cairo_bool_t from_face; /* was the FT_Face provided by user? */
92 FT_Face face; /* provided or cached face */
94 /* only set if from_face is false */
95 char *filename;
96 int id;
98 /* We temporarily scale the unscaled font as needed */
99 cairo_bool_t have_scale;
100 cairo_matrix_t current_scale;
101 double x_scale; /* Extracted X scale factor */
102 double y_scale; /* Extracted Y scale factor */
103 cairo_bool_t have_shape; /* true if the current scale has a non-scale component*/
104 cairo_matrix_t current_shape;
105 FT_Matrix Current_Shape;
107 cairo_mutex_t mutex;
108 int lock_count;
110 cairo_ft_font_face_t *faces; /* Linked list of faces for this font */
113 static int
114 _cairo_ft_unscaled_font_keys_equal (const void *key_a,
115 const void *key_b);
117 static void
118 _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled);
120 static cairo_status_t
121 _cairo_ft_font_options_substitute (const cairo_font_options_t *options,
122 FcPattern *pattern);
124 typedef enum _cairo_ft_extra_flags {
125 CAIRO_FT_OPTIONS_HINT_METRICS = (1 << 0),
126 CAIRO_FT_OPTIONS_EMBOLDEN = (1 << 1)
127 } cairo_ft_extra_flags_t;
129 typedef struct _cairo_ft_options {
130 cairo_font_options_t base;
131 int load_flags; /* flags for FT_Load_Glyph */
132 cairo_ft_extra_flags_t extra_flags; /* other flags that affect results */
133 } cairo_ft_options_t;
135 struct _cairo_ft_font_face {
136 cairo_font_face_t base;
137 cairo_ft_unscaled_font_t *unscaled;
138 cairo_ft_options_t ft_options;
139 cairo_ft_font_face_t *next;
142 static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend;
145 * We maintain a hash table to map file/id => #cairo_ft_unscaled_font_t.
146 * The hash table itself isn't limited in size. However, we limit the
147 * number of FT_Face objects we keep around; when we've exceeded that
148 * limit and need to create a new FT_Face, we dump the FT_Face from a
149 * random #cairo_ft_unscaled_font_t which has an unlocked FT_Face, (if
150 * there are any).
153 typedef struct _cairo_ft_unscaled_font_map {
154 cairo_hash_table_t *hash_table;
155 FT_Library ft_library;
156 int num_open_faces;
157 } cairo_ft_unscaled_font_map_t;
159 static cairo_ft_unscaled_font_map_t *cairo_ft_unscaled_font_map = NULL;
161 static void
162 _font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t *font_map,
163 cairo_ft_unscaled_font_t *unscaled)
165 if (unscaled->face) {
166 FT_Done_Face (unscaled->face);
167 unscaled->face = NULL;
168 unscaled->have_scale = FALSE;
170 font_map->num_open_faces--;
174 static void
175 _cairo_ft_unscaled_font_map_create (void)
177 cairo_ft_unscaled_font_map_t *font_map;
179 /* This function is only intended to be called from
180 * _cairo_ft_unscaled_font_map_lock. So we'll crash if we can
181 * detect some other call path. */
182 assert (cairo_ft_unscaled_font_map == NULL);
184 font_map = malloc (sizeof (cairo_ft_unscaled_font_map_t));
185 if (font_map == NULL) {
186 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
187 goto FAIL;
190 font_map->hash_table =
191 _cairo_hash_table_create (_cairo_ft_unscaled_font_keys_equal);
193 if (font_map->hash_table == NULL)
194 goto FAIL;
196 if (FT_Init_FreeType (&font_map->ft_library))
197 goto FAIL;
199 font_map->num_open_faces = 0;
201 cairo_ft_unscaled_font_map = font_map;
202 return;
204 FAIL:
205 if (font_map) {
206 if (font_map->hash_table)
207 _cairo_hash_table_destroy (font_map->hash_table);
208 free (font_map);
210 cairo_ft_unscaled_font_map = NULL;
213 static void
214 _cairo_ft_unscaled_font_map_destroy (void)
216 cairo_ft_unscaled_font_t *unscaled;
217 cairo_ft_unscaled_font_map_t *font_map;
219 CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
221 if (cairo_ft_unscaled_font_map) {
222 font_map = cairo_ft_unscaled_font_map;
224 /* This is rather inefficient, but destroying the hash table
225 * is something we only do during debugging, (during
226 * cairo_debug_reset_static_data), when efficiency is not
227 * relevant. */
228 while (1) {
229 unscaled = _cairo_hash_table_random_entry (font_map->hash_table,
230 NULL);
231 if (unscaled == NULL)
232 break;
233 _cairo_hash_table_remove (font_map->hash_table,
234 &unscaled->base.hash_entry);
236 _font_map_release_face_lock_held (font_map, unscaled);
237 _cairo_ft_unscaled_font_fini (unscaled);
238 free (unscaled);
241 assert (font_map->num_open_faces == 0);
243 FT_Done_FreeType (font_map->ft_library);
245 _cairo_hash_table_destroy (font_map->hash_table);
247 free (font_map);
249 cairo_ft_unscaled_font_map = NULL;
252 CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
255 static cairo_ft_unscaled_font_map_t *
256 _cairo_ft_unscaled_font_map_lock (void)
258 CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex);
260 if (cairo_ft_unscaled_font_map == NULL)
262 _cairo_ft_unscaled_font_map_create ();
264 if (cairo_ft_unscaled_font_map == NULL) {
265 CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
266 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
267 return NULL;
271 return cairo_ft_unscaled_font_map;
274 static void
275 _cairo_ft_unscaled_font_map_unlock (void)
277 CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex);
280 static void
281 _cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t *key,
282 cairo_bool_t from_face,
283 char *filename,
284 int id,
285 FT_Face face)
287 unsigned long hash;
289 key->from_face = from_face;
290 key->filename = filename;
291 key->id = id;
292 key->face = face;
294 hash = _cairo_hash_string (filename);
295 /* the constants are just arbitrary primes */
296 hash += ((unsigned long) id) * 1607;
297 hash += ((unsigned long) face) * 2137;
299 key->base.hash_entry.hash = hash;
303 * _cairo_ft_unscaled_font_init:
305 * Initialize a #cairo_ft_unscaled_font_t.
307 * There are two basic flavors of #cairo_ft_unscaled_font_t, one
308 * created from an FT_Face and the other created from a filename/id
309 * pair. These two flavors are identified as from_face and !from_face.
311 * To initialize a from_face font, pass filename==%NULL, id=0 and the
312 * desired face.
314 * To initialize a !from_face font, pass the filename/id as desired
315 * and face==%NULL.
317 * Note that the code handles these two flavors in very distinct
318 * ways. For example there is a hash_table mapping
319 * filename/id->#cairo_unscaled_font_t in the !from_face case, but no
320 * parallel in the from_face case, (where the calling code would have
321 * to do its own mapping to ensure similar sharing).
323 static cairo_status_t
324 _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t *unscaled,
325 cairo_bool_t from_face,
326 const char *filename,
327 int id,
328 FT_Face face)
330 _cairo_unscaled_font_init (&unscaled->base,
331 &cairo_ft_unscaled_font_backend);
333 if (from_face) {
334 unscaled->from_face = TRUE;
335 _cairo_ft_unscaled_font_init_key (unscaled, TRUE, NULL, 0, face);
336 } else {
337 char *filename_copy;
339 unscaled->from_face = FALSE;
340 unscaled->face = NULL;
342 filename_copy = strdup (filename);
343 if (filename_copy == NULL)
344 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
345 _cairo_ft_unscaled_font_init_key (unscaled, FALSE, filename_copy, id, NULL);
348 unscaled->have_scale = FALSE;
349 CAIRO_MUTEX_INIT (unscaled->mutex);
350 unscaled->lock_count = 0;
352 unscaled->faces = NULL;
354 return CAIRO_STATUS_SUCCESS;
358 * _cairo_ft_unscaled_font_fini:
360 * Free all data associated with a #cairo_ft_unscaled_font_t.
362 * CAUTION: The unscaled->face field must be %NULL before calling this
363 * function. This is because the #cairo_ft_unscaled_font_t_map keeps a
364 * count of these faces (font_map->num_open_faces) so it maintains the
365 * unscaled->face field while it has its lock held. See
366 * _font_map_release_face_lock_held().
368 static void
369 _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t *unscaled)
371 assert (unscaled->face == NULL);
373 if (unscaled->filename) {
374 free (unscaled->filename);
375 unscaled->filename = NULL;
378 CAIRO_MUTEX_FINI (unscaled->mutex);
381 static int
382 _cairo_ft_unscaled_font_keys_equal (const void *key_a,
383 const void *key_b)
385 const cairo_ft_unscaled_font_t *unscaled_a = key_a;
386 const cairo_ft_unscaled_font_t *unscaled_b = key_b;
388 if (unscaled_a->id == unscaled_b->id &&
389 unscaled_a->from_face == unscaled_b->from_face)
391 if (unscaled_a->from_face)
392 return unscaled_a->face == unscaled_b->face;
394 if (unscaled_a->filename == NULL && unscaled_b->filename == NULL)
395 return TRUE;
396 else if (unscaled_a->filename == NULL || unscaled_b->filename == NULL)
397 return FALSE;
398 else
399 return (strcmp (unscaled_a->filename, unscaled_b->filename) == 0);
402 return FALSE;
405 /* Finds or creates a #cairo_ft_unscaled_font_t for the filename/id from
406 * pattern. Returns a new reference to the unscaled font.
408 static cairo_ft_unscaled_font_t *
409 _cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face,
410 char *filename,
411 int id,
412 FT_Face font_face)
414 cairo_ft_unscaled_font_t key, *unscaled;
415 cairo_ft_unscaled_font_map_t *font_map;
416 cairo_status_t status;
418 font_map = _cairo_ft_unscaled_font_map_lock ();
419 if (font_map == NULL)
420 goto UNWIND;
422 _cairo_ft_unscaled_font_init_key (&key, from_face, filename, id, font_face);
424 /* Return existing unscaled font if it exists in the hash table. */
425 if (_cairo_hash_table_lookup (font_map->hash_table, &key.base.hash_entry,
426 (cairo_hash_entry_t **) &unscaled))
428 _cairo_unscaled_font_reference (&unscaled->base);
429 _cairo_ft_unscaled_font_map_unlock ();
430 return unscaled;
433 /* Otherwise create it and insert into hash table. */
434 unscaled = malloc (sizeof (cairo_ft_unscaled_font_t));
435 if (unscaled == NULL) {
436 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
437 goto UNWIND_FONT_MAP_LOCK;
440 status = _cairo_ft_unscaled_font_init (unscaled, from_face, filename, id, font_face);
441 if (status)
442 goto UNWIND_UNSCALED_MALLOC;
444 status = _cairo_hash_table_insert (font_map->hash_table,
445 &unscaled->base.hash_entry);
446 if (status)
447 goto UNWIND_UNSCALED_FONT_INIT;
449 _cairo_ft_unscaled_font_map_unlock ();
451 return unscaled;
453 UNWIND_UNSCALED_FONT_INIT:
454 _cairo_ft_unscaled_font_fini (unscaled);
455 UNWIND_UNSCALED_MALLOC:
456 free (unscaled);
457 UNWIND_FONT_MAP_LOCK:
458 _cairo_ft_unscaled_font_map_unlock ();
459 UNWIND:
460 return NULL;
464 static cairo_ft_unscaled_font_t *
465 _cairo_ft_unscaled_font_create_for_pattern (FcPattern *pattern)
467 FT_Face font_face = NULL;
468 char *filename = NULL;
469 int id = 0;
471 if (FcPatternGetFTFace (pattern, FC_FT_FACE, 0, &font_face) != FcResultMatch) {
472 FcChar8 *fc_filename = NULL;
474 if (FcPatternGetString (pattern, FC_FILE, 0, &fc_filename) != FcResultMatch)
475 goto UNWIND;
476 filename = (char *) fc_filename;
478 if (FcPatternGetInteger (pattern, FC_INDEX, 0, &id) != FcResultMatch)
479 goto UNWIND;
482 return _cairo_ft_unscaled_font_create_internal (font_face != NULL, filename, id, font_face);
484 UNWIND:
485 return NULL;
488 static cairo_ft_unscaled_font_t *
489 _cairo_ft_unscaled_font_create_from_face (FT_Face face)
491 return _cairo_ft_unscaled_font_create_internal (TRUE, NULL, 0, face);
494 static void
495 _cairo_ft_unscaled_font_destroy (void *abstract_font)
497 cairo_ft_unscaled_font_t *unscaled = abstract_font;
498 cairo_ft_unscaled_font_map_t *font_map;
500 if (unscaled == NULL)
501 return;
503 font_map = _cairo_ft_unscaled_font_map_lock ();
504 /* All created objects must have been mapped in the font map. */
505 assert (font_map != NULL);
507 _cairo_hash_table_remove (font_map->hash_table,
508 &unscaled->base.hash_entry);
510 if (unscaled->from_face) {
511 /* See comments in _ft_font_face_destroy about the "zombie" state
512 * for a _ft_font_face.
514 if (unscaled->faces && !unscaled->faces->unscaled)
515 cairo_font_face_destroy (&unscaled->faces->base);
516 } else {
517 _font_map_release_face_lock_held (font_map, unscaled);
519 unscaled->face = NULL;
521 _cairo_ft_unscaled_font_map_unlock ();
523 _cairo_ft_unscaled_font_fini (unscaled);
526 static cairo_bool_t
527 _has_unlocked_face (void *entry)
529 cairo_ft_unscaled_font_t *unscaled = entry;
531 return (unscaled->lock_count == 0 && unscaled->face);
534 /* Ensures that an unscaled font has a face object. If we exceed
535 * MAX_OPEN_FACES, try to close some.
537 * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
538 * set the scale on the face, but just returns it at the last scale.
540 cairo_warn FT_Face
541 _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t *unscaled)
543 cairo_ft_unscaled_font_map_t *font_map;
544 FT_Face face = NULL;
546 CAIRO_MUTEX_LOCK (unscaled->mutex);
547 unscaled->lock_count++;
549 if (unscaled->face)
550 return unscaled->face;
552 /* If this unscaled font was created from an FT_Face then we just
553 * returned it above. */
554 assert (!unscaled->from_face);
556 font_map = _cairo_ft_unscaled_font_map_lock ();
558 assert (font_map != NULL);
560 while (font_map->num_open_faces >= MAX_OPEN_FACES)
562 cairo_ft_unscaled_font_t *entry;
564 entry = _cairo_hash_table_random_entry (font_map->hash_table,
565 _has_unlocked_face);
566 if (entry == NULL)
567 break;
569 _font_map_release_face_lock_held (font_map, entry);
572 _cairo_ft_unscaled_font_map_unlock ();
574 if (FT_New_Face (font_map->ft_library,
575 unscaled->filename,
576 unscaled->id,
577 &face) != FT_Err_Ok)
579 unscaled->lock_count--;
580 CAIRO_MUTEX_UNLOCK (unscaled->mutex);
581 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
582 return NULL;
585 unscaled->face = face;
587 font_map->num_open_faces++;
589 return face;
593 /* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face
595 void
596 _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t *unscaled)
598 assert (unscaled->lock_count > 0);
600 unscaled->lock_count--;
602 CAIRO_MUTEX_UNLOCK (unscaled->mutex);
606 static cairo_status_t
607 _compute_transform (cairo_ft_font_transform_t *sf,
608 cairo_matrix_t *scale)
610 cairo_status_t status;
611 double x_scale, y_scale;
612 cairo_matrix_t normalized = *scale;
614 /* The font matrix has x and y "scale" components which we extract and
615 * use as character scale values. These influence the way freetype
616 * chooses hints, as well as selecting different bitmaps in
617 * hand-rendered fonts. We also copy the normalized matrix to
618 * freetype's transformation.
621 status = _cairo_matrix_compute_basis_scale_factors (scale,
622 &x_scale, &y_scale,
624 if (status)
625 return status;
627 /* FreeType docs say this about x_scale and y_scale:
628 * "A character width or height smaller than 1pt is set to 1pt;"
629 * So, we cap them from below at 1.0 and let the FT transform
630 * take care of sub-1.0 scaling. */
631 if (x_scale < 1.0)
632 x_scale = 1.0;
633 if (y_scale < 1.0)
634 y_scale = 1.0;
636 sf->x_scale = x_scale;
637 sf->y_scale = y_scale;
639 cairo_matrix_scale (&normalized, 1.0 / x_scale, 1.0 / y_scale);
641 _cairo_matrix_get_affine (&normalized,
642 &sf->shape[0][0], &sf->shape[0][1],
643 &sf->shape[1][0], &sf->shape[1][1],
644 NULL, NULL);
646 return CAIRO_STATUS_SUCCESS;
649 /* Temporarily scales an unscaled font to the give scale. We catch
650 * scaling to the same size, since changing a FT_Face is expensive.
652 static cairo_status_t
653 _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t *unscaled,
654 cairo_matrix_t *scale)
656 cairo_status_t status;
657 cairo_ft_font_transform_t sf;
658 FT_Matrix mat;
659 FT_Error error;
661 assert (unscaled->face != NULL);
663 if (unscaled->have_scale &&
664 scale->xx == unscaled->current_scale.xx &&
665 scale->yx == unscaled->current_scale.yx &&
666 scale->xy == unscaled->current_scale.xy &&
667 scale->yy == unscaled->current_scale.yy)
668 return CAIRO_STATUS_SUCCESS;
670 unscaled->have_scale = TRUE;
671 unscaled->current_scale = *scale;
673 status = _compute_transform (&sf, scale);
674 if (status)
675 return status;
677 unscaled->x_scale = sf.x_scale;
678 unscaled->y_scale = sf.y_scale;
680 mat.xx = DOUBLE_TO_16_16(sf.shape[0][0]);
681 mat.yx = - DOUBLE_TO_16_16(sf.shape[0][1]);
682 mat.xy = - DOUBLE_TO_16_16(sf.shape[1][0]);
683 mat.yy = DOUBLE_TO_16_16(sf.shape[1][1]);
685 unscaled->have_shape = (mat.xx != 0x10000 ||
686 mat.yx != 0x00000 ||
687 mat.xy != 0x00000 ||
688 mat.yy != 0x10000);
690 unscaled->Current_Shape = mat;
691 cairo_matrix_init (&unscaled->current_shape,
692 sf.shape[0][0], sf.shape[0][1],
693 sf.shape[1][0], sf.shape[1][1],
694 0.0, 0.0);
696 FT_Set_Transform(unscaled->face, &mat, NULL);
698 if ((unscaled->face->face_flags & FT_FACE_FLAG_SCALABLE) != 0) {
699 error = FT_Set_Char_Size (unscaled->face,
700 sf.x_scale * 64.0 + .5,
701 sf.y_scale * 64.0 + .5,
702 0, 0);
703 if (error)
704 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
705 } else {
706 double min_distance = DBL_MAX;
707 int i;
708 int best_i = 0;
710 for (i = 0; i < unscaled->face->num_fixed_sizes; i++) {
711 #if HAVE_FT_BITMAP_SIZE_Y_PPEM
712 double size = unscaled->face->available_sizes[i].y_ppem / 64.;
713 #else
714 double size = unscaled->face->available_sizes[i].height;
715 #endif
716 double distance = fabs (size - sf.y_scale);
718 if (distance <= min_distance) {
719 min_distance = distance;
720 best_i = i;
723 #if HAVE_FT_BITMAP_SIZE_Y_PPEM
724 error = FT_Set_Char_Size (unscaled->face,
725 unscaled->face->available_sizes[best_i].x_ppem,
726 unscaled->face->available_sizes[best_i].y_ppem,
727 0, 0);
728 if (error)
729 #endif
730 error = FT_Set_Pixel_Sizes (unscaled->face,
731 unscaled->face->available_sizes[best_i].width,
732 unscaled->face->available_sizes[best_i].height);
733 if (error)
734 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
737 return CAIRO_STATUS_SUCCESS;
740 /* Empirically-derived subpixel filtering values thanks to Keith
741 * Packard and libXft. */
742 static const int filters[3][3] = {
743 /* red */
744 #if 0
745 { 65538*4/7,65538*2/7,65538*1/7 },
746 /* green */
747 { 65536*1/4, 65536*2/4, 65537*1/4 },
748 /* blue */
749 { 65538*1/7,65538*2/7,65538*4/7 },
750 #endif
751 { 65538*9/13,65538*3/13,65538*1/13 },
752 /* green */
753 { 65538*1/6, 65538*4/6, 65538*1/6 },
754 /* blue */
755 { 65538*1/13,65538*3/13,65538*9/13 },
758 /* Fills in val->image with an image surface created from @bitmap
760 static cairo_status_t
761 _get_bitmap_surface (FT_Bitmap *bitmap,
762 cairo_bool_t own_buffer,
763 cairo_font_options_t *font_options,
764 cairo_image_surface_t **surface)
766 int width, height, stride;
767 unsigned char *data;
768 int format = CAIRO_FORMAT_A8;
769 cairo_bool_t subpixel = FALSE;
771 width = bitmap->width;
772 height = bitmap->rows;
774 if (width == 0 || height == 0) {
775 *surface = (cairo_image_surface_t *)
776 cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
777 return (*surface)->base.status;
780 switch (bitmap->pixel_mode) {
781 case FT_PIXEL_MODE_MONO:
782 stride = (((width + 31) & ~31) >> 3);
783 if (own_buffer) {
784 data = bitmap->buffer;
785 assert (stride == bitmap->pitch);
786 } else {
787 data = _cairo_malloc_ab (height, stride);
788 if (!data)
789 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
791 if (stride == bitmap->pitch) {
792 memcpy (data, bitmap->buffer, stride * height);
793 } else {
794 int i;
795 unsigned char *source, *dest;
797 source = bitmap->buffer;
798 dest = data;
799 for (i = height; i; i--) {
800 memcpy (dest, source, bitmap->pitch);
801 memset (dest + bitmap->pitch, '\0', stride - bitmap->pitch);
803 source += bitmap->pitch;
804 dest += stride;
809 #ifndef WORDS_BIGENDIAN
811 uint8_t *d = data;
812 int count = stride * height;
814 while (count--) {
815 *d = CAIRO_BITSWAP8 (*d);
816 d++;
819 #endif
820 format = CAIRO_FORMAT_A1;
821 break;
823 case FT_PIXEL_MODE_LCD:
824 case FT_PIXEL_MODE_LCD_V:
825 case FT_PIXEL_MODE_GRAY:
826 switch (font_options->antialias) {
827 case CAIRO_ANTIALIAS_DEFAULT:
828 case CAIRO_ANTIALIAS_GRAY:
829 case CAIRO_ANTIALIAS_NONE:
830 default:
831 stride = bitmap->pitch;
832 if (own_buffer) {
833 data = bitmap->buffer;
834 } else {
835 data = _cairo_malloc_ab (height, stride);
836 if (!data)
837 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
839 memcpy (data, bitmap->buffer, stride * height);
841 format = CAIRO_FORMAT_A8;
842 break;
843 case CAIRO_ANTIALIAS_SUBPIXEL: {
844 int x, y;
845 unsigned char *in_line, *out_line, *in;
846 unsigned int *out;
847 unsigned int red, green, blue;
848 int rf, gf, bf;
849 int s;
850 int o, os;
851 unsigned char *data_rgba;
852 unsigned int width_rgba, stride_rgba;
853 int vmul = 1;
854 int hmul = 1;
856 switch (font_options->subpixel_order) {
857 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
858 case CAIRO_SUBPIXEL_ORDER_RGB:
859 case CAIRO_SUBPIXEL_ORDER_BGR:
860 default:
861 width /= 3;
862 hmul = 3;
863 break;
864 case CAIRO_SUBPIXEL_ORDER_VRGB:
865 case CAIRO_SUBPIXEL_ORDER_VBGR:
866 vmul = 3;
867 height /= 3;
868 break;
871 * Filter the glyph to soften the color fringes
873 width_rgba = width;
874 stride = bitmap->pitch;
875 stride_rgba = (width_rgba * 4 + 3) & ~3;
876 data_rgba = calloc (stride_rgba, height);
877 if (data_rgba == NULL) {
878 if (own_buffer)
879 free (bitmap->buffer);
880 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
883 os = 1;
884 switch (font_options->subpixel_order) {
885 case CAIRO_SUBPIXEL_ORDER_VRGB:
886 os = stride;
887 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
888 case CAIRO_SUBPIXEL_ORDER_RGB:
889 default:
890 rf = 0;
891 gf = 1;
892 bf = 2;
893 break;
894 case CAIRO_SUBPIXEL_ORDER_VBGR:
895 os = stride;
896 case CAIRO_SUBPIXEL_ORDER_BGR:
897 bf = 0;
898 gf = 1;
899 rf = 2;
900 break;
902 in_line = bitmap->buffer;
903 out_line = data_rgba;
904 for (y = 0; y < height; y++)
906 in = in_line;
907 out = (unsigned int *) out_line;
908 in_line += stride * vmul;
909 out_line += stride_rgba;
910 for (x = 0; x < width * hmul; x += hmul)
912 red = green = blue = 0;
913 o = 0;
914 for (s = 0; s < 3; s++)
916 red += filters[rf][s]*in[x+o];
917 green += filters[gf][s]*in[x+o];
918 blue += filters[bf][s]*in[x+o];
919 o += os;
921 red = red / 65536;
922 green = green / 65536;
923 blue = blue / 65536;
924 *out++ = (green << 24) | (red << 16) | (green << 8) | blue;
928 /* Images here are stored in native format. The
929 * backend must convert to its own format as needed
932 if (own_buffer)
933 free (bitmap->buffer);
934 data = data_rgba;
935 stride = stride_rgba;
936 format = CAIRO_FORMAT_ARGB32;
937 subpixel = TRUE;
938 break;
941 break;
942 case FT_PIXEL_MODE_GRAY2:
943 case FT_PIXEL_MODE_GRAY4:
944 /* These could be triggered by very rare types of TrueType fonts */
945 default:
946 if (own_buffer)
947 free (bitmap->buffer);
948 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
951 *surface = (cairo_image_surface_t *)
952 cairo_image_surface_create_for_data (data,
953 format,
954 width, height, stride);
955 if ((*surface)->base.status) {
956 free (data);
957 return (*surface)->base.status;
960 if (subpixel)
961 pixman_image_set_component_alpha ((*surface)->pixman_image, TRUE);
963 _cairo_image_surface_assume_ownership_of_data ((*surface));
965 return CAIRO_STATUS_SUCCESS;
968 /* Converts an outline FT_GlyphSlot into an image
970 * This could go through _render_glyph_bitmap as well, letting
971 * FreeType convert the outline to a bitmap, but doing it ourselves
972 * has two minor advantages: first, we save a copy of the bitmap
973 * buffer: we can directly use the buffer that FreeType renders
974 * into.
976 * Second, it may help when we add support for subpixel
977 * rendering: the Xft code does it this way. (Keith thinks that
978 * it may also be possible to get the subpixel rendering with
979 * FT_Render_Glyph: something worth looking into in more detail
980 * when we add subpixel support. If so, we may want to eliminate
981 * this version of the code path entirely.
983 static cairo_status_t
984 _render_glyph_outline (FT_Face face,
985 cairo_font_options_t *font_options,
986 cairo_image_surface_t **surface)
988 FT_GlyphSlot glyphslot = face->glyph;
989 FT_Outline *outline = &glyphslot->outline;
990 FT_Bitmap bitmap;
991 FT_BBox cbox;
992 FT_Matrix matrix;
993 int hmul = 1;
994 int vmul = 1;
995 unsigned int width, height, stride;
996 cairo_bool_t subpixel = FALSE;
997 cairo_status_t status;
999 FT_Outline_Get_CBox (outline, &cbox);
1001 cbox.xMin &= -64;
1002 cbox.yMin &= -64;
1003 cbox.xMax = (cbox.xMax + 63) & -64;
1004 cbox.yMax = (cbox.yMax + 63) & -64;
1006 width = (unsigned int) ((cbox.xMax - cbox.xMin) >> 6);
1007 height = (unsigned int) ((cbox.yMax - cbox.yMin) >> 6);
1008 stride = (width * hmul + 3) & ~3;
1010 if (width * height == 0) {
1011 cairo_format_t format;
1012 /* Looks like fb handles zero-sized images just fine */
1013 switch (font_options->antialias) {
1014 case CAIRO_ANTIALIAS_NONE:
1015 format = CAIRO_FORMAT_A1;
1016 break;
1017 case CAIRO_ANTIALIAS_SUBPIXEL:
1018 format= CAIRO_FORMAT_ARGB32;
1019 break;
1020 case CAIRO_ANTIALIAS_DEFAULT:
1021 case CAIRO_ANTIALIAS_GRAY:
1022 default:
1023 format = CAIRO_FORMAT_A8;
1024 break;
1027 (*surface) = (cairo_image_surface_t *)
1028 cairo_image_surface_create_for_data (NULL, format, 0, 0, 0);
1029 if ((*surface)->base.status)
1030 return (*surface)->base.status;
1031 } else {
1033 matrix.xx = matrix.yy = 0x10000L;
1034 matrix.xy = matrix.yx = 0;
1036 switch (font_options->antialias) {
1037 case CAIRO_ANTIALIAS_NONE:
1038 bitmap.pixel_mode = FT_PIXEL_MODE_MONO;
1039 bitmap.num_grays = 1;
1040 stride = ((width + 31) & -32) >> 3;
1041 break;
1042 case CAIRO_ANTIALIAS_DEFAULT:
1043 case CAIRO_ANTIALIAS_GRAY:
1044 bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
1045 bitmap.num_grays = 256;
1046 stride = (width + 3) & -4;
1047 break;
1048 case CAIRO_ANTIALIAS_SUBPIXEL:
1049 switch (font_options->subpixel_order) {
1050 case CAIRO_SUBPIXEL_ORDER_RGB:
1051 case CAIRO_SUBPIXEL_ORDER_BGR:
1052 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1053 default:
1054 matrix.xx *= 3;
1055 hmul = 3;
1056 subpixel = TRUE;
1057 break;
1058 case CAIRO_SUBPIXEL_ORDER_VRGB:
1059 case CAIRO_SUBPIXEL_ORDER_VBGR:
1060 matrix.yy *= 3;
1061 vmul = 3;
1062 subpixel = TRUE;
1063 break;
1065 FT_Outline_Transform (outline, &matrix);
1067 bitmap.pixel_mode = FT_PIXEL_MODE_GRAY;
1068 bitmap.num_grays = 256;
1069 stride = (width * hmul + 3) & -4;
1072 bitmap.pitch = stride;
1073 bitmap.width = width * hmul;
1074 bitmap.rows = height * vmul;
1075 bitmap.buffer = calloc (stride, bitmap.rows);
1076 if (bitmap.buffer == NULL)
1077 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1079 FT_Outline_Translate (outline, -cbox.xMin*hmul, -cbox.yMin*vmul);
1081 if (FT_Outline_Get_Bitmap (glyphslot->library, outline, &bitmap) != 0) {
1082 free (bitmap.buffer);
1083 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1086 status = _get_bitmap_surface (&bitmap, TRUE, font_options, surface);
1087 if (status)
1088 return status;
1092 * Note: the font's coordinate system is upside down from ours, so the
1093 * Y coordinate of the control box needs to be negated. Moreover, device
1094 * offsets are position of glyph origin relative to top left while xMin
1095 * and yMax are offsets of top left relative to origin. Another negation.
1097 cairo_surface_set_device_offset (&(*surface)->base,
1098 floor (-(double) cbox.xMin / 64.0),
1099 floor (+(double) cbox.yMax / 64.0));
1101 return CAIRO_STATUS_SUCCESS;
1104 /* Converts a bitmap (or other) FT_GlyphSlot into an image */
1105 static cairo_status_t
1106 _render_glyph_bitmap (FT_Face face,
1107 cairo_font_options_t *font_options,
1108 cairo_image_surface_t **surface)
1110 FT_GlyphSlot glyphslot = face->glyph;
1111 cairo_status_t status = CAIRO_STATUS_SUCCESS;
1112 FT_Error error;
1114 /* According to the FreeType docs, glyphslot->format could be
1115 * something other than FT_GLYPH_FORMAT_OUTLINE or
1116 * FT_GLYPH_FORMAT_BITMAP. Calling FT_Render_Glyph gives FreeType
1117 * the opportunity to convert such to
1118 * bitmap. FT_GLYPH_FORMAT_COMPOSITE will not be encountered since
1119 * we avoid the FT_LOAD_NO_RECURSE flag.
1121 error = FT_Render_Glyph (glyphslot, FT_RENDER_MODE_NORMAL);
1122 /* XXX ignoring all other errors for now. They are not fatal, typically
1123 * just a glyph-not-found. */
1124 if (error == FT_Err_Out_Of_Memory)
1125 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1127 status = _get_bitmap_surface (&glyphslot->bitmap, FALSE, font_options, surface);
1128 if (status)
1129 return status;
1132 * Note: the font's coordinate system is upside down from ours, so the
1133 * Y coordinate of the control box needs to be negated. Moreover, device
1134 * offsets are position of glyph origin relative to top left while
1135 * bitmap_left and bitmap_top are offsets of top left relative to origin.
1136 * Another negation.
1138 cairo_surface_set_device_offset (&(*surface)->base,
1139 -glyphslot->bitmap_left,
1140 +glyphslot->bitmap_top);
1142 return status;
1145 static cairo_status_t
1146 _transform_glyph_bitmap (cairo_matrix_t * shape,
1147 cairo_image_surface_t ** surface)
1149 cairo_matrix_t original_to_transformed;
1150 cairo_matrix_t transformed_to_original;
1151 cairo_image_surface_t *old_image;
1152 cairo_surface_t *image;
1153 double x[4], y[4];
1154 double origin_x, origin_y;
1155 int orig_width, orig_height;
1156 int i;
1157 int x_min, y_min, x_max, y_max;
1158 int width, height;
1159 cairo_status_t status;
1160 cairo_surface_pattern_t pattern;
1162 /* We want to compute a transform that takes the origin
1163 * (device_x_offset, device_y_offset) to 0,0, then applies
1164 * the "shape" portion of the font transform
1166 original_to_transformed = *shape;
1168 cairo_surface_get_device_offset (&(*surface)->base, &origin_x, &origin_y);
1169 orig_width = cairo_image_surface_get_width (&(*surface)->base);
1170 orig_height = cairo_image_surface_get_height (&(*surface)->base);
1172 cairo_matrix_translate (&original_to_transformed,
1173 -origin_x, -origin_y);
1175 /* Find the bounding box of the original bitmap under that
1176 * transform
1178 x[0] = 0; y[0] = 0;
1179 x[1] = orig_width; y[1] = 0;
1180 x[2] = orig_width; y[2] = orig_height;
1181 x[3] = 0; y[3] = orig_height;
1183 for (i = 0; i < 4; i++)
1184 cairo_matrix_transform_point (&original_to_transformed,
1185 &x[i], &y[i]);
1187 x_min = floor (x[0]); y_min = floor (y[0]);
1188 x_max = ceil (x[0]); y_max = ceil (y[0]);
1190 for (i = 1; i < 4; i++) {
1191 if (x[i] < x_min)
1192 x_min = floor (x[i]);
1193 else if (x[i] > x_max)
1194 x_max = ceil (x[i]);
1195 if (y[i] < y_min)
1196 y_min = floor (y[i]);
1197 else if (y[i] > y_max)
1198 y_max = ceil (y[i]);
1201 /* Adjust the transform so that the bounding box starts at 0,0 ...
1202 * this gives our final transform from original bitmap to transformed
1203 * bitmap.
1205 original_to_transformed.x0 -= x_min;
1206 original_to_transformed.y0 -= y_min;
1208 /* Create the transformed bitmap
1210 width = x_max - x_min;
1211 height = y_max - y_min;
1213 transformed_to_original = original_to_transformed;
1214 status = cairo_matrix_invert (&transformed_to_original);
1215 if (status)
1216 return status;
1218 /* We need to pad out the width to 32-bit intervals for cairo-xlib-surface.c */
1219 width = (width + 3) & ~3;
1220 image = cairo_image_surface_create (CAIRO_FORMAT_A8, width, height);
1221 if (image->status)
1222 return image->status;
1224 /* Initialize it to empty
1226 status = _cairo_surface_fill_rectangle (image, CAIRO_OPERATOR_CLEAR,
1227 CAIRO_COLOR_TRANSPARENT,
1228 0, 0,
1229 width, height);
1230 if (status) {
1231 cairo_surface_destroy (image);
1232 return status;
1235 /* Draw the original bitmap transformed into the new bitmap
1237 _cairo_pattern_init_for_surface (&pattern, &(*surface)->base);
1238 cairo_pattern_set_matrix (&pattern.base, &transformed_to_original);
1240 status = _cairo_surface_composite (CAIRO_OPERATOR_OVER,
1241 &pattern.base, NULL, image,
1242 0, 0, 0, 0, 0, 0,
1243 width,
1244 height);
1246 _cairo_pattern_fini (&pattern.base);
1248 if (status) {
1249 cairo_surface_destroy (image);
1250 return status;
1253 /* Now update the cache entry for the new bitmap, recomputing
1254 * the origin based on the final transform.
1256 cairo_matrix_transform_point (&original_to_transformed,
1257 &origin_x, &origin_y);
1259 old_image = (*surface);
1260 (*surface) = (cairo_image_surface_t *)image;
1261 cairo_surface_destroy (&old_image->base);
1263 cairo_surface_set_device_offset (&(*surface)->base,
1264 _cairo_lround (origin_x),
1265 _cairo_lround (origin_y));
1266 return status;
1269 static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend = {
1270 _cairo_ft_unscaled_font_destroy,
1271 #if 0
1272 _cairo_ft_unscaled_font_create_glyph
1273 #endif
1276 /* #cairo_ft_scaled_font_t */
1278 typedef struct _cairo_ft_scaled_font {
1279 cairo_scaled_font_t base;
1280 cairo_ft_unscaled_font_t *unscaled;
1281 cairo_ft_options_t ft_options;
1282 } cairo_ft_scaled_font_t;
1284 const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend;
1286 /* The load flags passed to FT_Load_Glyph control aspects like hinting and
1287 * antialiasing. Here we compute them from the fields of a FcPattern.
1289 static void
1290 _get_pattern_ft_options (FcPattern *pattern, cairo_ft_options_t *ret)
1292 FcBool antialias, vertical_layout, hinting, autohint, bitmap, embolden;
1293 cairo_ft_options_t ft_options;
1294 int rgba;
1295 #ifdef FC_HINT_STYLE
1296 int hintstyle;
1297 #endif
1299 _cairo_font_options_init_default (&ft_options.base);
1300 ft_options.load_flags = FT_LOAD_DEFAULT;
1301 ft_options.extra_flags = 0;
1303 #ifndef FC_EMBEDDED_BITMAP
1304 #define FC_EMBEDDED_BITMAP "embeddedbitmap"
1305 #endif
1307 /* Check whether to force use of embedded bitmaps */
1308 if (FcPatternGetBool (pattern,
1309 FC_EMBEDDED_BITMAP, 0, &bitmap) != FcResultMatch)
1310 bitmap = FcFalse;
1312 /* disable antialiasing if requested */
1313 if (FcPatternGetBool (pattern,
1314 FC_ANTIALIAS, 0, &antialias) != FcResultMatch)
1315 antialias = FcTrue;
1317 if (antialias) {
1318 cairo_subpixel_order_t subpixel_order;
1320 /* disable hinting if requested */
1321 if (FcPatternGetBool (pattern,
1322 FC_HINTING, 0, &hinting) != FcResultMatch)
1323 hinting = FcTrue;
1325 if (FcPatternGetInteger (pattern,
1326 FC_RGBA, 0, &rgba) != FcResultMatch)
1327 rgba = FC_RGBA_UNKNOWN;
1329 switch (rgba) {
1330 case FC_RGBA_RGB:
1331 subpixel_order = CAIRO_SUBPIXEL_ORDER_RGB;
1332 break;
1333 case FC_RGBA_BGR:
1334 subpixel_order = CAIRO_SUBPIXEL_ORDER_BGR;
1335 break;
1336 case FC_RGBA_VRGB:
1337 subpixel_order = CAIRO_SUBPIXEL_ORDER_VRGB;
1338 break;
1339 case FC_RGBA_VBGR:
1340 subpixel_order = CAIRO_SUBPIXEL_ORDER_VBGR;
1341 break;
1342 case FC_RGBA_UNKNOWN:
1343 case FC_RGBA_NONE:
1344 default:
1345 subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
1346 break;
1349 if (subpixel_order != CAIRO_SUBPIXEL_ORDER_DEFAULT) {
1350 ft_options.base.subpixel_order = subpixel_order;
1351 ft_options.base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
1354 #ifdef FC_HINT_STYLE
1355 if (FcPatternGetInteger (pattern,
1356 FC_HINT_STYLE, 0, &hintstyle) != FcResultMatch)
1357 hintstyle = FC_HINT_FULL;
1359 if (!hinting)
1360 hintstyle = FC_HINT_NONE;
1362 switch (hintstyle) {
1363 case FC_HINT_NONE:
1364 ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
1365 break;
1366 case FC_HINT_SLIGHT:
1367 ft_options.base.hint_style = CAIRO_HINT_STYLE_SLIGHT;
1368 break;
1369 case FC_HINT_MEDIUM:
1370 default:
1371 ft_options.base.hint_style = CAIRO_HINT_STYLE_MEDIUM;
1372 break;
1373 case FC_HINT_FULL:
1374 ft_options.base.hint_style = CAIRO_HINT_STYLE_FULL;
1375 break;
1377 #else /* !FC_HINT_STYLE */
1378 if (!hinting) {
1379 ft_options.base.hint_style = CAIRO_HINT_STYLE_NONE;
1381 #endif /* FC_HINT_STYLE */
1383 /* Force embedded bitmaps off if no hinting requested */
1384 if (ft_options.base.hint_style == CAIRO_HINT_STYLE_NONE)
1385 bitmap = FcFalse;
1387 if (!bitmap)
1388 ft_options.load_flags |= FT_LOAD_NO_BITMAP;
1390 } else {
1391 ft_options.base.antialias = CAIRO_ANTIALIAS_NONE;
1394 /* force autohinting if requested */
1395 if (FcPatternGetBool (pattern,
1396 FC_AUTOHINT, 0, &autohint) != FcResultMatch)
1397 autohint = FcFalse;
1399 if (autohint)
1400 ft_options.load_flags |= FT_LOAD_FORCE_AUTOHINT;
1402 if (FcPatternGetBool (pattern,
1403 FC_VERTICAL_LAYOUT, 0, &vertical_layout) != FcResultMatch)
1404 vertical_layout = FcFalse;
1406 if (vertical_layout)
1407 ft_options.load_flags |= FT_LOAD_VERTICAL_LAYOUT;
1409 #ifndef FC_EMBOLDEN
1410 #define FC_EMBOLDEN "embolden"
1411 #endif
1412 if (FcPatternGetBool (pattern,
1413 FC_EMBOLDEN, 0, &embolden) != FcResultMatch)
1414 embolden = FcFalse;
1416 if (embolden)
1417 ft_options.extra_flags |= CAIRO_FT_OPTIONS_EMBOLDEN;
1419 *ret = ft_options;
1422 static void
1423 _cairo_ft_options_merge (cairo_ft_options_t *options,
1424 cairo_ft_options_t *other)
1426 int load_flags = other->load_flags;
1427 int load_target = FT_LOAD_TARGET_NORMAL;
1429 /* clear load target mode */
1430 load_flags &= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(other->load_flags)));
1432 if (load_flags & FT_LOAD_NO_HINTING)
1433 other->base.hint_style = CAIRO_HINT_STYLE_NONE;
1435 if (other->base.antialias == CAIRO_ANTIALIAS_NONE ||
1436 options->base.antialias == CAIRO_ANTIALIAS_NONE) {
1437 options->base.antialias = CAIRO_ANTIALIAS_NONE;
1438 options->base.subpixel_order = CAIRO_SUBPIXEL_ORDER_DEFAULT;
1441 if (other->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL &&
1442 (options->base.antialias == CAIRO_ANTIALIAS_DEFAULT ||
1443 options->base.antialias == CAIRO_ANTIALIAS_GRAY)) {
1444 options->base.antialias = CAIRO_ANTIALIAS_SUBPIXEL;
1445 options->base.subpixel_order = other->base.subpixel_order;
1448 if (options->base.hint_style == CAIRO_HINT_STYLE_DEFAULT)
1449 options->base.hint_style = other->base.hint_style;
1451 if (other->base.hint_style == CAIRO_HINT_STYLE_NONE)
1452 options->base.hint_style = CAIRO_HINT_STYLE_NONE;
1454 if (options->base.antialias == CAIRO_ANTIALIAS_NONE) {
1455 if (options->base.hint_style == CAIRO_HINT_STYLE_NONE)
1456 load_flags |= FT_LOAD_NO_HINTING;
1457 else
1458 load_target = FT_LOAD_TARGET_MONO;
1459 load_flags |= FT_LOAD_MONOCHROME;
1460 } else {
1461 switch (options->base.hint_style) {
1462 case CAIRO_HINT_STYLE_NONE:
1463 load_flags |= FT_LOAD_NO_HINTING;
1464 break;
1465 case CAIRO_HINT_STYLE_SLIGHT:
1466 load_target = FT_LOAD_TARGET_LIGHT;
1467 break;
1468 case CAIRO_HINT_STYLE_MEDIUM:
1469 break;
1470 case CAIRO_HINT_STYLE_FULL:
1471 case CAIRO_HINT_STYLE_DEFAULT:
1472 if (options->base.antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
1473 switch (options->base.subpixel_order) {
1474 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
1475 case CAIRO_SUBPIXEL_ORDER_RGB:
1476 case CAIRO_SUBPIXEL_ORDER_BGR:
1477 load_target |= FT_LOAD_TARGET_LCD;
1478 break;
1479 case CAIRO_SUBPIXEL_ORDER_VRGB:
1480 case CAIRO_SUBPIXEL_ORDER_VBGR:
1481 load_target |= FT_LOAD_TARGET_LCD_V;
1482 break;
1485 break;
1489 options->load_flags = load_flags | load_target;
1490 options->extra_flags = other->extra_flags;
1491 if (options->base.hint_metrics != CAIRO_HINT_METRICS_OFF)
1492 options->extra_flags |= CAIRO_FT_OPTIONS_HINT_METRICS;
1495 static cairo_status_t
1496 _cairo_ft_scaled_font_create (cairo_ft_unscaled_font_t *unscaled,
1497 cairo_font_face_t *font_face,
1498 const cairo_matrix_t *font_matrix,
1499 const cairo_matrix_t *ctm,
1500 const cairo_font_options_t *options,
1501 cairo_ft_options_t ft_options,
1502 cairo_scaled_font_t **font_out)
1504 cairo_ft_scaled_font_t *scaled_font;
1505 FT_Face face;
1506 FT_Size_Metrics *metrics;
1507 cairo_font_extents_t fs_metrics;
1508 cairo_status_t status;
1510 face = _cairo_ft_unscaled_font_lock_face (unscaled);
1511 if (!face)
1512 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1514 scaled_font = malloc (sizeof(cairo_ft_scaled_font_t));
1515 if (scaled_font == NULL) {
1516 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1517 goto FAIL;
1520 _cairo_unscaled_font_reference (&unscaled->base);
1521 scaled_font->unscaled = unscaled;
1523 _cairo_font_options_init_copy (&scaled_font->ft_options.base, options);
1524 _cairo_ft_options_merge (&scaled_font->ft_options, &ft_options);
1526 status = _cairo_scaled_font_init (&scaled_font->base,
1527 font_face,
1528 font_matrix, ctm, options,
1529 &_cairo_ft_scaled_font_backend);
1530 if (status) {
1531 _cairo_unscaled_font_destroy (&unscaled->base);
1532 free (scaled_font);
1533 goto FAIL;
1536 status = _cairo_ft_unscaled_font_set_scale (unscaled,
1537 &scaled_font->base.scale);
1538 if (status) {
1539 _cairo_unscaled_font_destroy (&unscaled->base);
1540 free (scaled_font);
1541 goto FAIL;
1545 metrics = &face->size->metrics;
1548 * Get to unscaled metrics so that the upper level can get back to
1549 * user space
1551 * Also use this path for bitmap-only fonts. The other branch uses
1552 * face members that are only relevant for scalable fonts. This is
1553 * detected by simply checking for units_per_EM==0.
1555 if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF ||
1556 face->units_per_EM == 0) {
1557 double x_factor, y_factor;
1559 if (unscaled->x_scale == 0)
1560 x_factor = 0;
1561 else
1562 x_factor = 1 / unscaled->x_scale;
1564 if (unscaled->y_scale == 0)
1565 y_factor = 0;
1566 else
1567 y_factor = 1 / unscaled->y_scale;
1569 fs_metrics.ascent = DOUBLE_FROM_26_6(metrics->ascender) * y_factor;
1570 fs_metrics.descent = DOUBLE_FROM_26_6(- metrics->descender) * y_factor;
1571 fs_metrics.height = DOUBLE_FROM_26_6(metrics->height) * y_factor;
1572 if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
1573 fs_metrics.max_x_advance = DOUBLE_FROM_26_6(metrics->max_advance) * x_factor;
1574 fs_metrics.max_y_advance = 0;
1575 } else {
1576 fs_metrics.max_x_advance = 0;
1577 fs_metrics.max_y_advance = DOUBLE_FROM_26_6(metrics->max_advance) * y_factor;
1579 } else {
1580 double scale = face->units_per_EM;
1582 fs_metrics.ascent = face->ascender / scale;
1583 fs_metrics.descent = - face->descender / scale;
1584 fs_metrics.height = face->height / scale;
1585 if (!_cairo_ft_scaled_font_is_vertical (&scaled_font->base)) {
1586 fs_metrics.max_x_advance = face->max_advance_width / scale;
1587 fs_metrics.max_y_advance = 0;
1588 } else {
1589 fs_metrics.max_x_advance = 0;
1590 fs_metrics.max_y_advance = face->max_advance_height / scale;
1594 status = _cairo_scaled_font_set_metrics (&scaled_font->base, &fs_metrics);
1596 *font_out = &scaled_font->base;
1598 FAIL:
1599 _cairo_ft_unscaled_font_unlock_face (unscaled);
1601 return status;
1604 cairo_bool_t
1605 _cairo_scaled_font_is_ft (cairo_scaled_font_t *scaled_font)
1607 return scaled_font->backend == &_cairo_ft_scaled_font_backend;
1610 static cairo_status_t
1611 _cairo_ft_scaled_font_create_toy (cairo_toy_font_face_t *toy_face,
1612 const cairo_matrix_t *font_matrix,
1613 const cairo_matrix_t *ctm,
1614 const cairo_font_options_t *font_options,
1615 cairo_scaled_font_t **font)
1617 FcPattern *pattern, *resolved;
1618 cairo_ft_unscaled_font_t *unscaled;
1619 FcResult result;
1620 int fcslant;
1621 int fcweight;
1622 cairo_matrix_t scale;
1623 cairo_status_t status;
1624 cairo_ft_font_transform_t sf;
1625 cairo_ft_options_t ft_options;
1627 cairo_matrix_multiply (&scale, font_matrix, ctm);
1628 status = _compute_transform (&sf, &scale);
1629 if (status)
1630 return status;
1632 pattern = FcPatternCreate ();
1633 if (!pattern)
1634 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1636 if (!FcPatternAddString (pattern,
1637 FC_FAMILY, (unsigned char *) toy_face->family))
1639 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1640 goto FREE_PATTERN;
1643 switch (toy_face->slant)
1645 case CAIRO_FONT_SLANT_ITALIC:
1646 fcslant = FC_SLANT_ITALIC;
1647 break;
1648 case CAIRO_FONT_SLANT_OBLIQUE:
1649 fcslant = FC_SLANT_OBLIQUE;
1650 break;
1651 case CAIRO_FONT_SLANT_NORMAL:
1652 default:
1653 fcslant = FC_SLANT_ROMAN;
1654 break;
1657 if (!FcPatternAddInteger (pattern, FC_SLANT, fcslant)) {
1658 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1659 goto FREE_PATTERN;
1662 switch (toy_face->weight)
1664 case CAIRO_FONT_WEIGHT_BOLD:
1665 fcweight = FC_WEIGHT_BOLD;
1666 break;
1667 case CAIRO_FONT_WEIGHT_NORMAL:
1668 default:
1669 fcweight = FC_WEIGHT_MEDIUM;
1670 break;
1673 if (!FcPatternAddInteger (pattern, FC_WEIGHT, fcweight)) {
1674 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1675 goto FREE_PATTERN;
1678 if (! FcPatternAddDouble (pattern, FC_PIXEL_SIZE, sf.y_scale)) {
1679 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1680 goto FREE_PATTERN;
1683 if (! FcConfigSubstitute (NULL, pattern, FcMatchPattern)) {
1684 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1685 goto FREE_PATTERN;
1688 status = _cairo_ft_font_options_substitute (font_options, pattern);
1689 if (status)
1690 goto FREE_PATTERN;
1692 FcDefaultSubstitute (pattern);
1694 resolved = FcFontMatch (NULL, pattern, &result);
1695 if (!resolved) {
1696 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1697 goto FREE_PATTERN;
1700 unscaled = _cairo_ft_unscaled_font_create_for_pattern (resolved);
1701 if (!unscaled) {
1702 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1703 goto FREE_RESOLVED;
1706 _get_pattern_ft_options (resolved, &ft_options);
1708 status = _cairo_ft_scaled_font_create (unscaled,
1709 &toy_face->base,
1710 font_matrix, ctm,
1711 font_options, ft_options,
1712 font);
1714 _cairo_unscaled_font_destroy (&unscaled->base);
1716 FREE_RESOLVED:
1717 FcPatternDestroy (resolved);
1719 FREE_PATTERN:
1720 FcPatternDestroy (pattern);
1722 return status;
1725 static void
1726 _cairo_ft_scaled_font_fini (void *abstract_font)
1728 cairo_ft_scaled_font_t *scaled_font = abstract_font;
1730 if (scaled_font == NULL)
1731 return;
1733 _cairo_unscaled_font_destroy (&scaled_font->unscaled->base);
1736 static int
1737 _move_to (FT_Vector *to, void *closure)
1739 cairo_path_fixed_t *path = closure;
1740 cairo_fixed_t x, y;
1742 x = _cairo_fixed_from_26_6 (to->x);
1743 y = _cairo_fixed_from_26_6 (to->y);
1745 if (_cairo_path_fixed_close_path (path) != CAIRO_STATUS_SUCCESS)
1746 return 1;
1747 if (_cairo_path_fixed_move_to (path, x, y) != CAIRO_STATUS_SUCCESS)
1748 return 1;
1750 return 0;
1753 static int
1754 _line_to (FT_Vector *to, void *closure)
1756 cairo_path_fixed_t *path = closure;
1757 cairo_fixed_t x, y;
1759 x = _cairo_fixed_from_26_6 (to->x);
1760 y = _cairo_fixed_from_26_6 (to->y);
1762 if (_cairo_path_fixed_line_to (path, x, y) != CAIRO_STATUS_SUCCESS)
1763 return 1;
1765 return 0;
1768 static int
1769 _conic_to (FT_Vector *control, FT_Vector *to, void *closure)
1771 cairo_path_fixed_t *path = closure;
1773 cairo_fixed_t x0, y0;
1774 cairo_fixed_t x1, y1;
1775 cairo_fixed_t x2, y2;
1776 cairo_fixed_t x3, y3;
1777 cairo_point_t conic;
1779 if (! _cairo_path_fixed_get_current_point (path, &x0, &y0))
1780 return 1;
1782 conic.x = _cairo_fixed_from_26_6 (control->x);
1783 conic.y = _cairo_fixed_from_26_6 (control->y);
1785 x3 = _cairo_fixed_from_26_6 (to->x);
1786 y3 = _cairo_fixed_from_26_6 (to->y);
1788 x1 = x0 + 2.0/3.0 * (conic.x - x0);
1789 y1 = y0 + 2.0/3.0 * (conic.y - y0);
1791 x2 = x3 + 2.0/3.0 * (conic.x - x3);
1792 y2 = y3 + 2.0/3.0 * (conic.y - y3);
1794 if (_cairo_path_fixed_curve_to (path,
1795 x1, y1,
1796 x2, y2,
1797 x3, y3) != CAIRO_STATUS_SUCCESS)
1798 return 1;
1800 return 0;
1803 static int
1804 _cubic_to (FT_Vector *control1, FT_Vector *control2,
1805 FT_Vector *to, void *closure)
1807 cairo_path_fixed_t *path = closure;
1808 cairo_fixed_t x0, y0;
1809 cairo_fixed_t x1, y1;
1810 cairo_fixed_t x2, y2;
1812 x0 = _cairo_fixed_from_26_6 (control1->x);
1813 y0 = _cairo_fixed_from_26_6 (control1->y);
1815 x1 = _cairo_fixed_from_26_6 (control2->x);
1816 y1 = _cairo_fixed_from_26_6 (control2->y);
1818 x2 = _cairo_fixed_from_26_6 (to->x);
1819 y2 = _cairo_fixed_from_26_6 (to->y);
1821 if (_cairo_path_fixed_curve_to (path,
1822 x0, y0,
1823 x1, y1,
1824 x2, y2) != CAIRO_STATUS_SUCCESS)
1825 return 1;
1827 return 0;
1830 static cairo_status_t
1831 _decompose_glyph_outline (FT_Face face,
1832 cairo_font_options_t *options,
1833 cairo_path_fixed_t **pathp)
1835 static const FT_Outline_Funcs outline_funcs = {
1836 (FT_Outline_MoveToFunc)_move_to,
1837 (FT_Outline_LineToFunc)_line_to,
1838 (FT_Outline_ConicToFunc)_conic_to,
1839 (FT_Outline_CubicToFunc)_cubic_to,
1840 0, /* shift */
1841 0, /* delta */
1843 static const FT_Matrix invert_y = {
1844 DOUBLE_TO_16_16 (1.0), 0,
1845 0, DOUBLE_TO_16_16 (-1.0),
1848 FT_GlyphSlot glyph;
1849 cairo_path_fixed_t *path;
1850 cairo_status_t status;
1852 path = _cairo_path_fixed_create ();
1853 if (!path)
1854 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1856 glyph = face->glyph;
1858 /* Font glyphs have an inverted Y axis compared to cairo. */
1859 FT_Outline_Transform (&glyph->outline, &invert_y);
1860 if (FT_Outline_Decompose (&glyph->outline, &outline_funcs, path)) {
1861 _cairo_path_fixed_destroy (path);
1862 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1865 status = _cairo_path_fixed_close_path (path);
1866 if (status) {
1867 _cairo_path_fixed_destroy (path);
1868 return status;
1871 *pathp = path;
1873 return CAIRO_STATUS_SUCCESS;
1877 * Translate glyph to match its metrics.
1879 static void
1880 _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (void *abstract_font,
1881 FT_GlyphSlot glyph)
1883 cairo_ft_scaled_font_t *scaled_font = abstract_font;
1884 FT_Vector vector;
1886 vector.x = glyph->metrics.vertBearingX - glyph->metrics.horiBearingX;
1887 vector.y = -glyph->metrics.vertBearingY - glyph->metrics.horiBearingY;
1889 if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
1890 FT_Vector_Transform (&vector, &scaled_font->unscaled->Current_Shape);
1891 FT_Outline_Translate(&glyph->outline, vector.x, vector.y);
1892 } else if (glyph->format == FT_GLYPH_FORMAT_BITMAP) {
1893 glyph->bitmap_left += vector.x / 64;
1894 glyph->bitmap_top += vector.y / 64;
1898 static cairo_int_status_t
1899 _cairo_ft_scaled_glyph_init (void *abstract_font,
1900 cairo_scaled_glyph_t *scaled_glyph,
1901 cairo_scaled_glyph_info_t info)
1903 cairo_text_extents_t fs_metrics;
1904 cairo_ft_scaled_font_t *scaled_font = abstract_font;
1905 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
1906 FT_GlyphSlot glyph;
1907 FT_Face face;
1908 FT_Error error;
1909 int load_flags = scaled_font->ft_options.load_flags;
1910 FT_Glyph_Metrics *metrics;
1911 double x_factor, y_factor;
1912 cairo_bool_t vertical_layout = FALSE;
1913 cairo_status_t status;
1915 face = _cairo_ft_unscaled_font_lock_face (unscaled);
1916 if (!face)
1917 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
1919 status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
1920 &scaled_font->base.scale);
1921 if (status)
1922 goto FAIL;
1924 /* Ignore global advance unconditionally */
1925 load_flags |= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH;
1927 if ((info & CAIRO_SCALED_GLYPH_INFO_PATH) != 0 &&
1928 (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) == 0)
1929 load_flags |= FT_LOAD_NO_BITMAP;
1932 * Don't pass FT_LOAD_VERTICAL_LAYOUT to FT_Load_Glyph here as
1933 * suggested by freetype people.
1935 if (load_flags & FT_LOAD_VERTICAL_LAYOUT) {
1936 load_flags &= ~FT_LOAD_VERTICAL_LAYOUT;
1937 vertical_layout = TRUE;
1940 error = FT_Load_Glyph (scaled_font->unscaled->face,
1941 _cairo_scaled_glyph_index(scaled_glyph),
1942 load_flags);
1943 /* XXX ignoring all other errors for now. They are not fatal, typically
1944 * just a glyph-not-found. */
1945 if (error == FT_Err_Out_Of_Memory) {
1946 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
1947 goto FAIL;
1950 glyph = face->glyph;
1952 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
1954 * embolden glyphs if requested
1956 if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN)
1957 FT_GlyphSlot_Embolden (glyph);
1958 #endif
1960 if (vertical_layout)
1961 _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph);
1963 if (info & CAIRO_SCALED_GLYPH_INFO_METRICS) {
1965 cairo_bool_t hint_metrics = scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF;
1967 * Compute font-space metrics
1969 metrics = &glyph->metrics;
1971 if (unscaled->x_scale == 0)
1972 x_factor = 0;
1973 else
1974 x_factor = 1 / unscaled->x_scale;
1976 if (unscaled->y_scale == 0)
1977 y_factor = 0;
1978 else
1979 y_factor = 1 / unscaled->y_scale;
1982 * Note: Y coordinates of the horizontal bearing need to be negated.
1984 * Scale metrics back to glyph space from the scaled glyph space returned
1985 * by FreeType
1987 * If we want hinted metrics but aren't asking for hinted glyphs from
1988 * FreeType, then we need to do the metric hinting ourselves.
1991 if (hint_metrics && (load_flags & FT_LOAD_NO_HINTING))
1993 FT_Pos x1, x2;
1994 FT_Pos y1, y2;
1995 FT_Pos advance;
1997 if (!vertical_layout) {
1998 x1 = (metrics->horiBearingX) & -64;
1999 x2 = (metrics->horiBearingX + metrics->width + 63) & -64;
2000 y1 = (-metrics->horiBearingY) & -64;
2001 y2 = (-metrics->horiBearingY + metrics->height + 63) & -64;
2003 advance = ((metrics->horiAdvance + 32) & -64);
2005 fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor;
2006 fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor;
2008 fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor;
2009 fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
2011 fs_metrics.x_advance = DOUBLE_FROM_26_6 (advance) * x_factor;
2012 fs_metrics.y_advance = 0;
2013 } else {
2014 x1 = (metrics->vertBearingX) & -64;
2015 x2 = (metrics->vertBearingX + metrics->width + 63) & -64;
2016 y1 = (metrics->vertBearingY) & -64;
2017 y2 = (metrics->vertBearingY + metrics->height + 63) & -64;
2019 advance = ((metrics->vertAdvance + 32) & -64);
2021 fs_metrics.x_bearing = DOUBLE_FROM_26_6 (x1) * x_factor;
2022 fs_metrics.y_bearing = DOUBLE_FROM_26_6 (y1) * y_factor;
2024 fs_metrics.width = DOUBLE_FROM_26_6 (x2 - x1) * x_factor;
2025 fs_metrics.height = DOUBLE_FROM_26_6 (y2 - y1) * y_factor;
2027 fs_metrics.x_advance = 0;
2028 fs_metrics.y_advance = DOUBLE_FROM_26_6 (advance) * y_factor;
2030 } else {
2031 fs_metrics.width = DOUBLE_FROM_26_6 (metrics->width) * x_factor;
2032 fs_metrics.height = DOUBLE_FROM_26_6 (metrics->height) * y_factor;
2034 if (!vertical_layout) {
2035 fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->horiBearingX) * x_factor;
2036 fs_metrics.y_bearing = DOUBLE_FROM_26_6 (-metrics->horiBearingY) * y_factor;
2038 if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
2039 fs_metrics.x_advance = DOUBLE_FROM_26_6 (metrics->horiAdvance) * x_factor;
2040 else
2041 fs_metrics.x_advance = DOUBLE_FROM_16_16 (glyph->linearHoriAdvance) * x_factor;
2042 fs_metrics.y_advance = 0 * y_factor;
2043 } else {
2044 fs_metrics.x_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingX) * x_factor;
2045 fs_metrics.y_bearing = DOUBLE_FROM_26_6 (metrics->vertBearingY) * y_factor;
2047 fs_metrics.x_advance = 0 * x_factor;
2048 if (hint_metrics || glyph->format != FT_GLYPH_FORMAT_OUTLINE)
2049 fs_metrics.y_advance = DOUBLE_FROM_26_6 (metrics->vertAdvance) * y_factor;
2050 else
2051 fs_metrics.y_advance = DOUBLE_FROM_26_6 (glyph->linearVertAdvance) * y_factor;
2055 _cairo_scaled_glyph_set_metrics (scaled_glyph,
2056 &scaled_font->base,
2057 &fs_metrics);
2060 if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
2061 cairo_image_surface_t *surface;
2063 if (glyph->format == FT_GLYPH_FORMAT_OUTLINE) {
2064 status = _render_glyph_outline (face, &scaled_font->ft_options.base,
2065 &surface);
2066 } else {
2067 status = _render_glyph_bitmap (face, &scaled_font->ft_options.base,
2068 &surface);
2069 if (status == CAIRO_STATUS_SUCCESS && unscaled->have_shape) {
2070 status = _transform_glyph_bitmap (&unscaled->current_shape,
2071 &surface);
2072 if (status)
2073 cairo_surface_destroy (&surface->base);
2076 if (status)
2077 goto FAIL;
2079 _cairo_scaled_glyph_set_surface (scaled_glyph,
2080 &scaled_font->base,
2081 surface);
2084 if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
2085 cairo_path_fixed_t *path = NULL; /* hide compiler warning */
2088 * A kludge -- the above code will trash the outline,
2089 * so reload it. This will probably never occur though
2091 if ((info & CAIRO_SCALED_GLYPH_INFO_SURFACE) != 0) {
2092 error = FT_Load_Glyph (face,
2093 _cairo_scaled_glyph_index(scaled_glyph),
2094 load_flags | FT_LOAD_NO_BITMAP);
2095 /* XXX ignoring all other errors for now. They are not fatal, typically
2096 * just a glyph-not-found. */
2097 if (error == FT_Err_Out_Of_Memory) {
2098 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2099 goto FAIL;
2101 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
2103 * embolden glyphs if requested
2105 if (scaled_font->ft_options.extra_flags & CAIRO_FT_OPTIONS_EMBOLDEN)
2106 FT_GlyphSlot_Embolden (glyph);
2107 #endif
2108 if (vertical_layout)
2109 _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font, glyph);
2112 if (glyph->format == FT_GLYPH_FORMAT_OUTLINE)
2113 status = _decompose_glyph_outline (face, &scaled_font->ft_options.base,
2114 &path);
2115 else
2116 status = CAIRO_INT_STATUS_UNSUPPORTED;
2118 if (status)
2119 goto FAIL;
2121 _cairo_scaled_glyph_set_path (scaled_glyph,
2122 &scaled_font->base,
2123 path);
2125 FAIL:
2126 _cairo_ft_unscaled_font_unlock_face (unscaled);
2128 return status;
2131 static unsigned long
2132 _cairo_ft_ucs4_to_index (void *abstract_font,
2133 uint32_t ucs4)
2135 cairo_ft_scaled_font_t *scaled_font = abstract_font;
2136 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
2137 FT_Face face;
2138 FT_UInt index;
2140 face = _cairo_ft_unscaled_font_lock_face (unscaled);
2141 if (!face)
2142 return 0;
2144 /* If making this compile without fontconfig, use:
2145 * index = FT_Get_Char_Index (face, ucs4); */
2146 index = FcFreeTypeCharIndex (face, ucs4);
2148 _cairo_ft_unscaled_font_unlock_face (unscaled);
2149 return index;
2152 static cairo_int_status_t
2153 _cairo_ft_load_truetype_table (void *abstract_font,
2154 unsigned long tag,
2155 long offset,
2156 unsigned char *buffer,
2157 unsigned long *length)
2159 cairo_ft_scaled_font_t *scaled_font = abstract_font;
2160 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
2161 FT_Face face;
2162 cairo_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
2164 if (_cairo_ft_scaled_font_is_vertical (&scaled_font->base))
2165 return CAIRO_INT_STATUS_UNSUPPORTED;
2167 #if HAVE_FT_LOAD_SFNT_TABLE
2168 face = _cairo_ft_unscaled_font_lock_face (unscaled);
2169 if (!face)
2170 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2172 if (FT_IS_SFNT (face) &&
2173 FT_Load_Sfnt_Table (face, tag, offset, buffer, length) == 0)
2174 status = CAIRO_STATUS_SUCCESS;
2176 _cairo_ft_unscaled_font_unlock_face (unscaled);
2177 #endif
2179 return status;
2182 static cairo_int_status_t
2183 _cairo_ft_index_to_ucs4(void *abstract_font,
2184 unsigned long index,
2185 uint32_t *ucs4)
2187 cairo_ft_scaled_font_t *scaled_font = abstract_font;
2188 cairo_ft_unscaled_font_t *unscaled = scaled_font->unscaled;
2189 FT_Face face;
2190 FT_ULong charcode;
2191 FT_UInt gindex;
2193 face = _cairo_ft_unscaled_font_lock_face (unscaled);
2194 if (!face)
2195 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2197 *ucs4 = (uint32_t) -1;
2198 charcode = FT_Get_First_Char(face, &gindex);
2199 while (gindex != 0) {
2200 charcode = FT_Get_Next_Char (face, charcode, &gindex);
2201 if (gindex == index) {
2202 *ucs4 = charcode;
2203 break;
2207 _cairo_ft_unscaled_font_unlock_face (unscaled);
2209 return CAIRO_STATUS_SUCCESS;
2212 const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend = {
2213 CAIRO_FONT_TYPE_FT,
2214 NULL,
2215 _cairo_ft_scaled_font_create_toy,
2216 _cairo_ft_scaled_font_fini,
2217 _cairo_ft_scaled_glyph_init,
2218 NULL, /* text_to_glyphs */
2219 _cairo_ft_ucs4_to_index,
2220 NULL, /* show_glyphs */
2221 _cairo_ft_load_truetype_table,
2222 _cairo_ft_index_to_ucs4
2225 /* #cairo_ft_font_face_t */
2227 static void
2228 _cairo_ft_font_face_destroy (void *abstract_face)
2230 cairo_ft_font_face_t *font_face = abstract_face;
2232 cairo_ft_font_face_t *tmp_face = NULL;
2233 cairo_ft_font_face_t *last_face = NULL;
2235 if (font_face == NULL)
2236 return;
2238 /* When destroying the face created by cairo_ft_font_face_create_for_ft_face,
2239 * we have a special "zombie" state for the face when the unscaled font
2240 * is still alive but there are no public references to the font face.
2242 * We go from:
2244 * font_face ------> unscaled
2245 * <-....weak....../
2247 * To:
2249 * font_face <------- unscaled
2252 if (font_face->unscaled &&
2253 font_face->unscaled->from_face &&
2254 CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face->unscaled->base.ref_count) > 1)
2256 cairo_font_face_reference (&font_face->base);
2258 _cairo_unscaled_font_destroy (&font_face->unscaled->base);
2259 font_face->unscaled = NULL;
2261 return;
2264 if (font_face->unscaled) {
2265 /* Remove face from linked list */
2266 for (tmp_face = font_face->unscaled->faces;
2267 tmp_face;
2268 tmp_face = tmp_face->next)
2270 if (tmp_face == font_face) {
2271 if (last_face)
2272 last_face->next = tmp_face->next;
2273 else
2274 font_face->unscaled->faces = tmp_face->next;
2277 last_face = tmp_face;
2280 _cairo_unscaled_font_destroy (&font_face->unscaled->base);
2281 font_face->unscaled = NULL;
2285 static cairo_status_t
2286 _cairo_ft_font_face_scaled_font_create (void *abstract_face,
2287 const cairo_matrix_t *font_matrix,
2288 const cairo_matrix_t *ctm,
2289 const cairo_font_options_t *options,
2290 cairo_scaled_font_t **scaled_font)
2292 cairo_ft_font_face_t *font_face = abstract_face;
2293 cairo_ft_options_t ft_options;
2295 /* The handling of font options is different depending on how the
2296 * font face was created. When the user creates a font face with
2297 * cairo_ft_font_face_create_for_ft_face(), then the load flags
2298 * passed in augment the load flags for the options. But for
2299 * cairo_ft_font_face_create_for_pattern(), the load flags are
2300 * derived from a pattern where the user has called
2301 * cairo_ft_font_options_substitute(), so *just* use those load
2302 * flags and ignore the options.
2304 * XXX two points about the above comment:
2305 * 1. I don't see how the comment is relevant here,
2306 * 2. What if the face is coming from FC_FT_FACE of a pattern?
2309 ft_options = font_face->ft_options;
2311 return _cairo_ft_scaled_font_create (font_face->unscaled,
2312 &font_face->base,
2313 font_matrix, ctm,
2314 options, ft_options,
2315 scaled_font);
2318 static const cairo_font_face_backend_t _cairo_ft_font_face_backend = {
2319 CAIRO_FONT_TYPE_FT,
2320 _cairo_ft_font_face_destroy,
2321 NULL, /* direct implementation */
2322 _cairo_ft_font_face_scaled_font_create
2325 static cairo_font_face_t *
2326 _cairo_ft_font_face_create (cairo_ft_unscaled_font_t *unscaled,
2327 cairo_ft_options_t *ft_options)
2329 cairo_ft_font_face_t *font_face, **prev_font_face;
2331 /* Looked for an existing matching font face */
2332 for (font_face = unscaled->faces, prev_font_face = &unscaled->faces;
2333 font_face;
2334 prev_font_face = &font_face->next, font_face = font_face->next)
2336 if (font_face->ft_options.load_flags == ft_options->load_flags &&
2337 font_face->ft_options.extra_flags == ft_options->extra_flags &&
2338 cairo_font_options_equal (&font_face->ft_options.base, &ft_options->base))
2340 if (font_face->base.status == CAIRO_STATUS_SUCCESS)
2341 return cairo_font_face_reference (&font_face->base);
2343 /* The font_face has been left in an error state, abandon it. */
2344 *prev_font_face = font_face->next;
2345 break;
2349 /* No match found, create a new one */
2350 font_face = malloc (sizeof (cairo_ft_font_face_t));
2351 if (!font_face) {
2352 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
2353 return (cairo_font_face_t *)&_cairo_font_face_nil;
2356 font_face->unscaled = unscaled;
2357 _cairo_unscaled_font_reference (&unscaled->base);
2359 font_face->ft_options = *ft_options;
2361 font_face->next = unscaled->faces;
2362 unscaled->faces = font_face;
2364 _cairo_font_face_init (&font_face->base, &_cairo_ft_font_face_backend);
2366 return &font_face->base;
2369 /* implement the platform-specific interface */
2371 static cairo_status_t
2372 _cairo_ft_font_options_substitute (const cairo_font_options_t *options,
2373 FcPattern *pattern)
2375 FcValue v;
2377 if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
2379 if (FcPatternGet (pattern, FC_ANTIALIAS, 0, &v) == FcResultNoMatch)
2381 if (! FcPatternAddBool (pattern,
2382 FC_ANTIALIAS,
2383 options->antialias != CAIRO_ANTIALIAS_NONE))
2384 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2386 if (options->antialias != CAIRO_ANTIALIAS_SUBPIXEL) {
2387 FcPatternDel (pattern, FC_RGBA);
2388 if (! FcPatternAddInteger (pattern, FC_RGBA, FC_RGBA_NONE))
2389 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2394 if (options->antialias != CAIRO_ANTIALIAS_DEFAULT)
2396 if (FcPatternGet (pattern, FC_RGBA, 0, &v) == FcResultNoMatch)
2398 int rgba;
2400 if (options->antialias == CAIRO_ANTIALIAS_SUBPIXEL) {
2401 switch (options->subpixel_order) {
2402 case CAIRO_SUBPIXEL_ORDER_DEFAULT:
2403 case CAIRO_SUBPIXEL_ORDER_RGB:
2404 default:
2405 rgba = FC_RGBA_RGB;
2406 break;
2407 case CAIRO_SUBPIXEL_ORDER_BGR:
2408 rgba = FC_RGBA_BGR;
2409 break;
2410 case CAIRO_SUBPIXEL_ORDER_VRGB:
2411 rgba = FC_RGBA_VRGB;
2412 break;
2413 case CAIRO_SUBPIXEL_ORDER_VBGR:
2414 rgba = FC_RGBA_VBGR;
2415 break;
2417 } else {
2418 rgba = FC_RGBA_NONE;
2421 if (! FcPatternAddInteger (pattern, FC_RGBA, rgba))
2422 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2426 if (options->hint_style != CAIRO_HINT_STYLE_DEFAULT)
2428 if (FcPatternGet (pattern, FC_HINTING, 0, &v) == FcResultNoMatch)
2430 if (! FcPatternAddBool (pattern,
2431 FC_HINTING,
2432 options->hint_style != CAIRO_HINT_STYLE_NONE))
2433 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2436 #ifdef FC_HINT_STYLE
2437 if (FcPatternGet (pattern, FC_HINT_STYLE, 0, &v) == FcResultNoMatch)
2439 int hint_style;
2441 switch (options->hint_style) {
2442 case CAIRO_HINT_STYLE_NONE:
2443 hint_style = FC_HINT_NONE;
2444 break;
2445 case CAIRO_HINT_STYLE_SLIGHT:
2446 hint_style = FC_HINT_SLIGHT;
2447 break;
2448 case CAIRO_HINT_STYLE_MEDIUM:
2449 hint_style = FC_HINT_MEDIUM;
2450 break;
2451 case CAIRO_HINT_STYLE_FULL:
2452 case CAIRO_HINT_STYLE_DEFAULT:
2453 default:
2454 hint_style = FC_HINT_FULL;
2455 break;
2458 if (! FcPatternAddInteger (pattern, FC_HINT_STYLE, hint_style))
2459 return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2461 #endif
2464 return CAIRO_STATUS_SUCCESS;
2468 * cairo_ft_font_options_substitute:
2469 * @options: a #cairo_font_options_t object
2470 * @pattern: an existing #FcPattern
2472 * Add options to a #FcPattern based on a #cairo_font_options_t font
2473 * options object. Options that are already in the pattern, are not overridden,
2474 * so you should call this function after calling FcConfigSubstitute() (the
2475 * user's settings should override options based on the surface type), but
2476 * before calling FcDefaultSubstitute().
2478 void
2479 cairo_ft_font_options_substitute (const cairo_font_options_t *options,
2480 FcPattern *pattern)
2482 if (cairo_font_options_status ((cairo_font_options_t *) options))
2483 return;
2485 _cairo_ft_font_options_substitute (options, pattern);
2489 * cairo_ft_font_face_create_for_pattern:
2490 * @pattern: A fully resolved fontconfig
2491 * pattern. A pattern can be resolved, by, among other things, calling
2492 * FcConfigSubstitute(), FcDefaultSubstitute(), then
2493 * FcFontMatch(). Cairo will call FcPatternReference() on this
2494 * pattern, so you should not further modify the pattern, but you can
2495 * release your reference to the pattern with FcPatternDestroy() if
2496 * you no longer need to access it.
2498 * Creates a new font face for the FreeType font backend based on a
2499 * fontconfig pattern. This font can then be used with
2500 * cairo_set_font_face() or cairo_scaled_font_create(). The
2501 * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
2502 * also for the FreeType backend and can be used with functions such
2503 * as cairo_ft_scaled_font_lock_face().
2505 * Font rendering options are represented both here and when you
2506 * call cairo_scaled_font_create(). Font options that have a representation
2507 * in a #FcPattern must be passed in here; to modify #FcPattern
2508 * appropriately to reflect the options in a #cairo_font_options_t, call
2509 * cairo_ft_font_options_substitute().
2511 * The pattern's FC_FT_FACE element is inspected first and if that is set,
2512 * that will be the FreeType font face associated with the returned cairo
2513 * font face. Otherwise the FC_FILE and FC_INDEX elements of @pattern are
2514 * used to load a font face from file.
2516 * If the FC_FT_FACE element of @pattern is set, the user is responsible
2517 * for making sure that the referenced FT_Face remains valid for the life
2518 * time of the returned #cairo_font_face_t. See
2519 * cairo_ft_font_face_create_for_ft_face() for an exmaple of how to couple
2520 * the life time of the FT_Face to that of the cairo font-face.
2522 * Return value: a newly created #cairo_font_face_t. Free with
2523 * cairo_font_face_destroy() when you are done using it.
2525 cairo_font_face_t *
2526 cairo_ft_font_face_create_for_pattern (FcPattern *pattern)
2528 cairo_ft_unscaled_font_t *unscaled;
2529 cairo_font_face_t *font_face;
2530 cairo_ft_options_t ft_options;
2532 unscaled = _cairo_ft_unscaled_font_create_for_pattern (pattern);
2533 if (unscaled == NULL) {
2534 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
2535 return (cairo_font_face_t *)&_cairo_font_face_nil;
2538 _get_pattern_ft_options (pattern, &ft_options);
2539 font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
2540 _cairo_unscaled_font_destroy (&unscaled->base);
2542 return font_face;
2546 * cairo_ft_font_face_create_for_ft_face:
2547 * @face: A FreeType face object, already opened. This must
2548 * be kept around until the face's ref_count drops to
2549 * zero and it is freed. Since the face may be referenced
2550 * internally to Cairo, the best way to determine when it
2551 * is safe to free the face is to pass a
2552 * #cairo_destroy_func_t to cairo_font_face_set_user_data()
2553 * @load_flags: flags to pass to FT_Load_Glyph when loading
2554 * glyphs from the font. These flags are OR'ed together with
2555 * the flags derived from the #cairo_font_options_t passed
2556 * to cairo_scaled_font_create(), so only a few values such
2557 * as %FT_LOAD_VERTICAL_LAYOUT, and %FT_LOAD_FORCE_AUTOHINT
2558 * are useful. You should not pass any of the flags affecting
2559 * the load target, such as %FT_LOAD_TARGET_LIGHT.
2561 * Creates a new font face for the FreeType font backend from a
2562 * pre-opened FreeType face. This font can then be used with
2563 * cairo_set_font_face() or cairo_scaled_font_create(). The
2564 * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
2565 * also for the FreeType backend and can be used with functions such
2566 * as cairo_ft_scaled_font_lock_face(). Note that Cairo may keep a reference
2567 * to the FT_Face alive in a font-cache and the exact lifetime of the reference
2568 * depends highly upon the exact usage pattern and is subject to external
2569 * factors. You must not call FT_Done_Face() before the last reference to the
2570 * #cairo_font_face_t has been dropped.
2572 * As an example, below is how one might correctly couple the lifetime of
2573 * the FreeType face object to the #cairo_font_face_t.
2575 * <informalexample><programlisting>
2576 * static const cairo_user_data_key_t key;
2578 * font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
2579 * status = cairo_font_face_set_user_data (font_face, &key,
2580 * ft_face, (cairo_destroy_func_t) FT_Done_Face);
2581 * if (status) {
2582 * cairo_font_face_destroy (font_face);
2583 * FT_Done_Face (ft_face);
2584 * return ERROR;
2586 * </programlisting></informalexample>
2588 * Return value: a newly created #cairo_font_face_t. Free with
2589 * cairo_font_face_destroy() when you are done using it.
2591 cairo_font_face_t *
2592 cairo_ft_font_face_create_for_ft_face (FT_Face face,
2593 int load_flags)
2595 cairo_ft_unscaled_font_t *unscaled;
2596 cairo_font_face_t *font_face;
2597 cairo_ft_options_t ft_options;
2599 unscaled = _cairo_ft_unscaled_font_create_from_face (face);
2600 if (unscaled == NULL) {
2601 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
2602 return (cairo_font_face_t *)&_cairo_font_face_nil;
2605 ft_options.load_flags = load_flags;
2606 ft_options.extra_flags = 0;
2607 _cairo_font_options_init_default (&ft_options.base);
2609 font_face = _cairo_ft_font_face_create (unscaled, &ft_options);
2610 _cairo_unscaled_font_destroy (&unscaled->base);
2612 return font_face;
2616 * cairo_ft_scaled_font_lock_face:
2617 * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
2618 * object can be created by calling cairo_scaled_font_create() on a
2619 * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
2620 * cairo_ft_font_face_create_for_ft_face()).
2622 * cairo_ft_scaled_font_lock_face() gets the #FT_Face object from a FreeType
2623 * backend font and scales it appropriately for the font. You must
2624 * release the face with cairo_ft_scaled_font_unlock_face()
2625 * when you are done using it. Since the #FT_Face object can be
2626 * shared between multiple #cairo_scaled_font_t objects, you must not
2627 * lock any other font objects until you unlock this one. A count is
2628 * kept of the number of times cairo_ft_scaled_font_lock_face() is
2629 * called. cairo_ft_scaled_font_unlock_face() must be called the same number
2630 * of times.
2632 * You must be careful when using this function in a library or in a
2633 * threaded application, because freetype's design makes it unsafe to
2634 * call freetype functions simultaneously from multiple threads, (even
2635 * if using distinct FT_Face objects). Because of this, application
2636 * code that acquires an FT_Face object with this call must add it's
2637 * own locking to protect any use of that object, (and which also must
2638 * protect any other calls into cairo as almost any cairo function
2639 * might result in a call into the freetype library).
2641 * Return value: The #FT_Face object for @font, scaled appropriately,
2642 * or %NULL if @scaled_font is in an error state (see
2643 * cairo_scaled_font_status()) or there is insufficient memory.
2645 FT_Face
2646 cairo_ft_scaled_font_lock_face (cairo_scaled_font_t *abstract_font)
2648 cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
2649 FT_Face face;
2650 cairo_status_t status;
2652 if (! _cairo_scaled_font_is_ft (abstract_font)) {
2653 _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
2654 return NULL;
2657 if (scaled_font->base.status)
2658 return NULL;
2660 face = _cairo_ft_unscaled_font_lock_face (scaled_font->unscaled);
2661 if (face == NULL) {
2662 status = _cairo_scaled_font_set_error (&scaled_font->base, CAIRO_STATUS_NO_MEMORY);
2663 return NULL;
2666 status = _cairo_ft_unscaled_font_set_scale (scaled_font->unscaled,
2667 &scaled_font->base.scale);
2668 if (status) {
2669 _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
2670 status = _cairo_scaled_font_set_error (&scaled_font->base, status);
2671 return NULL;
2674 /* Note: We deliberately release the unscaled font's mutex here,
2675 * so that we are not holding a lock across two separate calls to
2676 * cairo function, (which would give the application some
2677 * opportunity for creating deadlock. This is obviously unsafe,
2678 * but as documented, the user must add manual locking when using
2679 * this function. */
2680 CAIRO_MUTEX_UNLOCK (scaled_font->unscaled->mutex);
2682 return face;
2686 * cairo_ft_scaled_font_unlock_face:
2687 * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
2688 * object can be created by calling cairo_scaled_font_create() on a
2689 * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
2690 * cairo_ft_font_face_create_for_ft_face()).
2692 * Releases a face obtained with cairo_ft_scaled_font_lock_face().
2694 void
2695 cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t *abstract_font)
2697 cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
2699 if (! _cairo_scaled_font_is_ft (abstract_font)) {
2700 _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH);
2701 return;
2704 if (scaled_font->base.status)
2705 return;
2707 /* Note: We released the unscaled font's mutex at the end of
2708 * cairo_ft_scaled_font_lock_face, so we have to acquire it again
2709 * as _cairo_ft_unscaled_font_unlock_face expects it to be held
2710 * when we call into it. */
2711 CAIRO_MUTEX_LOCK (scaled_font->unscaled->mutex);
2713 _cairo_ft_unscaled_font_unlock_face (scaled_font->unscaled);
2716 /* We expose our unscaled font implementation internally for the the
2717 * PDF backend, which needs to keep track of the the different
2718 * fonts-on-disk used by a document, so it can embed them.
2720 cairo_unscaled_font_t *
2721 _cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t *abstract_font)
2723 cairo_ft_scaled_font_t *scaled_font = (cairo_ft_scaled_font_t *) abstract_font;
2725 return &scaled_font->unscaled->base;
2728 cairo_bool_t
2729 _cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t *scaled_font)
2731 cairo_ft_scaled_font_t *ft_scaled_font;
2733 if (!_cairo_scaled_font_is_ft (scaled_font))
2734 return FALSE;
2736 ft_scaled_font = (cairo_ft_scaled_font_t *) scaled_font;
2737 if (ft_scaled_font->ft_options.load_flags & FT_LOAD_VERTICAL_LAYOUT)
2738 return TRUE;
2739 return FALSE;
2742 void
2743 _cairo_ft_font_reset_static_data (void)
2745 _cairo_ft_unscaled_font_map_destroy ();