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.
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() */
44 #include "cairo-ft-private.h"
49 #include <fontconfig/fontconfig.h>
50 #include <fontconfig/fcfreetype.h>
54 #include FT_FREETYPE_H
57 #include FT_TRUETYPE_TABLES_H
58 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
59 #include FT_SYNTHESIS_H
62 #define DOUBLE_TO_26_6(d) ((FT_F26Dot6)((d) * 64.0))
63 #define DOUBLE_FROM_26_6(t) ((double)(t) / 64.0)
64 #define DOUBLE_TO_16_16(d) ((FT_Fixed)((d) * 65536.0))
65 #define DOUBLE_FROM_16_16(t) ((double)(t) / 65536.0)
67 /* This is the max number of FT_face objects we keep open at once
69 #define MAX_OPEN_FACES 10
72 * The simple 2x2 matrix is converted into separate scale and shape
73 * factors so that hinting works right
76 typedef struct _cairo_ft_font_transform
{
77 double x_scale
, y_scale
;
79 } cairo_ft_font_transform_t
;
82 * We create an object that corresponds to a single font on the disk;
83 * (identified by a filename/id pair) these are shared between all
84 * fonts using that file. For cairo_ft_font_face_create_for_ft_face(), we
85 * just create a one-off version with a permanent face value.
88 typedef struct _cairo_ft_font_face cairo_ft_font_face_t
;
90 struct _cairo_ft_unscaled_font
{
91 cairo_unscaled_font_t base
;
93 cairo_bool_t from_face
; /* was the FT_Face provided by user? */
94 FT_Face face
; /* provided or cached face */
96 /* only set if from_face is false */
100 /* We temporarily scale the unscaled font as needed */
101 cairo_bool_t have_scale
;
102 cairo_matrix_t current_scale
;
103 double x_scale
; /* Extracted X scale factor */
104 double y_scale
; /* Extracted Y scale factor */
105 cairo_bool_t have_shape
; /* true if the current scale has a non-scale component*/
106 cairo_matrix_t current_shape
;
107 FT_Matrix Current_Shape
;
112 cairo_ft_font_face_t
*faces
; /* Linked list of faces for this font */
116 _cairo_ft_unscaled_font_keys_equal (const void *key_a
,
120 _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t
*unscaled
);
122 typedef enum _cairo_ft_extra_flags
{
123 CAIRO_FT_OPTIONS_HINT_METRICS
= (1 << 0),
124 CAIRO_FT_OPTIONS_EMBOLDEN
= (1 << 1)
125 } cairo_ft_extra_flags_t
;
127 typedef struct _cairo_ft_options
{
128 cairo_font_options_t base
;
129 int load_flags
; /* flags for FT_Load_Glyph */
130 cairo_ft_extra_flags_t extra_flags
; /* other flags that affect results */
131 } cairo_ft_options_t
;
133 struct _cairo_ft_font_face
{
134 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
;
140 #if CAIRO_HAS_FC_FONT
141 FcPattern
*pattern
; /* if pattern is set, the above fields will be NULL */
142 cairo_font_face_t
*resolved_font_face
;
143 FcConfig
*resolved_config
;
147 static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend
;
149 #if CAIRO_HAS_FC_FONT
150 static cairo_status_t
151 _cairo_ft_font_options_substitute (const cairo_font_options_t
*options
,
154 static cairo_font_face_t
*
155 _cairo_ft_resolve_pattern (FcPattern
*pattern
,
156 const cairo_matrix_t
*font_matrix
,
157 const cairo_matrix_t
*ctm
,
158 const cairo_font_options_t
*options
);
163 * We maintain a hash table to map file/id => #cairo_ft_unscaled_font_t.
164 * The hash table itself isn't limited in size. However, we limit the
165 * number of FT_Face objects we keep around; when we've exceeded that
166 * limit and need to create a new FT_Face, we dump the FT_Face from a
167 * random #cairo_ft_unscaled_font_t which has an unlocked FT_Face, (if
171 typedef struct _cairo_ft_unscaled_font_map
{
172 cairo_hash_table_t
*hash_table
;
173 FT_Library ft_library
;
175 } cairo_ft_unscaled_font_map_t
;
177 static cairo_ft_unscaled_font_map_t
*cairo_ft_unscaled_font_map
= NULL
;
180 _font_map_release_face_lock_held (cairo_ft_unscaled_font_map_t
*font_map
,
181 cairo_ft_unscaled_font_t
*unscaled
)
183 if (unscaled
->face
) {
184 FT_Done_Face (unscaled
->face
);
185 unscaled
->face
= NULL
;
186 unscaled
->have_scale
= FALSE
;
188 font_map
->num_open_faces
--;
192 static cairo_status_t
193 _cairo_ft_unscaled_font_map_create (void)
195 cairo_ft_unscaled_font_map_t
*font_map
;
197 /* This function is only intended to be called from
198 * _cairo_ft_unscaled_font_map_lock. So we'll crash if we can
199 * detect some other call path. */
200 assert (cairo_ft_unscaled_font_map
== NULL
);
202 font_map
= malloc (sizeof (cairo_ft_unscaled_font_map_t
));
203 if (unlikely (font_map
== NULL
))
204 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
206 font_map
->hash_table
=
207 _cairo_hash_table_create (_cairo_ft_unscaled_font_keys_equal
);
209 if (unlikely (font_map
->hash_table
== NULL
))
212 if (unlikely (FT_Init_FreeType (&font_map
->ft_library
)))
215 font_map
->num_open_faces
= 0;
217 cairo_ft_unscaled_font_map
= font_map
;
218 return CAIRO_STATUS_SUCCESS
;
221 if (font_map
->hash_table
)
222 _cairo_hash_table_destroy (font_map
->hash_table
);
225 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
230 _cairo_ft_unscaled_font_map_pluck_entry (void *entry
, void *closure
)
232 cairo_ft_unscaled_font_t
*unscaled
= entry
;
233 cairo_ft_unscaled_font_map_t
*font_map
= closure
;
235 _cairo_hash_table_remove (font_map
->hash_table
,
236 &unscaled
->base
.hash_entry
);
238 if (! unscaled
->from_face
)
239 _font_map_release_face_lock_held (font_map
, unscaled
);
241 _cairo_ft_unscaled_font_fini (unscaled
);
246 _cairo_ft_unscaled_font_map_destroy (void)
248 cairo_ft_unscaled_font_map_t
*font_map
;
250 CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex
);
251 font_map
= cairo_ft_unscaled_font_map
;
252 cairo_ft_unscaled_font_map
= NULL
;
253 CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex
);
255 if (font_map
!= NULL
) {
256 _cairo_hash_table_foreach (font_map
->hash_table
,
257 _cairo_ft_unscaled_font_map_pluck_entry
,
259 assert (font_map
->num_open_faces
== 0);
261 FT_Done_FreeType (font_map
->ft_library
);
263 _cairo_hash_table_destroy (font_map
->hash_table
);
269 static cairo_ft_unscaled_font_map_t
*
270 _cairo_ft_unscaled_font_map_lock (void)
272 CAIRO_MUTEX_LOCK (_cairo_ft_unscaled_font_map_mutex
);
274 if (unlikely (cairo_ft_unscaled_font_map
== NULL
)) {
275 if (unlikely (_cairo_ft_unscaled_font_map_create ())) {
276 CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex
);
281 return cairo_ft_unscaled_font_map
;
285 _cairo_ft_unscaled_font_map_unlock (void)
287 CAIRO_MUTEX_UNLOCK (_cairo_ft_unscaled_font_map_mutex
);
291 _cairo_ft_unscaled_font_init_key (cairo_ft_unscaled_font_t
*key
,
292 cairo_bool_t from_face
,
299 key
->from_face
= from_face
;
300 key
->filename
= filename
;
304 hash
= _cairo_hash_string (filename
);
305 /* the constants are just arbitrary primes */
306 hash
+= ((unsigned long) id
) * 1607;
307 hash
+= ((unsigned long) face
) * 2137;
309 key
->base
.hash_entry
.hash
= hash
;
313 * _cairo_ft_unscaled_font_init:
315 * Initialize a #cairo_ft_unscaled_font_t.
317 * There are two basic flavors of #cairo_ft_unscaled_font_t, one
318 * created from an FT_Face and the other created from a filename/id
319 * pair. These two flavors are identified as from_face and !from_face.
321 * To initialize a from_face font, pass filename==%NULL, id=0 and the
324 * To initialize a !from_face font, pass the filename/id as desired
327 * Note that the code handles these two flavors in very distinct
328 * ways. For example there is a hash_table mapping
329 * filename/id->#cairo_unscaled_font_t in the !from_face case, but no
330 * parallel in the from_face case, (where the calling code would have
331 * to do its own mapping to ensure similar sharing).
333 static cairo_status_t
334 _cairo_ft_unscaled_font_init (cairo_ft_unscaled_font_t
*unscaled
,
335 cairo_bool_t from_face
,
336 const char *filename
,
340 _cairo_unscaled_font_init (&unscaled
->base
,
341 &cairo_ft_unscaled_font_backend
);
344 unscaled
->from_face
= TRUE
;
345 _cairo_ft_unscaled_font_init_key (unscaled
, TRUE
, NULL
, 0, face
);
349 unscaled
->from_face
= FALSE
;
350 unscaled
->face
= NULL
;
352 filename_copy
= strdup (filename
);
353 if (unlikely (filename_copy
== NULL
))
354 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
356 _cairo_ft_unscaled_font_init_key (unscaled
, FALSE
, filename_copy
, id
, NULL
);
359 unscaled
->have_scale
= FALSE
;
360 CAIRO_MUTEX_INIT (unscaled
->mutex
);
361 unscaled
->lock_count
= 0;
363 unscaled
->faces
= NULL
;
365 return CAIRO_STATUS_SUCCESS
;
369 * _cairo_ft_unscaled_font_fini:
371 * Free all data associated with a #cairo_ft_unscaled_font_t.
373 * CAUTION: The unscaled->face field must be %NULL before calling this
374 * function. This is because the #cairo_ft_unscaled_font_t_map keeps a
375 * count of these faces (font_map->num_open_faces) so it maintains the
376 * unscaled->face field while it has its lock held. See
377 * _font_map_release_face_lock_held().
380 _cairo_ft_unscaled_font_fini (cairo_ft_unscaled_font_t
*unscaled
)
382 assert (unscaled
->face
== NULL
);
384 if (unscaled
->filename
) {
385 free (unscaled
->filename
);
386 unscaled
->filename
= NULL
;
389 CAIRO_MUTEX_FINI (unscaled
->mutex
);
393 _cairo_ft_unscaled_font_keys_equal (const void *key_a
,
396 const cairo_ft_unscaled_font_t
*unscaled_a
= key_a
;
397 const cairo_ft_unscaled_font_t
*unscaled_b
= key_b
;
399 if (unscaled_a
->id
== unscaled_b
->id
&&
400 unscaled_a
->from_face
== unscaled_b
->from_face
)
402 if (unscaled_a
->from_face
)
403 return unscaled_a
->face
== unscaled_b
->face
;
405 if (unscaled_a
->filename
== NULL
&& unscaled_b
->filename
== NULL
)
407 else if (unscaled_a
->filename
== NULL
|| unscaled_b
->filename
== NULL
)
410 return (strcmp (unscaled_a
->filename
, unscaled_b
->filename
) == 0);
416 /* Finds or creates a #cairo_ft_unscaled_font_t for the filename/id from
417 * pattern. Returns a new reference to the unscaled font.
419 static cairo_status_t
420 _cairo_ft_unscaled_font_create_internal (cairo_bool_t from_face
,
424 cairo_ft_unscaled_font_t
**out
)
426 cairo_ft_unscaled_font_t key
, *unscaled
;
427 cairo_ft_unscaled_font_map_t
*font_map
;
428 cairo_status_t status
;
430 font_map
= _cairo_ft_unscaled_font_map_lock ();
431 if (unlikely (font_map
== NULL
))
432 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
434 _cairo_ft_unscaled_font_init_key (&key
, from_face
, filename
, id
, font_face
);
436 /* Return existing unscaled font if it exists in the hash table. */
437 unscaled
= _cairo_hash_table_lookup (font_map
->hash_table
,
438 &key
.base
.hash_entry
);
439 if (unscaled
!= NULL
) {
440 _cairo_unscaled_font_reference (&unscaled
->base
);
444 /* Otherwise create it and insert into hash table. */
445 unscaled
= malloc (sizeof (cairo_ft_unscaled_font_t
));
446 if (unlikely (unscaled
== NULL
)) {
447 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
448 goto UNWIND_FONT_MAP_LOCK
;
451 status
= _cairo_ft_unscaled_font_init (unscaled
, from_face
, filename
, id
, font_face
);
452 if (unlikely (status
))
453 goto UNWIND_UNSCALED_MALLOC
;
455 assert (unscaled
->base
.hash_entry
.hash
== key
.base
.hash_entry
.hash
);
456 status
= _cairo_hash_table_insert (font_map
->hash_table
,
457 &unscaled
->base
.hash_entry
);
458 if (unlikely (status
))
459 goto UNWIND_UNSCALED_FONT_INIT
;
462 _cairo_ft_unscaled_font_map_unlock ();
464 return CAIRO_STATUS_SUCCESS
;
466 UNWIND_UNSCALED_FONT_INIT
:
467 _cairo_ft_unscaled_font_fini (unscaled
);
468 UNWIND_UNSCALED_MALLOC
:
470 UNWIND_FONT_MAP_LOCK
:
471 _cairo_ft_unscaled_font_map_unlock ();
476 #if CAIRO_HAS_FC_FONT
477 static cairo_status_t
478 _cairo_ft_unscaled_font_create_for_pattern (FcPattern
*pattern
,
479 cairo_ft_unscaled_font_t
**out
)
481 FT_Face font_face
= NULL
;
482 char *filename
= NULL
;
486 ret
= FcPatternGetFTFace (pattern
, FC_FT_FACE
, 0, &font_face
);
487 if (ret
== FcResultMatch
)
489 if (ret
== FcResultOutOfMemory
)
490 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
492 ret
= FcPatternGetString (pattern
, FC_FILE
, 0, (FcChar8
**) &filename
);
493 if (ret
== FcResultOutOfMemory
)
494 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
495 if (ret
== FcResultMatch
) {
496 /* If FC_INDEX is not set, we just use 0 */
497 ret
= FcPatternGetInteger (pattern
, FC_INDEX
, 0, &id
);
498 if (ret
== FcResultOutOfMemory
)
499 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
504 /* The pattern contains neither a face nor a filename, resolve it later. */
506 return CAIRO_STATUS_SUCCESS
;
509 return _cairo_ft_unscaled_font_create_internal (font_face
!= NULL
,
510 filename
, id
, font_face
,
515 static cairo_status_t
516 _cairo_ft_unscaled_font_create_from_face (FT_Face face
,
517 cairo_ft_unscaled_font_t
**out
)
519 return _cairo_ft_unscaled_font_create_internal (TRUE
, NULL
, 0, face
, out
);
523 _cairo_ft_unscaled_font_destroy (void *abstract_font
)
525 cairo_ft_unscaled_font_t
*unscaled
= abstract_font
;
526 cairo_ft_unscaled_font_map_t
*font_map
;
528 if (unscaled
== NULL
)
531 font_map
= _cairo_ft_unscaled_font_map_lock ();
532 /* All created objects must have been mapped in the font map. */
533 assert (font_map
!= NULL
);
535 if (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&unscaled
->base
.ref_count
)) {
536 /* somebody recreated the font whilst we waited for the lock */
537 _cairo_ft_unscaled_font_map_unlock ();
541 _cairo_hash_table_remove (font_map
->hash_table
,
542 &unscaled
->base
.hash_entry
);
544 if (unscaled
->from_face
) {
545 /* See comments in _ft_font_face_destroy about the "zombie" state
546 * for a _ft_font_face.
548 if (unscaled
->faces
&& unscaled
->faces
->unscaled
== NULL
) {
549 assert (unscaled
->faces
->next
== NULL
);
550 cairo_font_face_destroy (&unscaled
->faces
->base
);
553 _font_map_release_face_lock_held (font_map
, unscaled
);
555 unscaled
->face
= NULL
;
557 _cairo_ft_unscaled_font_map_unlock ();
559 _cairo_ft_unscaled_font_fini (unscaled
);
563 _has_unlocked_face (const void *entry
)
565 const cairo_ft_unscaled_font_t
*unscaled
= entry
;
567 return (!unscaled
->from_face
&& unscaled
->lock_count
== 0 && unscaled
->face
);
570 /* Ensures that an unscaled font has a face object. If we exceed
571 * MAX_OPEN_FACES, try to close some.
573 * This differs from _cairo_ft_scaled_font_lock_face in that it doesn't
574 * set the scale on the face, but just returns it at the last scale.
577 _cairo_ft_unscaled_font_lock_face (cairo_ft_unscaled_font_t
*unscaled
)
579 cairo_ft_unscaled_font_map_t
*font_map
;
582 CAIRO_MUTEX_LOCK (unscaled
->mutex
);
583 unscaled
->lock_count
++;
586 return unscaled
->face
;
588 /* If this unscaled font was created from an FT_Face then we just
589 * returned it above. */
590 assert (!unscaled
->from_face
);
592 font_map
= _cairo_ft_unscaled_font_map_lock ();
594 assert (font_map
!= NULL
);
596 while (font_map
->num_open_faces
>= MAX_OPEN_FACES
)
598 cairo_ft_unscaled_font_t
*entry
;
600 entry
= _cairo_hash_table_random_entry (font_map
->hash_table
,
605 _font_map_release_face_lock_held (font_map
, entry
);
608 _cairo_ft_unscaled_font_map_unlock ();
610 if (FT_New_Face (font_map
->ft_library
,
615 unscaled
->lock_count
--;
616 CAIRO_MUTEX_UNLOCK (unscaled
->mutex
);
617 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
621 unscaled
->face
= face
;
623 font_map
->num_open_faces
++;
629 /* Unlock unscaled font locked with _cairo_ft_unscaled_font_lock_face
632 _cairo_ft_unscaled_font_unlock_face (cairo_ft_unscaled_font_t
*unscaled
)
634 assert (unscaled
->lock_count
> 0);
636 unscaled
->lock_count
--;
638 CAIRO_MUTEX_UNLOCK (unscaled
->mutex
);
642 static cairo_status_t
643 _compute_transform (cairo_ft_font_transform_t
*sf
,
644 cairo_matrix_t
*scale
)
646 cairo_status_t status
;
647 double x_scale
, y_scale
;
648 cairo_matrix_t normalized
= *scale
;
650 /* The font matrix has x and y "scale" components which we extract and
651 * use as character scale values. These influence the way freetype
652 * chooses hints, as well as selecting different bitmaps in
653 * hand-rendered fonts. We also copy the normalized matrix to
654 * freetype's transformation.
657 status
= _cairo_matrix_compute_basis_scale_factors (scale
,
660 if (unlikely (status
))
663 /* FreeType docs say this about x_scale and y_scale:
664 * "A character width or height smaller than 1pt is set to 1pt;"
665 * So, we cap them from below at 1.0 and let the FT transform
666 * take care of sub-1.0 scaling. */
672 sf
->x_scale
= x_scale
;
673 sf
->y_scale
= y_scale
;
675 cairo_matrix_scale (&normalized
, 1.0 / x_scale
, 1.0 / y_scale
);
677 _cairo_matrix_get_affine (&normalized
,
678 &sf
->shape
[0][0], &sf
->shape
[0][1],
679 &sf
->shape
[1][0], &sf
->shape
[1][1],
682 return CAIRO_STATUS_SUCCESS
;
685 /* Temporarily scales an unscaled font to the give scale. We catch
686 * scaling to the same size, since changing a FT_Face is expensive.
688 static cairo_status_t
689 _cairo_ft_unscaled_font_set_scale (cairo_ft_unscaled_font_t
*unscaled
,
690 cairo_matrix_t
*scale
)
692 cairo_status_t status
;
693 cairo_ft_font_transform_t sf
;
697 assert (unscaled
->face
!= NULL
);
699 if (unscaled
->have_scale
&&
700 scale
->xx
== unscaled
->current_scale
.xx
&&
701 scale
->yx
== unscaled
->current_scale
.yx
&&
702 scale
->xy
== unscaled
->current_scale
.xy
&&
703 scale
->yy
== unscaled
->current_scale
.yy
)
704 return CAIRO_STATUS_SUCCESS
;
706 unscaled
->have_scale
= TRUE
;
707 unscaled
->current_scale
= *scale
;
709 status
= _compute_transform (&sf
, scale
);
710 if (unlikely (status
))
713 unscaled
->x_scale
= sf
.x_scale
;
714 unscaled
->y_scale
= sf
.y_scale
;
716 mat
.xx
= DOUBLE_TO_16_16(sf
.shape
[0][0]);
717 mat
.yx
= - DOUBLE_TO_16_16(sf
.shape
[0][1]);
718 mat
.xy
= - DOUBLE_TO_16_16(sf
.shape
[1][0]);
719 mat
.yy
= DOUBLE_TO_16_16(sf
.shape
[1][1]);
721 unscaled
->have_shape
= (mat
.xx
!= 0x10000 ||
726 unscaled
->Current_Shape
= mat
;
727 cairo_matrix_init (&unscaled
->current_shape
,
728 sf
.shape
[0][0], sf
.shape
[0][1],
729 sf
.shape
[1][0], sf
.shape
[1][1],
732 FT_Set_Transform(unscaled
->face
, &mat
, NULL
);
734 if ((unscaled
->face
->face_flags
& FT_FACE_FLAG_SCALABLE
) != 0) {
735 error
= FT_Set_Char_Size (unscaled
->face
,
736 sf
.x_scale
* 64.0 + .5,
737 sf
.y_scale
* 64.0 + .5,
740 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
742 double min_distance
= DBL_MAX
;
746 for (i
= 0; i
< unscaled
->face
->num_fixed_sizes
; i
++) {
747 #if HAVE_FT_BITMAP_SIZE_Y_PPEM
748 double size
= unscaled
->face
->available_sizes
[i
].y_ppem
/ 64.;
750 double size
= unscaled
->face
->available_sizes
[i
].height
;
752 double distance
= fabs (size
- sf
.y_scale
);
754 if (distance
<= min_distance
) {
755 min_distance
= distance
;
759 #if HAVE_FT_BITMAP_SIZE_Y_PPEM
760 error
= FT_Set_Char_Size (unscaled
->face
,
761 unscaled
->face
->available_sizes
[best_i
].x_ppem
,
762 unscaled
->face
->available_sizes
[best_i
].y_ppem
,
766 error
= FT_Set_Pixel_Sizes (unscaled
->face
,
767 unscaled
->face
->available_sizes
[best_i
].width
,
768 unscaled
->face
->available_sizes
[best_i
].height
);
770 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
773 return CAIRO_STATUS_SUCCESS
;
776 /* Empirically-derived subpixel filtering values thanks to Keith
777 * Packard and libXft. */
778 static const int filters
[3][3] = {
781 { 65538*4/7,65538*2/7,65538*1/7 },
783 { 65536*1/4, 65536*2/4, 65537*1/4 },
785 { 65538*1/7,65538*2/7,65538*4/7 },
787 { 65538*9/13,65538*3/13,65538*1/13 },
789 { 65538*1/6, 65538*4/6, 65538*1/6 },
791 { 65538*1/13,65538*3/13,65538*9/13 },
794 /* Fills in val->image with an image surface created from @bitmap
796 static cairo_status_t
797 _get_bitmap_surface (FT_Bitmap
*bitmap
,
798 cairo_bool_t own_buffer
,
799 cairo_font_options_t
*font_options
,
800 cairo_image_surface_t
**surface
)
802 int width
, height
, stride
;
804 int format
= CAIRO_FORMAT_A8
;
805 cairo_bool_t subpixel
= FALSE
;
807 width
= bitmap
->width
;
808 height
= bitmap
->rows
;
810 if (width
== 0 || height
== 0) {
811 *surface
= (cairo_image_surface_t
*)
812 cairo_image_surface_create_for_data (NULL
, format
, 0, 0, 0);
813 return (*surface
)->base
.status
;
816 switch (bitmap
->pixel_mode
) {
817 case FT_PIXEL_MODE_MONO
:
818 stride
= (((width
+ 31) & ~31) >> 3);
820 data
= bitmap
->buffer
;
821 assert (stride
== bitmap
->pitch
);
823 data
= _cairo_malloc_ab (height
, stride
);
825 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
827 if (stride
== bitmap
->pitch
) {
828 memcpy (data
, bitmap
->buffer
, stride
* height
);
831 unsigned char *source
, *dest
;
833 source
= bitmap
->buffer
;
835 for (i
= height
; i
; i
--) {
836 memcpy (dest
, source
, bitmap
->pitch
);
837 memset (dest
+ bitmap
->pitch
, '\0', stride
- bitmap
->pitch
);
839 source
+= bitmap
->pitch
;
845 #ifndef WORDS_BIGENDIAN
848 int count
= stride
* height
;
851 *d
= CAIRO_BITSWAP8 (*d
);
856 format
= CAIRO_FORMAT_A1
;
859 case FT_PIXEL_MODE_LCD
:
860 case FT_PIXEL_MODE_LCD_V
:
861 case FT_PIXEL_MODE_GRAY
:
862 switch (font_options
->antialias
) {
863 case CAIRO_ANTIALIAS_DEFAULT
:
864 case CAIRO_ANTIALIAS_GRAY
:
865 case CAIRO_ANTIALIAS_NONE
:
867 stride
= bitmap
->pitch
;
869 data
= bitmap
->buffer
;
871 data
= _cairo_malloc_ab (height
, stride
);
873 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
875 memcpy (data
, bitmap
->buffer
, stride
* height
);
877 format
= CAIRO_FORMAT_A8
;
879 case CAIRO_ANTIALIAS_SUBPIXEL
: {
881 unsigned char *in_line
, *out_line
, *in
;
883 unsigned int red
, green
, blue
;
887 unsigned char *data_rgba
;
888 unsigned int width_rgba
, stride_rgba
;
892 switch (font_options
->subpixel_order
) {
893 case CAIRO_SUBPIXEL_ORDER_DEFAULT
:
894 case CAIRO_SUBPIXEL_ORDER_RGB
:
895 case CAIRO_SUBPIXEL_ORDER_BGR
:
900 case CAIRO_SUBPIXEL_ORDER_VRGB
:
901 case CAIRO_SUBPIXEL_ORDER_VBGR
:
907 * Filter the glyph to soften the color fringes
910 stride
= bitmap
->pitch
;
911 stride_rgba
= (width_rgba
* 4 + 3) & ~3;
912 data_rgba
= calloc (stride_rgba
, height
);
913 if (unlikely (data_rgba
== NULL
)) {
915 free (bitmap
->buffer
);
916 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
920 switch (font_options
->subpixel_order
) {
921 case CAIRO_SUBPIXEL_ORDER_VRGB
:
923 case CAIRO_SUBPIXEL_ORDER_DEFAULT
:
924 case CAIRO_SUBPIXEL_ORDER_RGB
:
930 case CAIRO_SUBPIXEL_ORDER_VBGR
:
932 case CAIRO_SUBPIXEL_ORDER_BGR
:
938 in_line
= bitmap
->buffer
;
939 out_line
= data_rgba
;
940 for (y
= 0; y
< height
; y
++)
943 out
= (unsigned int *) out_line
;
944 in_line
+= stride
* vmul
;
945 out_line
+= stride_rgba
;
946 for (x
= 0; x
< width
* hmul
; x
+= hmul
)
948 red
= green
= blue
= 0;
950 for (s
= 0; s
< 3; s
++)
952 red
+= filters
[rf
][s
]*in
[x
+o
];
953 green
+= filters
[gf
][s
]*in
[x
+o
];
954 blue
+= filters
[bf
][s
]*in
[x
+o
];
958 green
= green
/ 65536;
960 *out
++ = (green
<< 24) | (red
<< 16) | (green
<< 8) | blue
;
964 /* Images here are stored in native format. The
965 * backend must convert to its own format as needed
969 free (bitmap
->buffer
);
971 stride
= stride_rgba
;
972 format
= CAIRO_FORMAT_ARGB32
;
978 case FT_PIXEL_MODE_GRAY2
:
979 case FT_PIXEL_MODE_GRAY4
:
980 /* These could be triggered by very rare types of TrueType fonts */
983 free (bitmap
->buffer
);
984 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
987 *surface
= (cairo_image_surface_t
*)
988 cairo_image_surface_create_for_data (data
,
990 width
, height
, stride
);
991 if ((*surface
)->base
.status
) {
993 return (*surface
)->base
.status
;
997 pixman_image_set_component_alpha ((*surface
)->pixman_image
, TRUE
);
999 _cairo_image_surface_assume_ownership_of_data ((*surface
));
1001 _cairo_debug_check_image_surface_is_defined (&(*surface
)->base
);
1003 return CAIRO_STATUS_SUCCESS
;
1006 /* Converts an outline FT_GlyphSlot into an image
1008 * This could go through _render_glyph_bitmap as well, letting
1009 * FreeType convert the outline to a bitmap, but doing it ourselves
1010 * has two minor advantages: first, we save a copy of the bitmap
1011 * buffer: we can directly use the buffer that FreeType renders
1014 * Second, it may help when we add support for subpixel
1015 * rendering: the Xft code does it this way. (Keith thinks that
1016 * it may also be possible to get the subpixel rendering with
1017 * FT_Render_Glyph: something worth looking into in more detail
1018 * when we add subpixel support. If so, we may want to eliminate
1019 * this version of the code path entirely.
1021 static cairo_status_t
1022 _render_glyph_outline (FT_Face face
,
1023 cairo_font_options_t
*font_options
,
1024 cairo_image_surface_t
**surface
)
1026 FT_GlyphSlot glyphslot
= face
->glyph
;
1027 FT_Outline
*outline
= &glyphslot
->outline
;
1033 unsigned int width
, height
, stride
;
1034 cairo_bool_t subpixel
= FALSE
;
1035 cairo_status_t status
;
1037 FT_Outline_Get_CBox (outline
, &cbox
);
1041 cbox
.xMax
= (cbox
.xMax
+ 63) & -64;
1042 cbox
.yMax
= (cbox
.yMax
+ 63) & -64;
1044 width
= (unsigned int) ((cbox
.xMax
- cbox
.xMin
) >> 6);
1045 height
= (unsigned int) ((cbox
.yMax
- cbox
.yMin
) >> 6);
1046 stride
= (width
* hmul
+ 3) & ~3;
1048 if (width
* height
== 0) {
1049 cairo_format_t format
;
1050 /* Looks like fb handles zero-sized images just fine */
1051 switch (font_options
->antialias
) {
1052 case CAIRO_ANTIALIAS_NONE
:
1053 format
= CAIRO_FORMAT_A1
;
1055 case CAIRO_ANTIALIAS_SUBPIXEL
:
1056 format
= CAIRO_FORMAT_ARGB32
;
1058 case CAIRO_ANTIALIAS_DEFAULT
:
1059 case CAIRO_ANTIALIAS_GRAY
:
1061 format
= CAIRO_FORMAT_A8
;
1065 (*surface
) = (cairo_image_surface_t
*)
1066 cairo_image_surface_create_for_data (NULL
, format
, 0, 0, 0);
1067 if ((*surface
)->base
.status
)
1068 return (*surface
)->base
.status
;
1071 matrix
.xx
= matrix
.yy
= 0x10000L
;
1072 matrix
.xy
= matrix
.yx
= 0;
1074 switch (font_options
->antialias
) {
1075 case CAIRO_ANTIALIAS_NONE
:
1076 bitmap
.pixel_mode
= FT_PIXEL_MODE_MONO
;
1077 bitmap
.num_grays
= 1;
1078 stride
= ((width
+ 31) & -32) >> 3;
1080 case CAIRO_ANTIALIAS_DEFAULT
:
1081 case CAIRO_ANTIALIAS_GRAY
:
1082 bitmap
.pixel_mode
= FT_PIXEL_MODE_GRAY
;
1083 bitmap
.num_grays
= 256;
1084 stride
= (width
+ 3) & -4;
1086 case CAIRO_ANTIALIAS_SUBPIXEL
:
1087 switch (font_options
->subpixel_order
) {
1088 case CAIRO_SUBPIXEL_ORDER_RGB
:
1089 case CAIRO_SUBPIXEL_ORDER_BGR
:
1090 case CAIRO_SUBPIXEL_ORDER_DEFAULT
:
1096 case CAIRO_SUBPIXEL_ORDER_VRGB
:
1097 case CAIRO_SUBPIXEL_ORDER_VBGR
:
1103 FT_Outline_Transform (outline
, &matrix
);
1105 bitmap
.pixel_mode
= FT_PIXEL_MODE_GRAY
;
1106 bitmap
.num_grays
= 256;
1107 stride
= (width
* hmul
+ 3) & -4;
1110 bitmap
.pitch
= stride
;
1111 bitmap
.width
= width
* hmul
;
1112 bitmap
.rows
= height
* vmul
;
1113 bitmap
.buffer
= calloc (stride
, bitmap
.rows
);
1114 if (unlikely (bitmap
.buffer
== NULL
))
1115 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1117 FT_Outline_Translate (outline
, -cbox
.xMin
*hmul
, -cbox
.yMin
*vmul
);
1119 if (FT_Outline_Get_Bitmap (glyphslot
->library
, outline
, &bitmap
) != 0) {
1120 free (bitmap
.buffer
);
1121 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1124 status
= _get_bitmap_surface (&bitmap
, TRUE
, font_options
, surface
);
1125 if (unlikely (status
))
1130 * Note: the font's coordinate system is upside down from ours, so the
1131 * Y coordinate of the control box needs to be negated. Moreover, device
1132 * offsets are position of glyph origin relative to top left while xMin
1133 * and yMax are offsets of top left relative to origin. Another negation.
1135 cairo_surface_set_device_offset (&(*surface
)->base
,
1136 floor (-(double) cbox
.xMin
/ 64.0),
1137 floor (+(double) cbox
.yMax
/ 64.0));
1139 return CAIRO_STATUS_SUCCESS
;
1142 /* Converts a bitmap (or other) FT_GlyphSlot into an image */
1143 static cairo_status_t
1144 _render_glyph_bitmap (FT_Face face
,
1145 cairo_font_options_t
*font_options
,
1146 cairo_image_surface_t
**surface
)
1148 FT_GlyphSlot glyphslot
= face
->glyph
;
1149 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
1152 /* According to the FreeType docs, glyphslot->format could be
1153 * something other than FT_GLYPH_FORMAT_OUTLINE or
1154 * FT_GLYPH_FORMAT_BITMAP. Calling FT_Render_Glyph gives FreeType
1155 * the opportunity to convert such to
1156 * bitmap. FT_GLYPH_FORMAT_COMPOSITE will not be encountered since
1157 * we avoid the FT_LOAD_NO_RECURSE flag.
1159 error
= FT_Render_Glyph (glyphslot
, FT_RENDER_MODE_NORMAL
);
1160 /* XXX ignoring all other errors for now. They are not fatal, typically
1161 * just a glyph-not-found. */
1162 if (error
== FT_Err_Out_Of_Memory
)
1163 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1165 status
= _get_bitmap_surface (&glyphslot
->bitmap
, FALSE
, font_options
, surface
);
1166 if (unlikely (status
))
1170 * Note: the font's coordinate system is upside down from ours, so the
1171 * Y coordinate of the control box needs to be negated. Moreover, device
1172 * offsets are position of glyph origin relative to top left while
1173 * bitmap_left and bitmap_top are offsets of top left relative to origin.
1176 cairo_surface_set_device_offset (&(*surface
)->base
,
1177 -glyphslot
->bitmap_left
,
1178 +glyphslot
->bitmap_top
);
1183 static cairo_status_t
1184 _transform_glyph_bitmap (cairo_matrix_t
* shape
,
1185 cairo_image_surface_t
** surface
)
1187 cairo_matrix_t original_to_transformed
;
1188 cairo_matrix_t transformed_to_original
;
1189 cairo_image_surface_t
*old_image
;
1190 cairo_surface_t
*image
;
1192 double origin_x
, origin_y
;
1193 int orig_width
, orig_height
;
1195 int x_min
, y_min
, x_max
, y_max
;
1197 cairo_status_t status
;
1198 cairo_surface_pattern_t pattern
;
1200 /* We want to compute a transform that takes the origin
1201 * (device_x_offset, device_y_offset) to 0,0, then applies
1202 * the "shape" portion of the font transform
1204 original_to_transformed
= *shape
;
1206 cairo_surface_get_device_offset (&(*surface
)->base
, &origin_x
, &origin_y
);
1207 orig_width
= cairo_image_surface_get_width (&(*surface
)->base
);
1208 orig_height
= cairo_image_surface_get_height (&(*surface
)->base
);
1210 cairo_matrix_translate (&original_to_transformed
,
1211 -origin_x
, -origin_y
);
1213 /* Find the bounding box of the original bitmap under that
1217 x
[1] = orig_width
; y
[1] = 0;
1218 x
[2] = orig_width
; y
[2] = orig_height
;
1219 x
[3] = 0; y
[3] = orig_height
;
1221 for (i
= 0; i
< 4; i
++)
1222 cairo_matrix_transform_point (&original_to_transformed
,
1225 x_min
= floor (x
[0]); y_min
= floor (y
[0]);
1226 x_max
= ceil (x
[0]); y_max
= ceil (y
[0]);
1228 for (i
= 1; i
< 4; i
++) {
1230 x_min
= floor (x
[i
]);
1231 else if (x
[i
] > x_max
)
1232 x_max
= ceil (x
[i
]);
1234 y_min
= floor (y
[i
]);
1235 else if (y
[i
] > y_max
)
1236 y_max
= ceil (y
[i
]);
1239 /* Adjust the transform so that the bounding box starts at 0,0 ...
1240 * this gives our final transform from original bitmap to transformed
1243 original_to_transformed
.x0
-= x_min
;
1244 original_to_transformed
.y0
-= y_min
;
1246 /* Create the transformed bitmap
1248 width
= x_max
- x_min
;
1249 height
= y_max
- y_min
;
1251 transformed_to_original
= original_to_transformed
;
1252 status
= cairo_matrix_invert (&transformed_to_original
);
1253 if (unlikely (status
))
1256 /* We need to pad out the width to 32-bit intervals for cairo-xlib-surface.c */
1257 width
= (width
+ 3) & ~3;
1258 image
= cairo_image_surface_create (CAIRO_FORMAT_A8
, width
, height
);
1259 if (unlikely (image
->status
))
1260 return image
->status
;
1262 /* Initialize it to empty
1264 status
= _cairo_surface_fill_rectangle (image
, CAIRO_OPERATOR_CLEAR
,
1265 CAIRO_COLOR_TRANSPARENT
,
1268 if (unlikely (status
)) {
1269 cairo_surface_destroy (image
);
1273 /* Draw the original bitmap transformed into the new bitmap
1275 _cairo_pattern_init_for_surface (&pattern
, &(*surface
)->base
);
1276 cairo_pattern_set_matrix (&pattern
.base
, &transformed_to_original
);
1278 status
= _cairo_surface_composite (CAIRO_OPERATOR_OVER
,
1279 &pattern
.base
, NULL
, image
,
1284 _cairo_pattern_fini (&pattern
.base
);
1286 if (unlikely (status
)) {
1287 cairo_surface_destroy (image
);
1291 /* Now update the cache entry for the new bitmap, recomputing
1292 * the origin based on the final transform.
1294 cairo_matrix_transform_point (&original_to_transformed
,
1295 &origin_x
, &origin_y
);
1297 old_image
= (*surface
);
1298 (*surface
) = (cairo_image_surface_t
*)image
;
1299 cairo_surface_destroy (&old_image
->base
);
1301 cairo_surface_set_device_offset (&(*surface
)->base
,
1302 _cairo_lround (origin_x
),
1303 _cairo_lround (origin_y
));
1307 static const cairo_unscaled_font_backend_t cairo_ft_unscaled_font_backend
= {
1308 _cairo_ft_unscaled_font_destroy
,
1310 _cairo_ft_unscaled_font_create_glyph
1314 /* #cairo_ft_scaled_font_t */
1316 typedef struct _cairo_ft_scaled_font
{
1317 cairo_scaled_font_t base
;
1318 cairo_ft_unscaled_font_t
*unscaled
;
1319 cairo_ft_options_t ft_options
;
1320 } cairo_ft_scaled_font_t
;
1322 static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend
;
1324 #if CAIRO_HAS_FC_FONT
1325 /* The load flags passed to FT_Load_Glyph control aspects like hinting and
1326 * antialiasing. Here we compute them from the fields of a FcPattern.
1329 _get_pattern_ft_options (FcPattern
*pattern
, cairo_ft_options_t
*ret
)
1331 FcBool antialias
, vertical_layout
, hinting
, autohint
, bitmap
, embolden
;
1332 cairo_ft_options_t ft_options
;
1334 #ifdef FC_HINT_STYLE
1338 _cairo_font_options_init_default (&ft_options
.base
);
1339 ft_options
.load_flags
= FT_LOAD_DEFAULT
;
1340 ft_options
.extra_flags
= 0;
1342 #ifndef FC_EMBEDDED_BITMAP
1343 #define FC_EMBEDDED_BITMAP "embeddedbitmap"
1346 /* Check whether to force use of embedded bitmaps */
1347 if (FcPatternGetBool (pattern
,
1348 FC_EMBEDDED_BITMAP
, 0, &bitmap
) != FcResultMatch
)
1351 /* disable antialiasing if requested */
1352 if (FcPatternGetBool (pattern
,
1353 FC_ANTIALIAS
, 0, &antialias
) != FcResultMatch
)
1357 cairo_subpixel_order_t subpixel_order
;
1359 /* disable hinting if requested */
1360 if (FcPatternGetBool (pattern
,
1361 FC_HINTING
, 0, &hinting
) != FcResultMatch
)
1364 if (FcPatternGetInteger (pattern
,
1365 FC_RGBA
, 0, &rgba
) != FcResultMatch
)
1366 rgba
= FC_RGBA_UNKNOWN
;
1370 subpixel_order
= CAIRO_SUBPIXEL_ORDER_RGB
;
1373 subpixel_order
= CAIRO_SUBPIXEL_ORDER_BGR
;
1376 subpixel_order
= CAIRO_SUBPIXEL_ORDER_VRGB
;
1379 subpixel_order
= CAIRO_SUBPIXEL_ORDER_VBGR
;
1381 case FC_RGBA_UNKNOWN
:
1384 subpixel_order
= CAIRO_SUBPIXEL_ORDER_DEFAULT
;
1388 if (subpixel_order
!= CAIRO_SUBPIXEL_ORDER_DEFAULT
) {
1389 ft_options
.base
.subpixel_order
= subpixel_order
;
1390 ft_options
.base
.antialias
= CAIRO_ANTIALIAS_SUBPIXEL
;
1393 #ifdef FC_HINT_STYLE
1394 if (FcPatternGetInteger (pattern
,
1395 FC_HINT_STYLE
, 0, &hintstyle
) != FcResultMatch
)
1396 hintstyle
= FC_HINT_FULL
;
1399 hintstyle
= FC_HINT_NONE
;
1401 switch (hintstyle
) {
1403 ft_options
.base
.hint_style
= CAIRO_HINT_STYLE_NONE
;
1405 case FC_HINT_SLIGHT
:
1406 ft_options
.base
.hint_style
= CAIRO_HINT_STYLE_SLIGHT
;
1408 case FC_HINT_MEDIUM
:
1410 ft_options
.base
.hint_style
= CAIRO_HINT_STYLE_MEDIUM
;
1413 ft_options
.base
.hint_style
= CAIRO_HINT_STYLE_FULL
;
1416 #else /* !FC_HINT_STYLE */
1418 ft_options
.base
.hint_style
= CAIRO_HINT_STYLE_NONE
;
1420 #endif /* FC_HINT_STYLE */
1422 /* Force embedded bitmaps off if no hinting requested */
1423 if (ft_options
.base
.hint_style
== CAIRO_HINT_STYLE_NONE
)
1427 ft_options
.load_flags
|= FT_LOAD_NO_BITMAP
;
1430 ft_options
.base
.antialias
= CAIRO_ANTIALIAS_NONE
;
1433 /* force autohinting if requested */
1434 if (FcPatternGetBool (pattern
,
1435 FC_AUTOHINT
, 0, &autohint
) != FcResultMatch
)
1439 ft_options
.load_flags
|= FT_LOAD_FORCE_AUTOHINT
;
1441 if (FcPatternGetBool (pattern
,
1442 FC_VERTICAL_LAYOUT
, 0, &vertical_layout
) != FcResultMatch
)
1443 vertical_layout
= FcFalse
;
1445 if (vertical_layout
)
1446 ft_options
.load_flags
|= FT_LOAD_VERTICAL_LAYOUT
;
1449 #define FC_EMBOLDEN "embolden"
1451 if (FcPatternGetBool (pattern
,
1452 FC_EMBOLDEN
, 0, &embolden
) != FcResultMatch
)
1456 ft_options
.extra_flags
|= CAIRO_FT_OPTIONS_EMBOLDEN
;
1463 _cairo_ft_options_merge (cairo_ft_options_t
*options
,
1464 cairo_ft_options_t
*other
)
1466 int load_flags
= other
->load_flags
;
1467 int load_target
= FT_LOAD_TARGET_NORMAL
;
1469 /* clear load target mode */
1470 load_flags
&= ~(FT_LOAD_TARGET_(FT_LOAD_TARGET_MODE(other
->load_flags
)));
1472 if (load_flags
& FT_LOAD_NO_HINTING
)
1473 other
->base
.hint_style
= CAIRO_HINT_STYLE_NONE
;
1475 if (other
->base
.antialias
== CAIRO_ANTIALIAS_NONE
||
1476 options
->base
.antialias
== CAIRO_ANTIALIAS_NONE
) {
1477 options
->base
.antialias
= CAIRO_ANTIALIAS_NONE
;
1478 options
->base
.subpixel_order
= CAIRO_SUBPIXEL_ORDER_DEFAULT
;
1481 if (other
->base
.antialias
== CAIRO_ANTIALIAS_SUBPIXEL
&&
1482 (options
->base
.antialias
== CAIRO_ANTIALIAS_DEFAULT
||
1483 options
->base
.antialias
== CAIRO_ANTIALIAS_GRAY
)) {
1484 options
->base
.antialias
= CAIRO_ANTIALIAS_SUBPIXEL
;
1485 options
->base
.subpixel_order
= other
->base
.subpixel_order
;
1488 if (options
->base
.hint_style
== CAIRO_HINT_STYLE_DEFAULT
)
1489 options
->base
.hint_style
= other
->base
.hint_style
;
1491 if (other
->base
.hint_style
== CAIRO_HINT_STYLE_NONE
)
1492 options
->base
.hint_style
= CAIRO_HINT_STYLE_NONE
;
1494 if (options
->base
.antialias
== CAIRO_ANTIALIAS_NONE
) {
1495 if (options
->base
.hint_style
== CAIRO_HINT_STYLE_NONE
)
1496 load_flags
|= FT_LOAD_NO_HINTING
;
1498 load_target
= FT_LOAD_TARGET_MONO
;
1499 load_flags
|= FT_LOAD_MONOCHROME
;
1501 switch (options
->base
.hint_style
) {
1502 case CAIRO_HINT_STYLE_NONE
:
1503 load_flags
|= FT_LOAD_NO_HINTING
;
1505 case CAIRO_HINT_STYLE_SLIGHT
:
1506 load_target
= FT_LOAD_TARGET_LIGHT
;
1508 case CAIRO_HINT_STYLE_MEDIUM
:
1510 case CAIRO_HINT_STYLE_FULL
:
1511 case CAIRO_HINT_STYLE_DEFAULT
:
1512 if (options
->base
.antialias
== CAIRO_ANTIALIAS_SUBPIXEL
) {
1513 switch (options
->base
.subpixel_order
) {
1514 case CAIRO_SUBPIXEL_ORDER_DEFAULT
:
1515 case CAIRO_SUBPIXEL_ORDER_RGB
:
1516 case CAIRO_SUBPIXEL_ORDER_BGR
:
1517 load_target
|= FT_LOAD_TARGET_LCD
;
1519 case CAIRO_SUBPIXEL_ORDER_VRGB
:
1520 case CAIRO_SUBPIXEL_ORDER_VBGR
:
1521 load_target
|= FT_LOAD_TARGET_LCD_V
;
1529 options
->load_flags
= load_flags
| load_target
;
1530 options
->extra_flags
= other
->extra_flags
;
1531 if (options
->base
.hint_metrics
!= CAIRO_HINT_METRICS_OFF
)
1532 options
->extra_flags
|= CAIRO_FT_OPTIONS_HINT_METRICS
;
1535 static cairo_status_t
1536 _cairo_ft_font_face_scaled_font_create (void *abstract_font_face
,
1537 const cairo_matrix_t
*font_matrix
,
1538 const cairo_matrix_t
*ctm
,
1539 const cairo_font_options_t
*options
,
1540 cairo_scaled_font_t
**font_out
)
1542 cairo_ft_font_face_t
*font_face
= abstract_font_face
;
1543 cairo_ft_scaled_font_t
*scaled_font
;
1545 FT_Size_Metrics
*metrics
;
1546 cairo_font_extents_t fs_metrics
;
1547 cairo_status_t status
;
1548 cairo_ft_unscaled_font_t
*unscaled
;
1550 assert (font_face
->unscaled
);
1552 face
= _cairo_ft_unscaled_font_lock_face (font_face
->unscaled
);
1553 if (unlikely (face
== NULL
)) /* backend error */
1554 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1556 scaled_font
= malloc (sizeof (cairo_ft_scaled_font_t
));
1557 if (unlikely (scaled_font
== NULL
)) {
1558 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1562 scaled_font
->unscaled
= unscaled
= font_face
->unscaled
;
1563 _cairo_unscaled_font_reference (&unscaled
->base
);
1565 _cairo_font_options_init_copy (&scaled_font
->ft_options
.base
, options
);
1566 _cairo_ft_options_merge (&scaled_font
->ft_options
, &font_face
->ft_options
);
1568 status
= _cairo_scaled_font_init (&scaled_font
->base
,
1570 font_matrix
, ctm
, options
,
1571 &_cairo_ft_scaled_font_backend
);
1572 if (unlikely (status
))
1573 goto CLEANUP_SCALED_FONT
;
1575 status
= _cairo_ft_unscaled_font_set_scale (unscaled
,
1576 &scaled_font
->base
.scale
);
1577 if (unlikely (status
)) {
1578 /* This can only fail if we encounter an error with the underlying
1579 * font, so propagate the error back to the font-face. */
1580 _cairo_ft_unscaled_font_unlock_face (unscaled
);
1581 _cairo_unscaled_font_destroy (&unscaled
->base
);
1587 metrics
= &face
->size
->metrics
;
1590 * Get to unscaled metrics so that the upper level can get back to
1593 * Also use this path for bitmap-only fonts. The other branch uses
1594 * face members that are only relevant for scalable fonts. This is
1595 * detected by simply checking for units_per_EM==0.
1597 if (scaled_font
->base
.options
.hint_metrics
!= CAIRO_HINT_METRICS_OFF
||
1598 face
->units_per_EM
== 0) {
1599 double x_factor
, y_factor
;
1601 if (unscaled
->x_scale
== 0)
1604 x_factor
= 1 / unscaled
->x_scale
;
1606 if (unscaled
->y_scale
== 0)
1609 y_factor
= 1 / unscaled
->y_scale
;
1611 fs_metrics
.ascent
= DOUBLE_FROM_26_6(metrics
->ascender
) * y_factor
;
1612 fs_metrics
.descent
= DOUBLE_FROM_26_6(- metrics
->descender
) * y_factor
;
1613 fs_metrics
.height
= DOUBLE_FROM_26_6(metrics
->height
) * y_factor
;
1614 if (!_cairo_ft_scaled_font_is_vertical (&scaled_font
->base
)) {
1615 fs_metrics
.max_x_advance
= DOUBLE_FROM_26_6(metrics
->max_advance
) * x_factor
;
1616 fs_metrics
.max_y_advance
= 0;
1618 fs_metrics
.max_x_advance
= 0;
1619 fs_metrics
.max_y_advance
= DOUBLE_FROM_26_6(metrics
->max_advance
) * y_factor
;
1622 double scale
= face
->units_per_EM
;
1624 fs_metrics
.ascent
= face
->ascender
/ scale
;
1625 fs_metrics
.descent
= - face
->descender
/ scale
;
1626 fs_metrics
.height
= face
->height
/ scale
;
1627 if (!_cairo_ft_scaled_font_is_vertical (&scaled_font
->base
)) {
1628 fs_metrics
.max_x_advance
= face
->max_advance_width
/ scale
;
1629 fs_metrics
.max_y_advance
= 0;
1631 fs_metrics
.max_x_advance
= 0;
1632 fs_metrics
.max_y_advance
= face
->max_advance_height
/ scale
;
1636 status
= _cairo_scaled_font_set_metrics (&scaled_font
->base
, &fs_metrics
);
1637 if (unlikely (status
))
1638 goto CLEANUP_SCALED_FONT
;
1640 _cairo_ft_unscaled_font_unlock_face (unscaled
);
1642 *font_out
= &scaled_font
->base
;
1643 return CAIRO_STATUS_SUCCESS
;
1645 CLEANUP_SCALED_FONT
:
1646 _cairo_unscaled_font_destroy (&unscaled
->base
);
1649 _cairo_ft_unscaled_font_unlock_face (font_face
->unscaled
);
1650 *font_out
= _cairo_scaled_font_create_in_error (status
);
1651 return CAIRO_STATUS_SUCCESS
; /* non-backend error */
1655 _cairo_scaled_font_is_ft (cairo_scaled_font_t
*scaled_font
)
1657 return scaled_font
->backend
== &_cairo_ft_scaled_font_backend
;
1661 _cairo_ft_scaled_font_fini (void *abstract_font
)
1663 cairo_ft_scaled_font_t
*scaled_font
= abstract_font
;
1665 if (scaled_font
== NULL
)
1668 _cairo_unscaled_font_destroy (&scaled_font
->unscaled
->base
);
1672 _move_to (FT_Vector
*to
, void *closure
)
1674 cairo_path_fixed_t
*path
= closure
;
1677 x
= _cairo_fixed_from_26_6 (to
->x
);
1678 y
= _cairo_fixed_from_26_6 (to
->y
);
1680 if (_cairo_path_fixed_close_path (path
) != CAIRO_STATUS_SUCCESS
)
1682 if (_cairo_path_fixed_move_to (path
, x
, y
) != CAIRO_STATUS_SUCCESS
)
1689 _line_to (FT_Vector
*to
, void *closure
)
1691 cairo_path_fixed_t
*path
= closure
;
1694 x
= _cairo_fixed_from_26_6 (to
->x
);
1695 y
= _cairo_fixed_from_26_6 (to
->y
);
1697 if (_cairo_path_fixed_line_to (path
, x
, y
) != CAIRO_STATUS_SUCCESS
)
1704 _conic_to (FT_Vector
*control
, FT_Vector
*to
, void *closure
)
1706 cairo_path_fixed_t
*path
= closure
;
1708 cairo_fixed_t x0
, y0
;
1709 cairo_fixed_t x1
, y1
;
1710 cairo_fixed_t x2
, y2
;
1711 cairo_fixed_t x3
, y3
;
1712 cairo_point_t conic
;
1714 if (! _cairo_path_fixed_get_current_point (path
, &x0
, &y0
))
1717 conic
.x
= _cairo_fixed_from_26_6 (control
->x
);
1718 conic
.y
= _cairo_fixed_from_26_6 (control
->y
);
1720 x3
= _cairo_fixed_from_26_6 (to
->x
);
1721 y3
= _cairo_fixed_from_26_6 (to
->y
);
1723 x1
= x0
+ 2.0/3.0 * (conic
.x
- x0
);
1724 y1
= y0
+ 2.0/3.0 * (conic
.y
- y0
);
1726 x2
= x3
+ 2.0/3.0 * (conic
.x
- x3
);
1727 y2
= y3
+ 2.0/3.0 * (conic
.y
- y3
);
1729 if (_cairo_path_fixed_curve_to (path
,
1732 x3
, y3
) != CAIRO_STATUS_SUCCESS
)
1739 _cubic_to (FT_Vector
*control1
, FT_Vector
*control2
,
1740 FT_Vector
*to
, void *closure
)
1742 cairo_path_fixed_t
*path
= closure
;
1743 cairo_fixed_t x0
, y0
;
1744 cairo_fixed_t x1
, y1
;
1745 cairo_fixed_t x2
, y2
;
1747 x0
= _cairo_fixed_from_26_6 (control1
->x
);
1748 y0
= _cairo_fixed_from_26_6 (control1
->y
);
1750 x1
= _cairo_fixed_from_26_6 (control2
->x
);
1751 y1
= _cairo_fixed_from_26_6 (control2
->y
);
1753 x2
= _cairo_fixed_from_26_6 (to
->x
);
1754 y2
= _cairo_fixed_from_26_6 (to
->y
);
1756 if (_cairo_path_fixed_curve_to (path
,
1759 x2
, y2
) != CAIRO_STATUS_SUCCESS
)
1765 static cairo_status_t
1766 _decompose_glyph_outline (FT_Face face
,
1767 cairo_font_options_t
*options
,
1768 cairo_path_fixed_t
**pathp
)
1770 static const FT_Outline_Funcs outline_funcs
= {
1771 (FT_Outline_MoveToFunc
)_move_to
,
1772 (FT_Outline_LineToFunc
)_line_to
,
1773 (FT_Outline_ConicToFunc
)_conic_to
,
1774 (FT_Outline_CubicToFunc
)_cubic_to
,
1778 static const FT_Matrix invert_y
= {
1779 DOUBLE_TO_16_16 (1.0), 0,
1780 0, DOUBLE_TO_16_16 (-1.0),
1784 cairo_path_fixed_t
*path
;
1785 cairo_status_t status
;
1787 path
= _cairo_path_fixed_create ();
1789 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1791 glyph
= face
->glyph
;
1793 /* Font glyphs have an inverted Y axis compared to cairo. */
1794 FT_Outline_Transform (&glyph
->outline
, &invert_y
);
1795 if (FT_Outline_Decompose (&glyph
->outline
, &outline_funcs
, path
)) {
1796 _cairo_path_fixed_destroy (path
);
1797 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1800 status
= _cairo_path_fixed_close_path (path
);
1801 if (unlikely (status
)) {
1802 _cairo_path_fixed_destroy (path
);
1808 return CAIRO_STATUS_SUCCESS
;
1812 * Translate glyph to match its metrics.
1815 _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (void *abstract_font
,
1818 cairo_ft_scaled_font_t
*scaled_font
= abstract_font
;
1821 vector
.x
= glyph
->metrics
.vertBearingX
- glyph
->metrics
.horiBearingX
;
1822 vector
.y
= -glyph
->metrics
.vertBearingY
- glyph
->metrics
.horiBearingY
;
1824 if (glyph
->format
== FT_GLYPH_FORMAT_OUTLINE
) {
1825 FT_Vector_Transform (&vector
, &scaled_font
->unscaled
->Current_Shape
);
1826 FT_Outline_Translate(&glyph
->outline
, vector
.x
, vector
.y
);
1827 } else if (glyph
->format
== FT_GLYPH_FORMAT_BITMAP
) {
1828 glyph
->bitmap_left
+= vector
.x
/ 64;
1829 glyph
->bitmap_top
+= vector
.y
/ 64;
1833 static cairo_int_status_t
1834 _cairo_ft_scaled_glyph_init (void *abstract_font
,
1835 cairo_scaled_glyph_t
*scaled_glyph
,
1836 cairo_scaled_glyph_info_t info
)
1838 cairo_text_extents_t fs_metrics
;
1839 cairo_ft_scaled_font_t
*scaled_font
= abstract_font
;
1840 cairo_ft_unscaled_font_t
*unscaled
= scaled_font
->unscaled
;
1844 int load_flags
= scaled_font
->ft_options
.load_flags
;
1845 FT_Glyph_Metrics
*metrics
;
1846 double x_factor
, y_factor
;
1847 cairo_bool_t vertical_layout
= FALSE
;
1848 cairo_status_t status
;
1850 face
= _cairo_ft_unscaled_font_lock_face (unscaled
);
1852 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1854 status
= _cairo_ft_unscaled_font_set_scale (scaled_font
->unscaled
,
1855 &scaled_font
->base
.scale
);
1856 if (unlikely (status
))
1859 /* Ignore global advance unconditionally */
1860 load_flags
|= FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH
;
1862 if ((info
& CAIRO_SCALED_GLYPH_INFO_PATH
) != 0 &&
1863 (info
& CAIRO_SCALED_GLYPH_INFO_SURFACE
) == 0)
1864 load_flags
|= FT_LOAD_NO_BITMAP
;
1867 * Don't pass FT_LOAD_VERTICAL_LAYOUT to FT_Load_Glyph here as
1868 * suggested by freetype people.
1870 if (load_flags
& FT_LOAD_VERTICAL_LAYOUT
) {
1871 load_flags
&= ~FT_LOAD_VERTICAL_LAYOUT
;
1872 vertical_layout
= TRUE
;
1875 error
= FT_Load_Glyph (scaled_font
->unscaled
->face
,
1876 _cairo_scaled_glyph_index(scaled_glyph
),
1878 /* XXX ignoring all other errors for now. They are not fatal, typically
1879 * just a glyph-not-found. */
1880 if (error
== FT_Err_Out_Of_Memory
) {
1881 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
1885 glyph
= face
->glyph
;
1887 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
1889 * embolden glyphs if requested
1891 if (scaled_font
->ft_options
.extra_flags
& CAIRO_FT_OPTIONS_EMBOLDEN
)
1892 FT_GlyphSlot_Embolden (glyph
);
1895 if (vertical_layout
)
1896 _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font
, glyph
);
1898 if (info
& CAIRO_SCALED_GLYPH_INFO_METRICS
) {
1900 cairo_bool_t hint_metrics
= scaled_font
->base
.options
.hint_metrics
!= CAIRO_HINT_METRICS_OFF
;
1902 * Compute font-space metrics
1904 metrics
= &glyph
->metrics
;
1906 if (unscaled
->x_scale
== 0)
1909 x_factor
= 1 / unscaled
->x_scale
;
1911 if (unscaled
->y_scale
== 0)
1914 y_factor
= 1 / unscaled
->y_scale
;
1917 * Note: Y coordinates of the horizontal bearing need to be negated.
1919 * Scale metrics back to glyph space from the scaled glyph space returned
1922 * If we want hinted metrics but aren't asking for hinted glyphs from
1923 * FreeType, then we need to do the metric hinting ourselves.
1926 if (hint_metrics
&& (load_flags
& FT_LOAD_NO_HINTING
))
1932 if (!vertical_layout
) {
1933 x1
= (metrics
->horiBearingX
) & -64;
1934 x2
= (metrics
->horiBearingX
+ metrics
->width
+ 63) & -64;
1935 y1
= (-metrics
->horiBearingY
) & -64;
1936 y2
= (-metrics
->horiBearingY
+ metrics
->height
+ 63) & -64;
1938 advance
= ((metrics
->horiAdvance
+ 32) & -64);
1940 fs_metrics
.x_bearing
= DOUBLE_FROM_26_6 (x1
) * x_factor
;
1941 fs_metrics
.y_bearing
= DOUBLE_FROM_26_6 (y1
) * y_factor
;
1943 fs_metrics
.width
= DOUBLE_FROM_26_6 (x2
- x1
) * x_factor
;
1944 fs_metrics
.height
= DOUBLE_FROM_26_6 (y2
- y1
) * y_factor
;
1946 fs_metrics
.x_advance
= DOUBLE_FROM_26_6 (advance
) * x_factor
;
1947 fs_metrics
.y_advance
= 0;
1949 x1
= (metrics
->vertBearingX
) & -64;
1950 x2
= (metrics
->vertBearingX
+ metrics
->width
+ 63) & -64;
1951 y1
= (metrics
->vertBearingY
) & -64;
1952 y2
= (metrics
->vertBearingY
+ metrics
->height
+ 63) & -64;
1954 advance
= ((metrics
->vertAdvance
+ 32) & -64);
1956 fs_metrics
.x_bearing
= DOUBLE_FROM_26_6 (x1
) * x_factor
;
1957 fs_metrics
.y_bearing
= DOUBLE_FROM_26_6 (y1
) * y_factor
;
1959 fs_metrics
.width
= DOUBLE_FROM_26_6 (x2
- x1
) * x_factor
;
1960 fs_metrics
.height
= DOUBLE_FROM_26_6 (y2
- y1
) * y_factor
;
1962 fs_metrics
.x_advance
= 0;
1963 fs_metrics
.y_advance
= DOUBLE_FROM_26_6 (advance
) * y_factor
;
1966 fs_metrics
.width
= DOUBLE_FROM_26_6 (metrics
->width
) * x_factor
;
1967 fs_metrics
.height
= DOUBLE_FROM_26_6 (metrics
->height
) * y_factor
;
1969 if (!vertical_layout
) {
1970 fs_metrics
.x_bearing
= DOUBLE_FROM_26_6 (metrics
->horiBearingX
) * x_factor
;
1971 fs_metrics
.y_bearing
= DOUBLE_FROM_26_6 (-metrics
->horiBearingY
) * y_factor
;
1973 if (hint_metrics
|| glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1974 fs_metrics
.x_advance
= DOUBLE_FROM_26_6 (metrics
->horiAdvance
) * x_factor
;
1976 fs_metrics
.x_advance
= DOUBLE_FROM_16_16 (glyph
->linearHoriAdvance
) * x_factor
;
1977 fs_metrics
.y_advance
= 0 * y_factor
;
1979 fs_metrics
.x_bearing
= DOUBLE_FROM_26_6 (metrics
->vertBearingX
) * x_factor
;
1980 fs_metrics
.y_bearing
= DOUBLE_FROM_26_6 (metrics
->vertBearingY
) * y_factor
;
1982 fs_metrics
.x_advance
= 0 * x_factor
;
1983 if (hint_metrics
|| glyph
->format
!= FT_GLYPH_FORMAT_OUTLINE
)
1984 fs_metrics
.y_advance
= DOUBLE_FROM_26_6 (metrics
->vertAdvance
) * y_factor
;
1986 fs_metrics
.y_advance
= DOUBLE_FROM_16_16 (glyph
->linearVertAdvance
) * y_factor
;
1990 _cairo_scaled_glyph_set_metrics (scaled_glyph
,
1995 if ((info
& CAIRO_SCALED_GLYPH_INFO_SURFACE
) != 0) {
1996 cairo_image_surface_t
*surface
;
1998 if (glyph
->format
== FT_GLYPH_FORMAT_OUTLINE
) {
1999 status
= _render_glyph_outline (face
, &scaled_font
->ft_options
.base
,
2002 status
= _render_glyph_bitmap (face
, &scaled_font
->ft_options
.base
,
2004 if (likely (status
== CAIRO_STATUS_SUCCESS
) &&
2005 unscaled
->have_shape
)
2007 status
= _transform_glyph_bitmap (&unscaled
->current_shape
,
2009 if (unlikely (status
))
2010 cairo_surface_destroy (&surface
->base
);
2013 if (unlikely (status
))
2016 _cairo_scaled_glyph_set_surface (scaled_glyph
,
2021 if (info
& CAIRO_SCALED_GLYPH_INFO_PATH
) {
2022 cairo_path_fixed_t
*path
= NULL
; /* hide compiler warning */
2025 * A kludge -- the above code will trash the outline,
2026 * so reload it. This will probably never occur though
2028 if ((info
& CAIRO_SCALED_GLYPH_INFO_SURFACE
) != 0) {
2029 error
= FT_Load_Glyph (face
,
2030 _cairo_scaled_glyph_index(scaled_glyph
),
2031 load_flags
| FT_LOAD_NO_BITMAP
);
2032 /* XXX ignoring all other errors for now. They are not fatal, typically
2033 * just a glyph-not-found. */
2034 if (error
== FT_Err_Out_Of_Memory
) {
2035 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2038 #if HAVE_FT_GLYPHSLOT_EMBOLDEN
2040 * embolden glyphs if requested
2042 if (scaled_font
->ft_options
.extra_flags
& CAIRO_FT_OPTIONS_EMBOLDEN
)
2043 FT_GlyphSlot_Embolden (glyph
);
2045 if (vertical_layout
)
2046 _cairo_ft_scaled_glyph_vertical_layout_bearing_fix (scaled_font
, glyph
);
2049 if (glyph
->format
== FT_GLYPH_FORMAT_OUTLINE
)
2050 status
= _decompose_glyph_outline (face
, &scaled_font
->ft_options
.base
,
2053 status
= CAIRO_INT_STATUS_UNSUPPORTED
;
2055 if (unlikely (status
))
2058 _cairo_scaled_glyph_set_path (scaled_glyph
,
2063 _cairo_ft_unscaled_font_unlock_face (unscaled
);
2068 static unsigned long
2069 _cairo_ft_ucs4_to_index (void *abstract_font
,
2072 cairo_ft_scaled_font_t
*scaled_font
= abstract_font
;
2073 cairo_ft_unscaled_font_t
*unscaled
= scaled_font
->unscaled
;
2077 face
= _cairo_ft_unscaled_font_lock_face (unscaled
);
2081 #if CAIRO_HAS_FC_FONT
2082 index
= FcFreeTypeCharIndex (face
, ucs4
);
2084 index
= FT_Get_Char_Index (face
, ucs4
);
2087 _cairo_ft_unscaled_font_unlock_face (unscaled
);
2091 static cairo_int_status_t
2092 _cairo_ft_load_truetype_table (void *abstract_font
,
2095 unsigned char *buffer
,
2096 unsigned long *length
)
2098 cairo_ft_scaled_font_t
*scaled_font
= abstract_font
;
2099 cairo_ft_unscaled_font_t
*unscaled
= scaled_font
->unscaled
;
2101 cairo_status_t status
= CAIRO_INT_STATUS_UNSUPPORTED
;
2103 if (_cairo_ft_scaled_font_is_vertical (&scaled_font
->base
))
2104 return CAIRO_INT_STATUS_UNSUPPORTED
;
2106 #if HAVE_FT_LOAD_SFNT_TABLE
2107 face
= _cairo_ft_unscaled_font_lock_face (unscaled
);
2109 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2111 if (FT_IS_SFNT (face
) &&
2112 FT_Load_Sfnt_Table (face
, tag
, offset
, buffer
, length
) == 0)
2113 status
= CAIRO_STATUS_SUCCESS
;
2115 _cairo_ft_unscaled_font_unlock_face (unscaled
);
2121 static cairo_int_status_t
2122 _cairo_ft_index_to_ucs4(void *abstract_font
,
2123 unsigned long index
,
2126 cairo_ft_scaled_font_t
*scaled_font
= abstract_font
;
2127 cairo_ft_unscaled_font_t
*unscaled
= scaled_font
->unscaled
;
2132 face
= _cairo_ft_unscaled_font_lock_face (unscaled
);
2134 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2136 *ucs4
= (uint32_t) -1;
2137 charcode
= FT_Get_First_Char(face
, &gindex
);
2138 while (gindex
!= 0) {
2139 charcode
= FT_Get_Next_Char (face
, charcode
, &gindex
);
2140 if (gindex
== index
) {
2146 _cairo_ft_unscaled_font_unlock_face (unscaled
);
2148 return CAIRO_STATUS_SUCCESS
;
2151 static const cairo_scaled_font_backend_t _cairo_ft_scaled_font_backend
= {
2153 _cairo_ft_scaled_font_fini
,
2154 _cairo_ft_scaled_glyph_init
,
2155 NULL
, /* text_to_glyphs */
2156 _cairo_ft_ucs4_to_index
,
2157 NULL
, /* show_glyphs */
2158 _cairo_ft_load_truetype_table
,
2159 _cairo_ft_index_to_ucs4
2162 /* #cairo_ft_font_face_t */
2164 #if CAIRO_HAS_FC_FONT
2165 static cairo_status_t
2166 _cairo_ft_font_face_create_for_pattern (FcPattern
*pattern
,
2167 cairo_font_face_t
**out
);
2169 static cairo_status_t
2170 _cairo_ft_font_face_create_for_toy (cairo_toy_font_face_t
*toy_face
,
2171 cairo_font_face_t
**font_face
)
2176 cairo_status_t status
= CAIRO_STATUS_SUCCESS
;
2178 pattern
= FcPatternCreate ();
2180 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2182 if (!FcPatternAddString (pattern
,
2183 FC_FAMILY
, (unsigned char *) toy_face
->family
))
2185 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2189 switch (toy_face
->slant
)
2191 case CAIRO_FONT_SLANT_ITALIC
:
2192 fcslant
= FC_SLANT_ITALIC
;
2194 case CAIRO_FONT_SLANT_OBLIQUE
:
2195 fcslant
= FC_SLANT_OBLIQUE
;
2197 case CAIRO_FONT_SLANT_NORMAL
:
2199 fcslant
= FC_SLANT_ROMAN
;
2203 if (!FcPatternAddInteger (pattern
, FC_SLANT
, fcslant
)) {
2204 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2208 switch (toy_face
->weight
)
2210 case CAIRO_FONT_WEIGHT_BOLD
:
2211 fcweight
= FC_WEIGHT_BOLD
;
2213 case CAIRO_FONT_WEIGHT_NORMAL
:
2215 fcweight
= FC_WEIGHT_MEDIUM
;
2219 if (!FcPatternAddInteger (pattern
, FC_WEIGHT
, fcweight
)) {
2220 status
= _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2224 status
= _cairo_ft_font_face_create_for_pattern (pattern
, font_face
);
2227 FcPatternDestroy (pattern
);
2234 _cairo_ft_font_face_destroy (void *abstract_face
)
2236 cairo_ft_font_face_t
*font_face
= abstract_face
;
2238 cairo_ft_font_face_t
*tmp_face
= NULL
;
2239 cairo_ft_font_face_t
*last_face
= NULL
;
2241 if (font_face
== NULL
)
2244 /* When destroying a face created by cairo_ft_font_face_create_for_ft_face,
2245 * we have a special "zombie" state for the face when the unscaled font
2246 * is still alive but there are no other references to a font face with
2251 * font_face ------> unscaled
2256 * font_face <------- unscaled
2259 if (font_face
->unscaled
&&
2260 font_face
->unscaled
->from_face
&&
2261 font_face
->next
== NULL
&&
2262 font_face
->unscaled
->faces
== font_face
&&
2263 CAIRO_REFERENCE_COUNT_GET_VALUE (&font_face
->unscaled
->base
.ref_count
) > 1)
2265 cairo_font_face_reference (&font_face
->base
);
2267 _cairo_unscaled_font_destroy (&font_face
->unscaled
->base
);
2268 font_face
->unscaled
= NULL
;
2273 if (font_face
->unscaled
) {
2274 /* Remove face from linked list */
2275 for (tmp_face
= font_face
->unscaled
->faces
;
2277 tmp_face
= tmp_face
->next
)
2279 if (tmp_face
== font_face
) {
2281 last_face
->next
= tmp_face
->next
;
2283 font_face
->unscaled
->faces
= tmp_face
->next
;
2286 last_face
= tmp_face
;
2289 _cairo_unscaled_font_destroy (&font_face
->unscaled
->base
);
2290 font_face
->unscaled
= NULL
;
2293 #if CAIRO_HAS_FC_FONT
2294 if (font_face
->pattern
) {
2295 FcPatternDestroy (font_face
->pattern
);
2296 cairo_font_face_destroy (font_face
->resolved_font_face
);
2301 static cairo_font_face_t
*
2302 _cairo_ft_font_face_get_implementation (void *abstract_face
,
2303 const cairo_matrix_t
*font_matrix
,
2304 const cairo_matrix_t
*ctm
,
2305 const cairo_font_options_t
*options
)
2307 cairo_ft_font_face_t
*font_face
= abstract_face
;
2309 /* The handling of font options is different depending on how the
2310 * font face was created. When the user creates a font face with
2311 * cairo_ft_font_face_create_for_ft_face(), then the load flags
2312 * passed in augment the load flags for the options. But for
2313 * cairo_ft_font_face_create_for_pattern(), the load flags are
2314 * derived from a pattern where the user has called
2315 * cairo_ft_font_options_substitute(), so *just* use those load
2316 * flags and ignore the options.
2319 #if CAIRO_HAS_FC_FONT
2320 /* If we have an unresolved pattern, resolve it and create
2321 * unscaled font. Otherwise, use the ones stored in font_face.
2323 if (font_face
->pattern
) {
2324 cairo_font_face_t
*resolved
;
2326 /* Cache the resolved font whilst the FcConfig remains consistent. */
2327 resolved
= font_face
->resolved_font_face
;
2328 if (resolved
!= NULL
) {
2329 if (! FcInitBringUptoDate ()) {
2330 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
2331 return (cairo_font_face_t
*) &_cairo_font_face_nil
;
2334 if (font_face
->resolved_config
== FcConfigGetCurrent ())
2335 return cairo_font_face_reference (resolved
);
2337 cairo_font_face_destroy (resolved
);
2340 resolved
= _cairo_ft_resolve_pattern (font_face
->pattern
,
2345 font_face
->resolved_font_face
= cairo_font_face_reference (resolved
);
2346 font_face
->resolved_config
= FcConfigGetCurrent ();
2352 return abstract_face
;
2355 const cairo_font_face_backend_t _cairo_ft_font_face_backend
= {
2357 #if CAIRO_HAS_FC_FONT
2358 _cairo_ft_font_face_create_for_toy
,
2362 _cairo_ft_font_face_destroy
,
2363 _cairo_ft_font_face_scaled_font_create
,
2364 _cairo_ft_font_face_get_implementation
2367 #if CAIRO_HAS_FC_FONT
2368 static cairo_status_t
2369 _cairo_ft_font_face_create_for_pattern (FcPattern
*pattern
,
2370 cairo_font_face_t
**out
)
2372 cairo_ft_font_face_t
*font_face
;
2374 font_face
= malloc (sizeof (cairo_ft_font_face_t
));
2375 if (unlikely (font_face
== NULL
))
2376 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2378 font_face
->unscaled
= NULL
;
2379 font_face
->next
= NULL
;
2381 font_face
->pattern
= FcPatternDuplicate (pattern
);
2382 if (unlikely (font_face
->pattern
== NULL
)) {
2384 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2387 font_face
->resolved_font_face
= NULL
;
2388 font_face
->resolved_config
= NULL
;
2390 _cairo_font_face_init (&font_face
->base
, &_cairo_ft_font_face_backend
);
2392 *out
= &font_face
->base
;
2393 return CAIRO_STATUS_SUCCESS
;
2397 static cairo_font_face_t
*
2398 _cairo_ft_font_face_create (cairo_ft_unscaled_font_t
*unscaled
,
2399 cairo_ft_options_t
*ft_options
)
2401 cairo_ft_font_face_t
*font_face
, **prev_font_face
;
2403 /* Looked for an existing matching font face */
2404 for (font_face
= unscaled
->faces
, prev_font_face
= &unscaled
->faces
;
2406 prev_font_face
= &font_face
->next
, font_face
= font_face
->next
)
2408 if (font_face
->ft_options
.load_flags
== ft_options
->load_flags
&&
2409 font_face
->ft_options
.extra_flags
== ft_options
->extra_flags
&&
2410 cairo_font_options_equal (&font_face
->ft_options
.base
, &ft_options
->base
))
2412 if (font_face
->base
.status
) {
2413 /* The font_face has been left in an error state, abandon it. */
2414 *prev_font_face
= font_face
->next
;
2418 if (font_face
->unscaled
== NULL
) {
2419 /* Resurrect this "zombie" font_face (from
2420 * _cairo_ft_font_face_destroy), switching its unscaled_font
2421 * from owner to ownee. */
2422 font_face
->unscaled
= unscaled
;
2423 _cairo_unscaled_font_reference (&unscaled
->base
);
2424 return &font_face
->base
;
2426 return cairo_font_face_reference (&font_face
->base
);
2430 /* No match found, create a new one */
2431 font_face
= malloc (sizeof (cairo_ft_font_face_t
));
2432 if (unlikely (!font_face
)) {
2433 _cairo_error_throw (CAIRO_STATUS_NO_MEMORY
);
2434 return (cairo_font_face_t
*)&_cairo_font_face_nil
;
2437 font_face
->unscaled
= unscaled
;
2438 _cairo_unscaled_font_reference (&unscaled
->base
);
2440 font_face
->ft_options
= *ft_options
;
2442 if (unscaled
->faces
&& unscaled
->faces
->unscaled
== NULL
) {
2443 /* This "zombie" font_face (from _cairo_ft_font_face_destroy)
2444 * is no longer needed. */
2445 assert (unscaled
->from_face
&& unscaled
->faces
->next
== NULL
);
2446 cairo_font_face_destroy (&unscaled
->faces
->base
);
2447 unscaled
->faces
= NULL
;
2450 font_face
->next
= unscaled
->faces
;
2451 unscaled
->faces
= font_face
;
2453 #if CAIRO_HAS_FC_FONT
2454 font_face
->pattern
= NULL
;
2457 _cairo_font_face_init (&font_face
->base
, &_cairo_ft_font_face_backend
);
2459 return &font_face
->base
;
2462 /* implement the platform-specific interface */
2464 #if CAIRO_HAS_FC_FONT
2465 static cairo_status_t
2466 _cairo_ft_font_options_substitute (const cairo_font_options_t
*options
,
2471 if (options
->antialias
!= CAIRO_ANTIALIAS_DEFAULT
)
2473 if (FcPatternGet (pattern
, FC_ANTIALIAS
, 0, &v
) == FcResultNoMatch
)
2475 if (! FcPatternAddBool (pattern
,
2477 options
->antialias
!= CAIRO_ANTIALIAS_NONE
))
2478 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2480 if (options
->antialias
!= CAIRO_ANTIALIAS_SUBPIXEL
) {
2481 FcPatternDel (pattern
, FC_RGBA
);
2482 if (! FcPatternAddInteger (pattern
, FC_RGBA
, FC_RGBA_NONE
))
2483 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2488 if (options
->antialias
!= CAIRO_ANTIALIAS_DEFAULT
)
2490 if (FcPatternGet (pattern
, FC_RGBA
, 0, &v
) == FcResultNoMatch
)
2494 if (options
->antialias
== CAIRO_ANTIALIAS_SUBPIXEL
) {
2495 switch (options
->subpixel_order
) {
2496 case CAIRO_SUBPIXEL_ORDER_DEFAULT
:
2497 case CAIRO_SUBPIXEL_ORDER_RGB
:
2501 case CAIRO_SUBPIXEL_ORDER_BGR
:
2504 case CAIRO_SUBPIXEL_ORDER_VRGB
:
2505 rgba
= FC_RGBA_VRGB
;
2507 case CAIRO_SUBPIXEL_ORDER_VBGR
:
2508 rgba
= FC_RGBA_VBGR
;
2512 rgba
= FC_RGBA_NONE
;
2515 if (! FcPatternAddInteger (pattern
, FC_RGBA
, rgba
))
2516 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2520 if (options
->hint_style
!= CAIRO_HINT_STYLE_DEFAULT
)
2522 if (FcPatternGet (pattern
, FC_HINTING
, 0, &v
) == FcResultNoMatch
)
2524 if (! FcPatternAddBool (pattern
,
2526 options
->hint_style
!= CAIRO_HINT_STYLE_NONE
))
2527 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2530 #ifdef FC_HINT_STYLE
2531 if (FcPatternGet (pattern
, FC_HINT_STYLE
, 0, &v
) == FcResultNoMatch
)
2535 switch (options
->hint_style
) {
2536 case CAIRO_HINT_STYLE_NONE
:
2537 hint_style
= FC_HINT_NONE
;
2539 case CAIRO_HINT_STYLE_SLIGHT
:
2540 hint_style
= FC_HINT_SLIGHT
;
2542 case CAIRO_HINT_STYLE_MEDIUM
:
2543 hint_style
= FC_HINT_MEDIUM
;
2545 case CAIRO_HINT_STYLE_FULL
:
2546 case CAIRO_HINT_STYLE_DEFAULT
:
2548 hint_style
= FC_HINT_FULL
;
2552 if (! FcPatternAddInteger (pattern
, FC_HINT_STYLE
, hint_style
))
2553 return _cairo_error (CAIRO_STATUS_NO_MEMORY
);
2558 return CAIRO_STATUS_SUCCESS
;
2562 * cairo_ft_font_options_substitute:
2563 * @options: a #cairo_font_options_t object
2564 * @pattern: an existing #FcPattern
2566 * Add options to a #FcPattern based on a #cairo_font_options_t font
2567 * options object. Options that are already in the pattern, are not overridden,
2568 * so you should call this function after calling FcConfigSubstitute() (the
2569 * user's settings should override options based on the surface type), but
2570 * before calling FcDefaultSubstitute().
2573 cairo_ft_font_options_substitute (const cairo_font_options_t
*options
,
2576 if (cairo_font_options_status ((cairo_font_options_t
*) options
))
2579 _cairo_ft_font_options_substitute (options
, pattern
);
2582 static cairo_font_face_t
*
2583 _cairo_ft_resolve_pattern (FcPattern
*pattern
,
2584 const cairo_matrix_t
*font_matrix
,
2585 const cairo_matrix_t
*ctm
,
2586 const cairo_font_options_t
*font_options
)
2588 cairo_status_t status
;
2590 cairo_matrix_t scale
;
2591 FcPattern
*resolved
;
2592 cairo_ft_font_transform_t sf
;
2594 cairo_ft_unscaled_font_t
*unscaled
;
2595 cairo_ft_options_t ft_options
;
2596 cairo_font_face_t
*font_face
;
2599 scale
.x0
= scale
.y0
= 0;
2600 cairo_matrix_multiply (&scale
,
2604 status
= _compute_transform (&sf
, &scale
);
2605 if (unlikely (status
))
2606 return (cairo_font_face_t
*)&_cairo_font_face_nil
;
2608 pattern
= FcPatternDuplicate (pattern
);
2609 if (pattern
== NULL
)
2610 return (cairo_font_face_t
*)&_cairo_font_face_nil
;
2612 if (! FcPatternAddDouble (pattern
, FC_PIXEL_SIZE
, sf
.y_scale
)) {
2613 font_face
= (cairo_font_face_t
*)&_cairo_font_face_nil
;
2617 if (! FcConfigSubstitute (NULL
, pattern
, FcMatchPattern
)) {
2618 font_face
= (cairo_font_face_t
*)&_cairo_font_face_nil
;
2622 status
= _cairo_ft_font_options_substitute (font_options
, pattern
);
2624 font_face
= (cairo_font_face_t
*)&_cairo_font_face_nil
;
2628 FcDefaultSubstitute (pattern
);
2630 resolved
= FcFontMatch (NULL
, pattern
, &result
);
2632 /* We failed to find any font. Substitute twin so that the user can
2633 * see something (and hopefully recognise that the font is missing)
2634 * and not just receive a NO_MEMORY error during rendering.
2636 font_face
= _cairo_font_face_twin_create_fallback ();
2640 status
= _cairo_ft_unscaled_font_create_for_pattern (resolved
, &unscaled
);
2641 if (unlikely (status
)) {
2642 font_face
= (cairo_font_face_t
*)&_cairo_font_face_nil
;
2646 assert (unscaled
!= NULL
);
2648 _get_pattern_ft_options (resolved
, &ft_options
);
2649 font_face
= _cairo_ft_font_face_create (unscaled
, &ft_options
);
2650 _cairo_unscaled_font_destroy (&unscaled
->base
);
2653 FcPatternDestroy (resolved
);
2656 FcPatternDestroy (pattern
);
2662 * cairo_ft_font_face_create_for_pattern:
2663 * @pattern: A fontconfig pattern. Cairo makes a copy of the pattern
2664 * if it needs to. You are free to modify or free @pattern after this call.
2666 * Creates a new font face for the FreeType font backend based on a
2667 * fontconfig pattern. This font can then be used with
2668 * cairo_set_font_face() or cairo_scaled_font_create(). The
2669 * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
2670 * also for the FreeType backend and can be used with functions such
2671 * as cairo_ft_scaled_font_lock_face().
2673 * Font rendering options are represented both here and when you
2674 * call cairo_scaled_font_create(). Font options that have a representation
2675 * in a #FcPattern must be passed in here; to modify #FcPattern
2676 * appropriately to reflect the options in a #cairo_font_options_t, call
2677 * cairo_ft_font_options_substitute().
2679 * The pattern's FC_FT_FACE element is inspected first and if that is set,
2680 * that will be the FreeType font face associated with the returned cairo
2681 * font face. Otherwise the FC_FILE element is checked. If it's set,
2682 * that and the value of the FC_INDEX element (defaults to zero) of @pattern
2683 * are used to load a font face from file.
2685 * If both steps from the previous paragraph fails, @pattern will be passed
2686 * to FcConfigSubstitute, FcDefaultSubstitute, and finally FcFontMatch,
2687 * and the resulting font pattern is used.
2689 * If the FC_FT_FACE element of @pattern is set, the user is responsible
2690 * for making sure that the referenced FT_Face remains valid for the life
2691 * time of the returned #cairo_font_face_t. See
2692 * cairo_ft_font_face_create_for_ft_face() for an exmaple of how to couple
2693 * the life time of the FT_Face to that of the cairo font-face.
2695 * Return value: a newly created #cairo_font_face_t. Free with
2696 * cairo_font_face_destroy() when you are done using it.
2699 cairo_ft_font_face_create_for_pattern (FcPattern
*pattern
)
2701 cairo_ft_unscaled_font_t
*unscaled
;
2702 cairo_font_face_t
*font_face
;
2703 cairo_ft_options_t ft_options
;
2704 cairo_status_t status
;
2706 status
= _cairo_ft_unscaled_font_create_for_pattern (pattern
, &unscaled
);
2707 if (unlikely (status
))
2708 return (cairo_font_face_t
*) &_cairo_font_face_nil
;
2709 if (unlikely (unscaled
== NULL
)) {
2710 /* Store the pattern. We will resolve it and create unscaled
2711 * font when creating scaled fonts */
2712 status
= _cairo_ft_font_face_create_for_pattern (pattern
,
2714 if (unlikely (status
))
2715 return (cairo_font_face_t
*) &_cairo_font_face_nil
;
2720 _get_pattern_ft_options (pattern
, &ft_options
);
2721 font_face
= _cairo_ft_font_face_create (unscaled
, &ft_options
);
2722 _cairo_unscaled_font_destroy (&unscaled
->base
);
2729 * cairo_ft_font_face_create_for_ft_face:
2730 * @face: A FreeType face object, already opened. This must
2731 * be kept around until the face's ref_count drops to
2732 * zero and it is freed. Since the face may be referenced
2733 * internally to Cairo, the best way to determine when it
2734 * is safe to free the face is to pass a
2735 * #cairo_destroy_func_t to cairo_font_face_set_user_data()
2736 * @load_flags: flags to pass to FT_Load_Glyph when loading
2737 * glyphs from the font. These flags are OR'ed together with
2738 * the flags derived from the #cairo_font_options_t passed
2739 * to cairo_scaled_font_create(), so only a few values such
2740 * as %FT_LOAD_VERTICAL_LAYOUT, and %FT_LOAD_FORCE_AUTOHINT
2741 * are useful. You should not pass any of the flags affecting
2742 * the load target, such as %FT_LOAD_TARGET_LIGHT.
2744 * Creates a new font face for the FreeType font backend from a
2745 * pre-opened FreeType face. This font can then be used with
2746 * cairo_set_font_face() or cairo_scaled_font_create(). The
2747 * #cairo_scaled_font_t returned from cairo_scaled_font_create() is
2748 * also for the FreeType backend and can be used with functions such
2749 * as cairo_ft_scaled_font_lock_face(). Note that Cairo may keep a reference
2750 * to the FT_Face alive in a font-cache and the exact lifetime of the reference
2751 * depends highly upon the exact usage pattern and is subject to external
2752 * factors. You must not call FT_Done_Face() before the last reference to the
2753 * #cairo_font_face_t has been dropped.
2755 * As an example, below is how one might correctly couple the lifetime of
2756 * the FreeType face object to the #cairo_font_face_t.
2758 * <informalexample><programlisting>
2759 * static const cairo_user_data_key_t key;
2761 * font_face = cairo_ft_font_face_create_for_ft_face (ft_face, 0);
2762 * status = cairo_font_face_set_user_data (font_face, &key,
2763 * ft_face, (cairo_destroy_func_t) FT_Done_Face);
2765 * cairo_font_face_destroy (font_face);
2766 * FT_Done_Face (ft_face);
2769 * </programlisting></informalexample>
2771 * Return value: a newly created #cairo_font_face_t. Free with
2772 * cairo_font_face_destroy() when you are done using it.
2775 cairo_ft_font_face_create_for_ft_face (FT_Face face
,
2778 cairo_ft_unscaled_font_t
*unscaled
;
2779 cairo_font_face_t
*font_face
;
2780 cairo_ft_options_t ft_options
;
2781 cairo_status_t status
;
2783 status
= _cairo_ft_unscaled_font_create_from_face (face
, &unscaled
);
2784 if (unlikely (status
))
2785 return (cairo_font_face_t
*)&_cairo_font_face_nil
;
2787 ft_options
.load_flags
= load_flags
;
2788 ft_options
.extra_flags
= 0;
2789 _cairo_font_options_init_default (&ft_options
.base
);
2791 font_face
= _cairo_ft_font_face_create (unscaled
, &ft_options
);
2792 _cairo_unscaled_font_destroy (&unscaled
->base
);
2798 * cairo_ft_scaled_font_lock_face:
2799 * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
2800 * object can be created by calling cairo_scaled_font_create() on a
2801 * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
2802 * cairo_ft_font_face_create_for_ft_face()).
2804 * cairo_ft_scaled_font_lock_face() gets the #FT_Face object from a FreeType
2805 * backend font and scales it appropriately for the font. You must
2806 * release the face with cairo_ft_scaled_font_unlock_face()
2807 * when you are done using it. Since the #FT_Face object can be
2808 * shared between multiple #cairo_scaled_font_t objects, you must not
2809 * lock any other font objects until you unlock this one. A count is
2810 * kept of the number of times cairo_ft_scaled_font_lock_face() is
2811 * called. cairo_ft_scaled_font_unlock_face() must be called the same number
2814 * You must be careful when using this function in a library or in a
2815 * threaded application, because freetype's design makes it unsafe to
2816 * call freetype functions simultaneously from multiple threads, (even
2817 * if using distinct FT_Face objects). Because of this, application
2818 * code that acquires an FT_Face object with this call must add its
2819 * own locking to protect any use of that object, (and which also must
2820 * protect any other calls into cairo as almost any cairo function
2821 * might result in a call into the freetype library).
2823 * Return value: The #FT_Face object for @font, scaled appropriately,
2824 * or %NULL if @scaled_font is in an error state (see
2825 * cairo_scaled_font_status()) or there is insufficient memory.
2828 cairo_ft_scaled_font_lock_face (cairo_scaled_font_t
*abstract_font
)
2830 cairo_ft_scaled_font_t
*scaled_font
= (cairo_ft_scaled_font_t
*) abstract_font
;
2832 cairo_status_t status
;
2834 if (! _cairo_scaled_font_is_ft (abstract_font
)) {
2835 _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH
);
2839 if (scaled_font
->base
.status
)
2842 face
= _cairo_ft_unscaled_font_lock_face (scaled_font
->unscaled
);
2843 if (unlikely (face
== NULL
)) {
2844 status
= _cairo_scaled_font_set_error (&scaled_font
->base
, CAIRO_STATUS_NO_MEMORY
);
2848 status
= _cairo_ft_unscaled_font_set_scale (scaled_font
->unscaled
,
2849 &scaled_font
->base
.scale
);
2850 if (unlikely (status
)) {
2851 _cairo_ft_unscaled_font_unlock_face (scaled_font
->unscaled
);
2852 status
= _cairo_scaled_font_set_error (&scaled_font
->base
, status
);
2856 /* Note: We deliberately release the unscaled font's mutex here,
2857 * so that we are not holding a lock across two separate calls to
2858 * cairo function, (which would give the application some
2859 * opportunity for creating deadlock. This is obviously unsafe,
2860 * but as documented, the user must add manual locking when using
2862 CAIRO_MUTEX_UNLOCK (scaled_font
->unscaled
->mutex
);
2868 * cairo_ft_scaled_font_unlock_face:
2869 * @scaled_font: A #cairo_scaled_font_t from the FreeType font backend. Such an
2870 * object can be created by calling cairo_scaled_font_create() on a
2871 * FreeType backend font face (see cairo_ft_font_face_create_for_pattern(),
2872 * cairo_ft_font_face_create_for_ft_face()).
2874 * Releases a face obtained with cairo_ft_scaled_font_lock_face().
2877 cairo_ft_scaled_font_unlock_face (cairo_scaled_font_t
*abstract_font
)
2879 cairo_ft_scaled_font_t
*scaled_font
= (cairo_ft_scaled_font_t
*) abstract_font
;
2881 if (! _cairo_scaled_font_is_ft (abstract_font
)) {
2882 _cairo_error_throw (CAIRO_STATUS_FONT_TYPE_MISMATCH
);
2886 if (scaled_font
->base
.status
)
2889 /* Note: We released the unscaled font's mutex at the end of
2890 * cairo_ft_scaled_font_lock_face, so we have to acquire it again
2891 * as _cairo_ft_unscaled_font_unlock_face expects it to be held
2892 * when we call into it. */
2893 CAIRO_MUTEX_LOCK (scaled_font
->unscaled
->mutex
);
2895 _cairo_ft_unscaled_font_unlock_face (scaled_font
->unscaled
);
2898 /* We expose our unscaled font implementation internally for the the
2899 * PDF backend, which needs to keep track of the the different
2900 * fonts-on-disk used by a document, so it can embed them.
2902 cairo_unscaled_font_t
*
2903 _cairo_ft_scaled_font_get_unscaled_font (cairo_scaled_font_t
*abstract_font
)
2905 cairo_ft_scaled_font_t
*scaled_font
= (cairo_ft_scaled_font_t
*) abstract_font
;
2907 return &scaled_font
->unscaled
->base
;
2911 _cairo_ft_scaled_font_is_vertical (cairo_scaled_font_t
*scaled_font
)
2913 cairo_ft_scaled_font_t
*ft_scaled_font
;
2915 if (!_cairo_scaled_font_is_ft (scaled_font
))
2918 ft_scaled_font
= (cairo_ft_scaled_font_t
*) scaled_font
;
2919 if (ft_scaled_font
->ft_options
.load_flags
& FT_LOAD_VERTICAL_LAYOUT
)
2925 _cairo_ft_scaled_font_get_load_flags (cairo_scaled_font_t
*scaled_font
)
2927 cairo_ft_scaled_font_t
*ft_scaled_font
;
2929 if (! _cairo_scaled_font_is_ft (scaled_font
))
2932 ft_scaled_font
= (cairo_ft_scaled_font_t
*) scaled_font
;
2933 return ft_scaled_font
->ft_options
.load_flags
;
2937 _cairo_ft_font_reset_static_data (void)
2939 _cairo_ft_unscaled_font_map_destroy ();