Tizen 2.0 Release
[framework/graphics/cairo.git] / src / cairo-scaled-font.c
1 /* -*- Mode: c; c-basic-offset: 4; indent-tabs-mode: t; tab-width: 8; -*- */
2 /*
3  * Copyright © 2005 Keith Packard
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it either under the terms of the GNU Lesser General Public
7  * License version 2.1 as published by the Free Software Foundation
8  * (the "LGPL") or, at your option, under the terms of the Mozilla
9  * Public License Version 1.1 (the "MPL"). If you do not alter this
10  * notice, a recipient may use your version of this file under either
11  * the MPL or the LGPL.
12  *
13  * You should have received a copy of the LGPL along with this library
14  * in the file COPYING-LGPL-2.1; if not, write to the Free Software
15  * Foundation, Inc., 51 Franklin Street, Suite 500, Boston, MA 02110-1335, USA
16  * You should have received a copy of the MPL along with this library
17  * in the file COPYING-MPL-1.1
18  *
19  * The contents of this file are subject to the Mozilla Public License
20  * Version 1.1 (the "License"); you may not use this file except in
21  * compliance with the License. You may obtain a copy of the License at
22  * http://www.mozilla.org/MPL/
23  *
24  * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY
25  * OF ANY KIND, either express or implied. See the LGPL or the MPL for
26  * the specific language governing rights and limitations.
27  *
28  * The Original Code is the cairo graphics library.
29  *
30  * The Initial Developer of the Original Code is Keith Packard
31  *
32  * Contributor(s):
33  *      Keith Packard <keithp@keithp.com>
34  *      Carl D. Worth <cworth@cworth.org>
35  *      Graydon Hoare <graydon@redhat.com>
36  *      Owen Taylor <otaylor@redhat.com>
37  *      Behdad Esfahbod <behdad@behdad.org>
38  *      Chris Wilson <chris@chris-wilson.co.uk>
39  */
40
41 #include "cairoint.h"
42 #include "cairo-error-private.h"
43 #include "cairo-image-surface-private.h"
44 #include "cairo-list-inline.h"
45 #include "cairo-pattern-private.h"
46 #include "cairo-scaled-font-private.h"
47 #include "cairo-surface-backend-private.h"
48
49 #define TOLERANCE 0.00001
50
51 #if _XOPEN_SOURCE >= 600 || defined (_ISOC99_SOURCE)
52 #define ISFINITE(x) isfinite (x)
53 #else
54 #define ISFINITE(x) ((x) * (x) >= 0.) /* check for NaNs */
55 #endif
56
57 /**
58  * SECTION:cairo-scaled-font
59  * @Title: cairo_scaled_font_t
60  * @Short_Description: Font face at particular size and options
61  * @See_Also: #cairo_font_face_t, #cairo_matrix_t, #cairo_font_options_t
62  *
63  * #cairo_scaled_font_t represents a realization of a font face at a particular
64  * size and transformation and a certain set of font options.
65  **/
66
67 static uint32_t
68 _cairo_scaled_font_compute_hash (cairo_scaled_font_t *scaled_font);
69
70 /* Global Glyph Cache
71  *
72  * We maintain a global pool of glyphs split between all active fonts. This
73  * allows a heavily used individual font to cache more glyphs than we could
74  * manage if we used per-font glyph caches, but at the same time maintains
75  * fairness across all fonts and provides a cap on the maximum number of
76  * global glyphs.
77  *
78  * The glyphs are allocated in pages, which are capped in the global pool.
79  * Using pages means we can reduce the frequency at which we have to probe the
80  * global pool and ameliorates the memory allocation pressure.
81  */
82
83 /* XXX: This number is arbitrary---we've never done any measurement of this. */
84 #define MAX_GLYPH_PAGES_CACHED 512
85 static cairo_cache_t cairo_scaled_glyph_page_cache;
86
87 #define CAIRO_SCALED_GLYPH_PAGE_SIZE 32
88 struct _cairo_scaled_glyph_page {
89     cairo_cache_entry_t cache_entry;
90
91     cairo_list_t link;
92
93     unsigned int num_glyphs;
94     cairo_scaled_glyph_t glyphs[CAIRO_SCALED_GLYPH_PAGE_SIZE];
95 };
96
97 /*
98  *  Notes:
99  *
100  *  To store rasterizations of glyphs, we use an image surface and the
101  *  device offset to represent the glyph origin.
102  *
103  *  A device_transform converts from device space (a conceptual space) to
104  *  surface space.  For simple cases of translation only, it's called a
105  *  device_offset and is public API (cairo_surface_[gs]et_device_offset()).
106  *  A possibly better name for those functions could have been
107  *  cairo_surface_[gs]et_origin().  So, that's what they do: they set where
108  *  the device-space origin (0,0) is in the surface.  If the origin is inside
109  *  the surface, device_offset values are positive.  It may look like this:
110  *
111  *  Device space:
112  *        (-x,-y) <-- negative numbers
113  *           +----------------+
114  *           |      .         |
115  *           |      .         |
116  *           |......(0,0) <---|-- device-space origin
117  *           |                |
118  *           |                |
119  *           +----------------+
120  *                    (width-x,height-y)
121  *
122  *  Surface space:
123  *         (0,0) <-- surface-space origin
124  *           +---------------+
125  *           |      .        |
126  *           |      .        |
127  *           |......(x,y) <--|-- device_offset
128  *           |               |
129  *           |               |
130  *           +---------------+
131  *                     (width,height)
132  *
133  *  In other words: device_offset is the coordinates of the device-space
134  *  origin relative to the top-left of the surface.
135  *
136  *  We use device offsets in a couple of places:
137  *
138  *    - Public API: To let toolkits like Gtk+ give user a surface that
139  *      only represents part of the final destination (say, the expose
140  *      area), but has the same device space as the destination.  In these
141  *      cases device_offset is typically negative.  Example:
142  *
143  *           application window
144  *           +---------------+
145  *           |      .        |
146  *           | (x,y).        |
147  *           |......+---+    |
148  *           |      |   | <--|-- expose area
149  *           |      +---+    |
150  *           +---------------+
151  *
152  *      In this case, the user of cairo API can set the device_space on
153  *      the expose area to (-x,-y) to move the device space origin to that
154  *      of the application window, such that drawing in the expose area
155  *      surface and painting it in the application window has the same
156  *      effect as drawing in the application window directly.  Gtk+ has
157  *      been using this feature.
158  *
159  *    - Glyph surfaces: In most font rendering systems, glyph surfaces
160  *      have an origin at (0,0) and a bounding box that is typically
161  *      represented as (x_bearing,y_bearing,width,height).  Depending on
162  *      which way y progresses in the system, y_bearing may typically be
163  *      negative (for systems similar to cairo, with origin at top left),
164  *      or be positive (in systems like PDF with origin at bottom left).
165  *      No matter which is the case, it is important to note that
166  *      (x_bearing,y_bearing) is the coordinates of top-left of the glyph
167  *      relative to the glyph origin.  That is, for example:
168  *
169  *      Scaled-glyph space:
170  *
171  *        (x_bearing,y_bearing) <-- negative numbers
172  *           +----------------+
173  *           |      .         |
174  *           |      .         |
175  *           |......(0,0) <---|-- glyph origin
176  *           |                |
177  *           |                |
178  *           +----------------+
179  *                    (width+x_bearing,height+y_bearing)
180  *
181  *      Note the similarity of the origin to the device space.  That is
182  *      exactly how we use the device_offset to represent scaled glyphs:
183  *      to use the device-space origin as the glyph origin.
184  *
185  *  Now compare the scaled-glyph space to device-space and surface-space
186  *  and convince yourself that:
187  *
188  *      (x_bearing,y_bearing) = (-x,-y) = - device_offset
189  *
190  *  That's right.  If you are not convinced yet, contrast the definition
191  *  of the two:
192  *
193  *      "(x_bearing,y_bearing) is the coordinates of top-left of the
194  *       glyph relative to the glyph origin."
195  *
196  *      "In other words: device_offset is the coordinates of the
197  *       device-space origin relative to the top-left of the surface."
198  *
199  *  and note that glyph origin = device-space origin.
200  */
201
202 static void
203 _cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font);
204
205 static void
206 _cairo_scaled_glyph_fini (cairo_scaled_font_t *scaled_font,
207                           cairo_scaled_glyph_t *scaled_glyph)
208 {
209     while (! cairo_list_is_empty (&scaled_glyph->dev_privates)) {
210         cairo_scaled_glyph_private_t *private =
211             cairo_list_first_entry (&scaled_glyph->dev_privates,
212                                     cairo_scaled_glyph_private_t,
213                                     link);
214         private->destroy (private, scaled_glyph, scaled_font);
215     }
216
217     _cairo_image_scaled_glyph_fini (scaled_font, scaled_glyph);
218
219     if (scaled_glyph->surface != NULL)
220         cairo_surface_destroy (&scaled_glyph->surface->base);
221
222     if (scaled_glyph->path != NULL)
223         _cairo_path_fixed_destroy (scaled_glyph->path);
224
225     if (scaled_glyph->recording_surface != NULL) {
226         cairo_surface_finish (scaled_glyph->recording_surface);
227         cairo_surface_destroy (scaled_glyph->recording_surface);
228     }
229 }
230
231 #define ZOMBIE 0
232 static const cairo_scaled_font_t _cairo_scaled_font_nil = {
233     { ZOMBIE },                 /* hash_entry */
234     CAIRO_STATUS_NO_MEMORY,     /* status */
235     CAIRO_REFERENCE_COUNT_INVALID,      /* ref_count */
236     { 0, 0, 0, NULL },          /* user_data */
237     NULL,                       /* original_font_face */
238     NULL,                       /* font_face */
239     { 1., 0., 0., 1., 0, 0},    /* font_matrix */
240     { 1., 0., 0., 1., 0, 0},    /* ctm */
241     { CAIRO_ANTIALIAS_DEFAULT,  /* options */
242       CAIRO_SUBPIXEL_ORDER_DEFAULT,
243       CAIRO_HINT_STYLE_DEFAULT,
244       CAIRO_HINT_METRICS_DEFAULT} ,
245     FALSE,                      /* placeholder */
246     FALSE,                      /* holdover */
247     TRUE,                       /* finished */
248     { 1., 0., 0., 1., 0, 0},    /* scale */
249     { 1., 0., 0., 1., 0, 0},    /* scale_inverse */
250     1.,                         /* max_scale */
251     { 0., 0., 0., 0., 0. },     /* extents */
252     { 0., 0., 0., 0., 0. },     /* fs_extents */
253     CAIRO_MUTEX_NIL_INITIALIZER,/* mutex */
254     NULL,                       /* glyphs */
255     { NULL, NULL },             /* pages */
256     FALSE,                      /* cache_frozen */
257     FALSE,                      /* global_cache_frozen */
258     { NULL, NULL },             /* privates */
259     NULL                        /* backend */
260 };
261
262 /**
263  * _cairo_scaled_font_set_error:
264  * @scaled_font: a scaled_font
265  * @status: a status value indicating an error
266  *
267  * Atomically sets scaled_font->status to @status and calls _cairo_error;
268  * Does nothing if status is %CAIRO_STATUS_SUCCESS.
269  *
270  * All assignments of an error status to scaled_font->status should happen
271  * through _cairo_scaled_font_set_error(). Note that due to the nature of
272  * the atomic operation, it is not safe to call this function on the nil
273  * objects.
274  *
275  * The purpose of this function is to allow the user to set a
276  * breakpoint in _cairo_error() to generate a stack trace for when the
277  * user causes cairo to detect an error.
278  *
279  * Return value: the error status.
280  **/
281 cairo_status_t
282 _cairo_scaled_font_set_error (cairo_scaled_font_t *scaled_font,
283                               cairo_status_t status)
284 {
285     if (status == CAIRO_STATUS_SUCCESS)
286         return status;
287
288     /* Don't overwrite an existing error. This preserves the first
289      * error, which is the most significant. */
290     _cairo_status_set_error (&scaled_font->status, status);
291
292     return _cairo_error (status);
293 }
294
295 /**
296  * cairo_scaled_font_get_type:
297  * @scaled_font: a #cairo_scaled_font_t
298  *
299  * This function returns the type of the backend used to create
300  * a scaled font. See #cairo_font_type_t for available types.
301  * However, this function never returns %CAIRO_FONT_TYPE_TOY.
302  *
303  * Return value: The type of @scaled_font.
304  *
305  * Since: 1.2
306  **/
307 cairo_font_type_t
308 cairo_scaled_font_get_type (cairo_scaled_font_t *scaled_font)
309 {
310     if (CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
311         return CAIRO_FONT_TYPE_TOY;
312
313     return scaled_font->backend->type;
314 }
315
316 /**
317  * cairo_scaled_font_status:
318  * @scaled_font: a #cairo_scaled_font_t
319  *
320  * Checks whether an error has previously occurred for this
321  * scaled_font.
322  *
323  * Return value: %CAIRO_STATUS_SUCCESS or another error such as
324  *   %CAIRO_STATUS_NO_MEMORY.
325  *
326  * Since: 1.0
327  **/
328 cairo_status_t
329 cairo_scaled_font_status (cairo_scaled_font_t *scaled_font)
330 {
331     return scaled_font->status;
332 }
333 slim_hidden_def (cairo_scaled_font_status);
334
335 /* Here we keep a unique mapping from
336  * font_face/matrix/ctm/font_options => #cairo_scaled_font_t.
337  *
338  * Here are the things that we want to map:
339  *
340  *  a) All otherwise referenced #cairo_scaled_font_t's
341  *  b) Some number of not otherwise referenced #cairo_scaled_font_t's
342  *
343  * The implementation uses a hash table which covers (a)
344  * completely. Then, for (b) we have an array of otherwise
345  * unreferenced fonts (holdovers) which are expired in
346  * least-recently-used order.
347  *
348  * The cairo_scaled_font_create() code gets to treat this like a regular
349  * hash table. All of the magic for the little holdover cache is in
350  * cairo_scaled_font_reference() and cairo_scaled_font_destroy().
351  */
352
353 /* This defines the size of the holdover array ... that is, the number
354  * of scaled fonts we keep around even when not otherwise referenced
355  */
356 #define CAIRO_SCALED_FONT_MAX_HOLDOVERS 256
357
358 typedef struct _cairo_scaled_font_map {
359     cairo_scaled_font_t *mru_scaled_font;
360     cairo_hash_table_t *hash_table;
361     cairo_scaled_font_t *holdovers[CAIRO_SCALED_FONT_MAX_HOLDOVERS];
362     int num_holdovers;
363 } cairo_scaled_font_map_t;
364
365 static cairo_scaled_font_map_t *cairo_scaled_font_map;
366
367 static int
368 _cairo_scaled_font_keys_equal (const void *abstract_key_a, const void *abstract_key_b);
369
370 static cairo_scaled_font_map_t *
371 _cairo_scaled_font_map_lock (void)
372 {
373     CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
374
375     if (cairo_scaled_font_map == NULL) {
376         cairo_scaled_font_map = malloc (sizeof (cairo_scaled_font_map_t));
377         if (unlikely (cairo_scaled_font_map == NULL))
378             goto CLEANUP_MUTEX_LOCK;
379
380         cairo_scaled_font_map->mru_scaled_font = NULL;
381         cairo_scaled_font_map->hash_table =
382             _cairo_hash_table_create (_cairo_scaled_font_keys_equal);
383
384         if (unlikely (cairo_scaled_font_map->hash_table == NULL))
385             goto CLEANUP_SCALED_FONT_MAP;
386
387         cairo_scaled_font_map->num_holdovers = 0;
388     }
389
390     return cairo_scaled_font_map;
391
392  CLEANUP_SCALED_FONT_MAP:
393     free (cairo_scaled_font_map);
394     cairo_scaled_font_map = NULL;
395  CLEANUP_MUTEX_LOCK:
396     CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
397     _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
398     return NULL;
399 }
400
401 static void
402 _cairo_scaled_font_map_unlock (void)
403 {
404    CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
405 }
406
407 void
408 _cairo_scaled_font_map_destroy (void)
409 {
410     cairo_scaled_font_map_t *font_map;
411     cairo_scaled_font_t *scaled_font;
412
413     CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
414
415     font_map = cairo_scaled_font_map;
416     if (unlikely (font_map == NULL)) {
417         goto CLEANUP_MUTEX_LOCK;
418     }
419
420     scaled_font = font_map->mru_scaled_font;
421     if (scaled_font != NULL) {
422         CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
423         cairo_scaled_font_destroy (scaled_font);
424         CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
425     }
426
427     /* remove scaled_fonts starting from the end so that font_map->holdovers
428      * is always in a consistent state when we release the mutex. */
429     while (font_map->num_holdovers) {
430         scaled_font = font_map->holdovers[font_map->num_holdovers-1];
431         assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
432         _cairo_hash_table_remove (font_map->hash_table,
433                                   &scaled_font->hash_entry);
434
435         font_map->num_holdovers--;
436
437         /* This releases the font_map lock to avoid the possibility of a
438          * recursive deadlock when the scaled font destroy closure gets
439          * called
440          */
441         _cairo_scaled_font_fini (scaled_font);
442
443         free (scaled_font);
444     }
445
446     _cairo_hash_table_destroy (font_map->hash_table);
447
448     free (cairo_scaled_font_map);
449     cairo_scaled_font_map = NULL;
450
451  CLEANUP_MUTEX_LOCK:
452     CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
453 }
454 static void
455 _cairo_scaled_glyph_page_destroy (void *closure)
456 {
457     cairo_scaled_glyph_page_t *page = closure;
458     cairo_scaled_font_t *scaled_font;
459     unsigned int n;
460
461     assert (! cairo_list_is_empty (&page->link));
462
463     scaled_font = (cairo_scaled_font_t *) page->cache_entry.hash;
464     for (n = 0; n < page->num_glyphs; n++) {
465         _cairo_hash_table_remove (scaled_font->glyphs,
466                                   &page->glyphs[n].hash_entry);
467         _cairo_scaled_glyph_fini (scaled_font, &page->glyphs[n]);
468     }
469
470     cairo_list_del (&page->link);
471
472     free (page);
473 }
474
475 /* If a scaled font wants to unlock the font map while still being
476  * created (needed for user-fonts), we need to take extra care not
477  * ending up with multiple identical scaled fonts being created.
478  *
479  * What we do is, we create a fake identical scaled font, and mark
480  * it as placeholder, lock its mutex, and insert that in the fontmap
481  * hash table.  This makes other code trying to create an identical
482  * scaled font to just wait and retry.
483  *
484  * The reason we have to create a fake scaled font instead of just using
485  * scaled_font is for lifecycle management: we need to (or rather,
486  * other code needs to) reference the scaled_font in the hash table.
487  * We can't do that on the input scaled_font as it may be freed by
488  * font backend upon error.
489  */
490
491 cairo_status_t
492 _cairo_scaled_font_register_placeholder_and_unlock_font_map (cairo_scaled_font_t *scaled_font)
493 {
494     cairo_status_t status;
495     cairo_scaled_font_t *placeholder_scaled_font;
496
497     assert (CAIRO_MUTEX_IS_LOCKED (_cairo_scaled_font_map_mutex));
498
499     status = scaled_font->status;
500     if (unlikely (status))
501         return status;
502
503     placeholder_scaled_font = malloc (sizeof (cairo_scaled_font_t));
504     if (unlikely (placeholder_scaled_font == NULL))
505         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
506
507     /* full initialization is wasteful, but who cares... */
508     status = _cairo_scaled_font_init (placeholder_scaled_font,
509                                       scaled_font->font_face,
510                                       &scaled_font->font_matrix,
511                                       &scaled_font->ctm,
512                                       &scaled_font->options,
513                                       NULL);
514     if (unlikely (status))
515         goto FREE_PLACEHOLDER;
516
517     placeholder_scaled_font->placeholder = TRUE;
518
519     placeholder_scaled_font->hash_entry.hash
520         = _cairo_scaled_font_compute_hash (placeholder_scaled_font);
521     status = _cairo_hash_table_insert (cairo_scaled_font_map->hash_table,
522                                        &placeholder_scaled_font->hash_entry);
523     if (unlikely (status))
524         goto FINI_PLACEHOLDER;
525
526     CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
527     CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex);
528
529     return CAIRO_STATUS_SUCCESS;
530
531   FINI_PLACEHOLDER:
532     _cairo_scaled_font_fini_internal (placeholder_scaled_font);
533   FREE_PLACEHOLDER:
534     free (placeholder_scaled_font);
535
536     return _cairo_scaled_font_set_error (scaled_font, status);
537 }
538
539 void
540 _cairo_scaled_font_unregister_placeholder_and_lock_font_map (cairo_scaled_font_t *scaled_font)
541 {
542     cairo_scaled_font_t *placeholder_scaled_font;
543
544     CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
545
546     /* temporary hash value to match the placeholder */
547     scaled_font->hash_entry.hash
548         = _cairo_scaled_font_compute_hash (scaled_font);
549     placeholder_scaled_font =
550         _cairo_hash_table_lookup (cairo_scaled_font_map->hash_table,
551                                   &scaled_font->hash_entry);
552     assert (placeholder_scaled_font != NULL);
553     assert (placeholder_scaled_font->placeholder);
554     assert (CAIRO_MUTEX_IS_LOCKED (placeholder_scaled_font->mutex));
555
556     _cairo_hash_table_remove (cairo_scaled_font_map->hash_table,
557                               &placeholder_scaled_font->hash_entry);
558
559     CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
560
561     CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex);
562     cairo_scaled_font_destroy (placeholder_scaled_font);
563
564     CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
565 }
566
567 static void
568 _cairo_scaled_font_placeholder_wait_for_creation_to_finish (cairo_scaled_font_t *placeholder_scaled_font)
569 {
570     /* reference the place holder so it doesn't go away */
571     cairo_scaled_font_reference (placeholder_scaled_font);
572
573     /* now unlock the fontmap mutex so creation has a chance to finish */
574     CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
575
576     /* wait on placeholder mutex until we are awaken */
577     CAIRO_MUTEX_LOCK (placeholder_scaled_font->mutex);
578
579     /* ok, creation done.  just clean up and back out */
580     CAIRO_MUTEX_UNLOCK (placeholder_scaled_font->mutex);
581     cairo_scaled_font_destroy (placeholder_scaled_font);
582
583     CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
584 }
585
586 /* Fowler / Noll / Vo (FNV) Hash (http://www.isthe.com/chongo/tech/comp/fnv/)
587  *
588  * Not necessarily better than a lot of other hashes, but should be OK, and
589  * well tested with binary data.
590  */
591
592 #define FNV_32_PRIME ((uint32_t)0x01000193)
593 #define FNV1_32_INIT ((uint32_t)0x811c9dc5)
594
595 static uint32_t
596 _hash_matrix_fnv (const cairo_matrix_t  *matrix,
597                   uint32_t               hval)
598 {
599     const uint8_t *buffer = (const uint8_t *) matrix;
600     int len = sizeof (cairo_matrix_t);
601     do {
602         hval *= FNV_32_PRIME;
603         hval ^= *buffer++;
604     } while (--len);
605
606     return hval;
607 }
608
609 static uint32_t
610 _hash_mix_bits (uint32_t hash)
611 {
612     hash += hash << 12;
613     hash ^= hash >> 7;
614     hash += hash << 3;
615     hash ^= hash >> 17;
616     hash += hash << 5;
617     return hash;
618 }
619
620 static uint32_t
621 _cairo_scaled_font_compute_hash (cairo_scaled_font_t *scaled_font)
622 {
623     uint32_t hash = FNV1_32_INIT;
624
625     /* We do a bytewise hash on the font matrices */
626     hash = _hash_matrix_fnv (&scaled_font->font_matrix, hash);
627     hash = _hash_matrix_fnv (&scaled_font->ctm, hash);
628     hash = _hash_mix_bits (hash);
629
630     hash ^= (unsigned long) scaled_font->original_font_face;
631     hash ^= cairo_font_options_hash (&scaled_font->options);
632
633     /* final mixing of bits */
634     hash = _hash_mix_bits (hash);
635     assert (hash != ZOMBIE);
636
637     return hash;
638 }
639
640 static void
641 _cairo_scaled_font_init_key (cairo_scaled_font_t        *scaled_font,
642                              cairo_font_face_t          *font_face,
643                              const cairo_matrix_t       *font_matrix,
644                              const cairo_matrix_t       *ctm,
645                              const cairo_font_options_t *options)
646 {
647     scaled_font->status = CAIRO_STATUS_SUCCESS;
648     scaled_font->placeholder = FALSE;
649     scaled_font->font_face = font_face;
650     scaled_font->original_font_face = font_face;
651     scaled_font->font_matrix = *font_matrix;
652     scaled_font->ctm = *ctm;
653     /* ignore translation values in the ctm */
654     scaled_font->ctm.x0 = 0.;
655     scaled_font->ctm.y0 = 0.;
656     _cairo_font_options_init_copy (&scaled_font->options, options);
657
658     scaled_font->hash_entry.hash =
659         _cairo_scaled_font_compute_hash (scaled_font);
660 }
661
662 static cairo_bool_t
663 _cairo_scaled_font_keys_equal (const void *abstract_key_a,
664                                const void *abstract_key_b)
665 {
666     const cairo_scaled_font_t *key_a = abstract_key_a;
667     const cairo_scaled_font_t *key_b = abstract_key_b;
668
669     return key_a->original_font_face == key_b->original_font_face &&
670             memcmp ((unsigned char *)(&key_a->font_matrix.xx),
671                     (unsigned char *)(&key_b->font_matrix.xx),
672                     sizeof(cairo_matrix_t)) == 0 &&
673             memcmp ((unsigned char *)(&key_a->ctm.xx),
674                     (unsigned char *)(&key_b->ctm.xx),
675                     sizeof(cairo_matrix_t)) == 0 &&
676             cairo_font_options_equal (&key_a->options, &key_b->options);
677 }
678
679 static cairo_bool_t
680 _cairo_scaled_font_matches (const cairo_scaled_font_t *scaled_font,
681                             const cairo_font_face_t *font_face,
682                             const cairo_matrix_t *font_matrix,
683                             const cairo_matrix_t *ctm,
684                             const cairo_font_options_t *options)
685 {
686     return scaled_font->original_font_face == font_face &&
687             memcmp ((unsigned char *)(&scaled_font->font_matrix.xx),
688                     (unsigned char *)(&font_matrix->xx),
689                     sizeof(cairo_matrix_t)) == 0 &&
690             memcmp ((unsigned char *)(&scaled_font->ctm.xx),
691                     (unsigned char *)(&ctm->xx),
692                     sizeof(cairo_matrix_t)) == 0 &&
693             cairo_font_options_equal (&scaled_font->options, options);
694 }
695
696 /*
697  * Basic #cairo_scaled_font_t object management
698  */
699
700 cairo_status_t
701 _cairo_scaled_font_init (cairo_scaled_font_t               *scaled_font,
702                          cairo_font_face_t                 *font_face,
703                          const cairo_matrix_t              *font_matrix,
704                          const cairo_matrix_t              *ctm,
705                          const cairo_font_options_t        *options,
706                          const cairo_scaled_font_backend_t *backend)
707 {
708     cairo_status_t status;
709
710     status = cairo_font_options_status ((cairo_font_options_t *) options);
711     if (unlikely (status))
712         return status;
713
714     scaled_font->status = CAIRO_STATUS_SUCCESS;
715     scaled_font->placeholder = FALSE;
716     scaled_font->font_face = font_face;
717     scaled_font->original_font_face = font_face;
718     scaled_font->font_matrix = *font_matrix;
719     scaled_font->ctm = *ctm;
720     /* ignore translation values in the ctm */
721     scaled_font->ctm.x0 = 0.;
722     scaled_font->ctm.y0 = 0.;
723     _cairo_font_options_init_copy (&scaled_font->options, options);
724
725     cairo_matrix_multiply (&scaled_font->scale,
726                            &scaled_font->font_matrix,
727                            &scaled_font->ctm);
728
729     scaled_font->max_scale = MAX (fabs (scaled_font->scale.xx) + fabs (scaled_font->scale.xy),
730                                   fabs (scaled_font->scale.yx) + fabs (scaled_font->scale.yy));
731     scaled_font->scale_inverse = scaled_font->scale;
732     status = cairo_matrix_invert (&scaled_font->scale_inverse);
733     if (unlikely (status)) {
734         /* If the font scale matrix is rank 0, just using an all-zero inverse matrix
735          * makes everything work correctly.  This make font size 0 work without
736          * producing an error.
737          *
738          * FIXME:  If the scale is rank 1, we still go into error mode.  But then
739          * again, that's what we do everywhere in cairo.
740          *
741          * Also, the check for == 0. below may be too harsh...
742          */
743         if (_cairo_matrix_is_scale_0 (&scaled_font->scale)) {
744             cairo_matrix_init (&scaled_font->scale_inverse,
745                                0, 0, 0, 0,
746                                -scaled_font->scale.x0,
747                                -scaled_font->scale.y0);
748         } else
749             return status;
750     }
751
752     scaled_font->glyphs = _cairo_hash_table_create (NULL);
753     if (unlikely (scaled_font->glyphs == NULL))
754         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
755
756     cairo_list_init (&scaled_font->glyph_pages);
757     scaled_font->cache_frozen = FALSE;
758     scaled_font->global_cache_frozen = FALSE;
759
760     scaled_font->holdover = FALSE;
761     scaled_font->finished = FALSE;
762
763     CAIRO_REFERENCE_COUNT_INIT (&scaled_font->ref_count, 1);
764
765     _cairo_user_data_array_init (&scaled_font->user_data);
766
767     cairo_font_face_reference (font_face);
768     scaled_font->original_font_face = NULL;
769
770     CAIRO_MUTEX_INIT (scaled_font->mutex);
771
772     cairo_list_init (&scaled_font->dev_privates);
773
774     scaled_font->backend = backend;
775     cairo_list_init (&scaled_font->link);
776
777     return CAIRO_STATUS_SUCCESS;
778 }
779
780 void
781 _cairo_scaled_font_freeze_cache (cairo_scaled_font_t *scaled_font)
782 {
783     /* ensure we do not modify an error object */
784     assert (scaled_font->status == CAIRO_STATUS_SUCCESS);
785
786     CAIRO_MUTEX_LOCK (scaled_font->mutex);
787     scaled_font->cache_frozen = TRUE;
788 }
789
790 void
791 _cairo_scaled_font_thaw_cache (cairo_scaled_font_t *scaled_font)
792 {
793     scaled_font->cache_frozen = FALSE;
794
795     if (scaled_font->global_cache_frozen) {
796         CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
797         _cairo_cache_thaw (&cairo_scaled_glyph_page_cache);
798         CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
799
800         scaled_font->global_cache_frozen = FALSE;
801     }
802
803     CAIRO_MUTEX_UNLOCK (scaled_font->mutex);
804 }
805
806 void
807 _cairo_scaled_font_reset_cache (cairo_scaled_font_t *scaled_font)
808 {
809     assert (! scaled_font->cache_frozen);
810
811     CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
812     while (! cairo_list_is_empty (&scaled_font->glyph_pages)) {
813         _cairo_cache_remove (&cairo_scaled_glyph_page_cache,
814                              &cairo_list_first_entry (&scaled_font->glyph_pages,
815                                                       cairo_scaled_glyph_page_t,
816                                                       link)->cache_entry);
817     }
818     CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
819 }
820
821 cairo_status_t
822 _cairo_scaled_font_set_metrics (cairo_scaled_font_t         *scaled_font,
823                                 cairo_font_extents_t        *fs_metrics)
824 {
825     cairo_status_t status;
826     double  font_scale_x, font_scale_y;
827
828     scaled_font->fs_extents = *fs_metrics;
829
830     status = _cairo_matrix_compute_basis_scale_factors (&scaled_font->font_matrix,
831                                                   &font_scale_x, &font_scale_y,
832                                                   1);
833     if (unlikely (status))
834         return status;
835
836     /*
837      * The font responded in unscaled units, scale by the font
838      * matrix scale factors to get to user space
839      */
840
841     scaled_font->extents.ascent = fs_metrics->ascent * font_scale_y;
842     scaled_font->extents.descent = fs_metrics->descent * font_scale_y;
843     scaled_font->extents.height = fs_metrics->height * font_scale_y;
844     scaled_font->extents.max_x_advance = fs_metrics->max_x_advance * font_scale_x;
845     scaled_font->extents.max_y_advance = fs_metrics->max_y_advance * font_scale_y;
846
847     return CAIRO_STATUS_SUCCESS;
848 }
849
850 static void
851 _cairo_scaled_font_fini_internal (cairo_scaled_font_t *scaled_font)
852 {
853     scaled_font->finished = TRUE;
854
855     _cairo_scaled_font_reset_cache (scaled_font);
856     _cairo_hash_table_destroy (scaled_font->glyphs);
857
858     cairo_font_face_destroy (scaled_font->font_face);
859     cairo_font_face_destroy (scaled_font->original_font_face);
860
861     CAIRO_MUTEX_FINI (scaled_font->mutex);
862
863     while (! cairo_list_is_empty (&scaled_font->dev_privates)) {
864         cairo_scaled_font_private_t *private =
865             cairo_list_first_entry (&scaled_font->dev_privates,
866                                     cairo_scaled_font_private_t,
867                                     link);
868         private->destroy (private, scaled_font);
869     }
870
871     if (scaled_font->backend != NULL && scaled_font->backend->fini != NULL)
872         scaled_font->backend->fini (scaled_font);
873
874     _cairo_user_data_array_fini (&scaled_font->user_data);
875 }
876
877 void
878 _cairo_scaled_font_fini (cairo_scaled_font_t *scaled_font)
879 {
880     /* Release the lock to avoid the possibility of a recursive
881      * deadlock when the scaled font destroy closure gets called. */
882     CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_map_mutex);
883     _cairo_scaled_font_fini_internal (scaled_font);
884     CAIRO_MUTEX_LOCK (_cairo_scaled_font_map_mutex);
885 }
886
887 void
888 _cairo_scaled_font_attach_private (cairo_scaled_font_t *scaled_font,
889                                    cairo_scaled_font_private_t *private,
890                                    const void *key,
891                                    void (*destroy) (cairo_scaled_font_private_t *,
892                                                     cairo_scaled_font_t *))
893 {
894     private->key = key;
895     private->destroy = destroy;
896     cairo_list_add (&private->link, &scaled_font->dev_privates);
897 }
898
899 cairo_scaled_font_private_t *
900 _cairo_scaled_font_find_private (cairo_scaled_font_t *scaled_font,
901                                  const void *key)
902 {
903     cairo_scaled_font_private_t *priv;
904
905     cairo_list_foreach_entry (priv, cairo_scaled_font_private_t,
906                               &scaled_font->dev_privates, link)
907     {
908         if (priv->key == key) {
909             if (priv->link.prev != &scaled_font->dev_privates)
910                 cairo_list_move (&priv->link, &scaled_font->dev_privates);
911             return priv;
912         }
913     }
914
915     return NULL;
916 }
917
918 void
919 _cairo_scaled_glyph_attach_private (cairo_scaled_glyph_t *scaled_glyph,
920                                    cairo_scaled_glyph_private_t *private,
921                                    const void *key,
922                                    void (*destroy) (cairo_scaled_glyph_private_t *,
923                                                     cairo_scaled_glyph_t *,
924                                                     cairo_scaled_font_t *))
925 {
926     private->key = key;
927     private->destroy = destroy;
928     cairo_list_add (&private->link, &scaled_glyph->dev_privates);
929 }
930
931 cairo_scaled_glyph_private_t *
932 _cairo_scaled_glyph_find_private (cairo_scaled_glyph_t *scaled_glyph,
933                                  const void *key)
934 {
935     cairo_scaled_glyph_private_t *priv;
936
937     cairo_list_foreach_entry (priv, cairo_scaled_glyph_private_t,
938                               &scaled_glyph->dev_privates, link)
939     {
940         if (priv->key == key) {
941             if (priv->link.prev != &scaled_glyph->dev_privates)
942                 cairo_list_move (&priv->link, &scaled_glyph->dev_privates);
943             return priv;
944         }
945     }
946
947     return NULL;
948 }
949
950 /**
951  * cairo_scaled_font_create:
952  * @font_face: a #cairo_font_face_t
953  * @font_matrix: font space to user space transformation matrix for the
954  *       font. In the simplest case of a N point font, this matrix is
955  *       just a scale by N, but it can also be used to shear the font
956  *       or stretch it unequally along the two axes. See
957  *       cairo_set_font_matrix().
958  * @ctm: user to device transformation matrix with which the font will
959  *       be used.
960  * @options: options to use when getting metrics for the font and
961  *           rendering with it.
962  *
963  * Creates a #cairo_scaled_font_t object from a font face and matrices that
964  * describe the size of the font and the environment in which it will
965  * be used.
966  *
967  * Return value: a newly created #cairo_scaled_font_t. Destroy with
968  *  cairo_scaled_font_destroy()
969  *
970  * Since: 1.0
971  **/
972 cairo_scaled_font_t *
973 cairo_scaled_font_create (cairo_font_face_t          *font_face,
974                           const cairo_matrix_t       *font_matrix,
975                           const cairo_matrix_t       *ctm,
976                           const cairo_font_options_t *options)
977 {
978     cairo_status_t status;
979     cairo_scaled_font_map_t *font_map;
980     cairo_font_face_t *original_font_face = font_face;
981     cairo_scaled_font_t key, *old = NULL, *scaled_font = NULL, *dead = NULL;
982     double det;
983
984     status = font_face->status;
985     if (unlikely (status))
986         return _cairo_scaled_font_create_in_error (status);
987
988     det = _cairo_matrix_compute_determinant (font_matrix);
989     if (! ISFINITE (det))
990         return _cairo_scaled_font_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_MATRIX));
991
992     det = _cairo_matrix_compute_determinant (ctm);
993     if (! ISFINITE (det))
994         return _cairo_scaled_font_create_in_error (_cairo_error (CAIRO_STATUS_INVALID_MATRIX));
995
996     status = cairo_font_options_status ((cairo_font_options_t *) options);
997     if (unlikely (status))
998         return _cairo_scaled_font_create_in_error (status);
999
1000     /* Note that degenerate ctm or font_matrix *are* allowed.
1001      * We want to support a font size of 0. */
1002
1003     font_map = _cairo_scaled_font_map_lock ();
1004     if (unlikely (font_map == NULL))
1005         return _cairo_scaled_font_create_in_error (_cairo_error (CAIRO_STATUS_NO_MEMORY));
1006
1007     scaled_font = font_map->mru_scaled_font;
1008     if (scaled_font != NULL &&
1009         _cairo_scaled_font_matches (scaled_font,
1010                                     font_face, font_matrix, ctm, options))
1011     {
1012         assert (scaled_font->hash_entry.hash != ZOMBIE);
1013         assert (! scaled_font->placeholder);
1014
1015         if (likely (scaled_font->status == CAIRO_STATUS_SUCCESS)) {
1016             /* We increment the reference count manually here, (rather
1017              * than calling into cairo_scaled_font_reference), since we
1018              * must modify the reference count while our lock is still
1019              * held. */
1020             _cairo_reference_count_inc (&scaled_font->ref_count);
1021             _cairo_scaled_font_map_unlock ();
1022             return scaled_font;
1023         }
1024
1025         /* the font has been put into an error status - abandon the cache */
1026         _cairo_hash_table_remove (font_map->hash_table,
1027                                   &scaled_font->hash_entry);
1028         scaled_font->hash_entry.hash = ZOMBIE;
1029         dead = scaled_font;
1030         font_map->mru_scaled_font = NULL;
1031     }
1032
1033     _cairo_scaled_font_init_key (&key, font_face, font_matrix, ctm, options);
1034
1035     while ((scaled_font = _cairo_hash_table_lookup (font_map->hash_table,
1036                                                     &key.hash_entry)))
1037     {
1038         if (! scaled_font->placeholder)
1039             break;
1040
1041         /* If the scaled font is being created (happens for user-font),
1042          * just wait until it's done, then retry */
1043         _cairo_scaled_font_placeholder_wait_for_creation_to_finish (scaled_font);
1044     }
1045
1046     if (scaled_font != NULL) {
1047         /* If the original reference count is 0, then this font must have
1048          * been found in font_map->holdovers, (which means this caching is
1049          * actually working). So now we remove it from the holdovers
1050          * array, unless we caught the font in the middle of destruction.
1051          */
1052         if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)) {
1053             if (scaled_font->holdover) {
1054                 int i;
1055
1056                 for (i = 0; i < font_map->num_holdovers; i++) {
1057                     if (font_map->holdovers[i] == scaled_font) {
1058                         font_map->num_holdovers--;
1059                         memmove (&font_map->holdovers[i],
1060                                  &font_map->holdovers[i+1],
1061                                  (font_map->num_holdovers - i) * sizeof (cairo_scaled_font_t*));
1062                         break;
1063                     }
1064                 }
1065
1066                 scaled_font->holdover = FALSE;
1067             }
1068
1069             /* reset any error status */
1070             scaled_font->status = CAIRO_STATUS_SUCCESS;
1071         }
1072
1073         if (likely (scaled_font->status == CAIRO_STATUS_SUCCESS)) {
1074             /* We increment the reference count manually here, (rather
1075              * than calling into cairo_scaled_font_reference), since we
1076              * must modify the reference count while our lock is still
1077              * held. */
1078
1079             old = font_map->mru_scaled_font;
1080             font_map->mru_scaled_font = scaled_font;
1081             /* increment reference count for the mru cache */
1082             _cairo_reference_count_inc (&scaled_font->ref_count);
1083             /* and increment for the returned reference */
1084             _cairo_reference_count_inc (&scaled_font->ref_count);
1085             _cairo_scaled_font_map_unlock ();
1086
1087             cairo_scaled_font_destroy (old);
1088             if (font_face != original_font_face)
1089                 cairo_font_face_destroy (font_face);
1090
1091             return scaled_font;
1092         }
1093
1094         /* the font has been put into an error status - abandon the cache */
1095         _cairo_hash_table_remove (font_map->hash_table,
1096                                   &scaled_font->hash_entry);
1097         scaled_font->hash_entry.hash = ZOMBIE;
1098     }
1099
1100
1101     /* Otherwise create it and insert it into the hash table. */
1102     if (font_face->backend->get_implementation != NULL) {
1103         font_face = font_face->backend->get_implementation (font_face,
1104                                                             font_matrix,
1105                                                             ctm,
1106                                                             options);
1107         if (unlikely (font_face->status)) {
1108             _cairo_scaled_font_map_unlock ();
1109             return _cairo_scaled_font_create_in_error (font_face->status);
1110         }
1111     }
1112
1113     status = font_face->backend->scaled_font_create (font_face, font_matrix,
1114                                                      ctm, options, &scaled_font);
1115     /* Did we leave the backend in an error state? */
1116     if (unlikely (status)) {
1117         _cairo_scaled_font_map_unlock ();
1118         if (font_face != original_font_face)
1119             cairo_font_face_destroy (font_face);
1120
1121         if (dead != NULL)
1122             cairo_scaled_font_destroy (dead);
1123
1124         status = _cairo_font_face_set_error (font_face, status);
1125         return _cairo_scaled_font_create_in_error (status);
1126     }
1127     /* Or did we encounter an error whilst constructing the scaled font? */
1128     if (unlikely (scaled_font->status)) {
1129         _cairo_scaled_font_map_unlock ();
1130         if (font_face != original_font_face)
1131             cairo_font_face_destroy (font_face);
1132
1133         if (dead != NULL)
1134             cairo_scaled_font_destroy (dead);
1135
1136         return scaled_font;
1137     }
1138
1139     /* Our caching above is defeated if the backend switches fonts on us -
1140      * e.g. old incarnations of toy-font-face and lazily resolved
1141      * ft-font-faces
1142      */
1143     assert (scaled_font->font_face == font_face);
1144
1145     scaled_font->original_font_face =
1146         cairo_font_face_reference (original_font_face);
1147
1148     scaled_font->hash_entry.hash = _cairo_scaled_font_compute_hash(scaled_font);
1149
1150     status = _cairo_hash_table_insert (font_map->hash_table,
1151                                        &scaled_font->hash_entry);
1152     if (likely (status == CAIRO_STATUS_SUCCESS)) {
1153         old = font_map->mru_scaled_font;
1154         font_map->mru_scaled_font = scaled_font;
1155         _cairo_reference_count_inc (&scaled_font->ref_count);
1156     }
1157
1158     _cairo_scaled_font_map_unlock ();
1159
1160     cairo_scaled_font_destroy (old);
1161     if (font_face != original_font_face)
1162         cairo_font_face_destroy (font_face);
1163
1164     if (dead != NULL)
1165         cairo_scaled_font_destroy (dead);
1166
1167     if (unlikely (status)) {
1168         /* We can't call _cairo_scaled_font_destroy here since it expects
1169          * that the font has already been successfully inserted into the
1170          * hash table. */
1171         _cairo_scaled_font_fini_internal (scaled_font);
1172         free (scaled_font);
1173         return _cairo_scaled_font_create_in_error (status);
1174     }
1175
1176     return scaled_font;
1177 }
1178 slim_hidden_def (cairo_scaled_font_create);
1179
1180 static cairo_scaled_font_t *_cairo_scaled_font_nil_objects[CAIRO_STATUS_LAST_STATUS + 1];
1181
1182 /* XXX This should disappear in favour of a common pool of error objects. */
1183 cairo_scaled_font_t *
1184 _cairo_scaled_font_create_in_error (cairo_status_t status)
1185 {
1186     cairo_scaled_font_t *scaled_font;
1187
1188     assert (status != CAIRO_STATUS_SUCCESS);
1189
1190     if (status == CAIRO_STATUS_NO_MEMORY)
1191         return (cairo_scaled_font_t *) &_cairo_scaled_font_nil;
1192
1193     CAIRO_MUTEX_LOCK (_cairo_scaled_font_error_mutex);
1194     scaled_font = _cairo_scaled_font_nil_objects[status];
1195     if (unlikely (scaled_font == NULL)) {
1196         scaled_font = malloc (sizeof (cairo_scaled_font_t));
1197         if (unlikely (scaled_font == NULL)) {
1198             CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex);
1199             _cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
1200             return (cairo_scaled_font_t *) &_cairo_scaled_font_nil;
1201         }
1202
1203         *scaled_font = _cairo_scaled_font_nil;
1204         scaled_font->status = status;
1205         _cairo_scaled_font_nil_objects[status] = scaled_font;
1206     }
1207     CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex);
1208
1209     return scaled_font;
1210 }
1211
1212 void
1213 _cairo_scaled_font_reset_static_data (void)
1214 {
1215     int status;
1216
1217     CAIRO_MUTEX_LOCK (_cairo_scaled_font_error_mutex);
1218     for (status = CAIRO_STATUS_SUCCESS;
1219          status <= CAIRO_STATUS_LAST_STATUS;
1220          status++)
1221     {
1222         free (_cairo_scaled_font_nil_objects[status]);
1223         _cairo_scaled_font_nil_objects[status] = NULL;
1224     }
1225     CAIRO_MUTEX_UNLOCK (_cairo_scaled_font_error_mutex);
1226
1227     CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
1228     if (cairo_scaled_glyph_page_cache.hash_table != NULL) {
1229         _cairo_cache_fini (&cairo_scaled_glyph_page_cache);
1230         cairo_scaled_glyph_page_cache.hash_table = NULL;
1231     }
1232     CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
1233 }
1234
1235 /**
1236  * cairo_scaled_font_reference:
1237  * @scaled_font: a #cairo_scaled_font_t, (may be %NULL in which case
1238  * this function does nothing)
1239  *
1240  * Increases the reference count on @scaled_font by one. This prevents
1241  * @scaled_font from being destroyed until a matching call to
1242  * cairo_scaled_font_destroy() is made.
1243  *
1244  * The number of references to a #cairo_scaled_font_t can be get using
1245  * cairo_scaled_font_get_reference_count().
1246  *
1247  * Returns: the referenced #cairo_scaled_font_t
1248  *
1249  * Since: 1.0
1250  **/
1251 cairo_scaled_font_t *
1252 cairo_scaled_font_reference (cairo_scaled_font_t *scaled_font)
1253 {
1254     if (scaled_font == NULL ||
1255             CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
1256         return scaled_font;
1257
1258     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
1259
1260     _cairo_reference_count_inc (&scaled_font->ref_count);
1261
1262     return scaled_font;
1263 }
1264 slim_hidden_def (cairo_scaled_font_reference);
1265
1266 /**
1267  * cairo_scaled_font_destroy:
1268  * @scaled_font: a #cairo_scaled_font_t
1269  *
1270  * Decreases the reference count on @font by one. If the result
1271  * is zero, then @font and all associated resources are freed.
1272  * See cairo_scaled_font_reference().
1273  *
1274  * Since: 1.0
1275  **/
1276 void
1277 cairo_scaled_font_destroy (cairo_scaled_font_t *scaled_font)
1278 {
1279     cairo_scaled_font_t *lru = NULL;
1280     cairo_scaled_font_map_t *font_map;
1281
1282     assert (CAIRO_MUTEX_IS_UNLOCKED (_cairo_scaled_font_map_mutex));
1283
1284     if (scaled_font == NULL ||
1285             CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
1286         return;
1287
1288     assert (CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count));
1289
1290     if (! _cairo_reference_count_dec_and_test (&scaled_font->ref_count))
1291         return;
1292
1293     font_map = _cairo_scaled_font_map_lock ();
1294     assert (font_map != NULL);
1295
1296     /* Another thread may have resurrected the font whilst we waited */
1297     if (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&scaled_font->ref_count)) {
1298         if (! scaled_font->placeholder &&
1299             scaled_font->hash_entry.hash != ZOMBIE)
1300         {
1301             /* Another thread may have already inserted us into the holdovers */
1302             if (scaled_font->holdover)
1303                 goto unlock;
1304
1305             /* Rather than immediately destroying this object, we put it into
1306              * the font_map->holdovers array in case it will get used again
1307              * soon (and is why we must hold the lock over the atomic op on
1308              * the reference count). To make room for it, we do actually
1309              * destroy the least-recently-used holdover.
1310              */
1311
1312             if (font_map->num_holdovers == CAIRO_SCALED_FONT_MAX_HOLDOVERS) {
1313                 lru = font_map->holdovers[0];
1314                 assert (! CAIRO_REFERENCE_COUNT_HAS_REFERENCE (&lru->ref_count));
1315
1316                 _cairo_hash_table_remove (font_map->hash_table,
1317                                           &lru->hash_entry);
1318
1319                 font_map->num_holdovers--;
1320                 memmove (&font_map->holdovers[0],
1321                          &font_map->holdovers[1],
1322                          font_map->num_holdovers * sizeof (cairo_scaled_font_t*));
1323             }
1324
1325             font_map->holdovers[font_map->num_holdovers++] = scaled_font;
1326             scaled_font->holdover = TRUE;
1327         } else
1328             lru = scaled_font;
1329     }
1330
1331   unlock:
1332     _cairo_scaled_font_map_unlock ();
1333
1334     /* If we pulled an item from the holdovers array, (while the font
1335      * map lock was held, of course), then there is no way that anyone
1336      * else could have acquired a reference to it. So we can now
1337      * safely call fini on it without any lock held. This is desirable
1338      * as we never want to call into any backend function with a lock
1339      * held. */
1340     if (lru != NULL) {
1341         _cairo_scaled_font_fini_internal (lru);
1342         free (lru);
1343     }
1344 }
1345 slim_hidden_def (cairo_scaled_font_destroy);
1346
1347 /**
1348  * cairo_scaled_font_get_reference_count:
1349  * @scaled_font: a #cairo_scaled_font_t
1350  *
1351  * Returns the current reference count of @scaled_font.
1352  *
1353  * Return value: the current reference count of @scaled_font.  If the
1354  * object is a nil object, 0 will be returned.
1355  *
1356  * Since: 1.4
1357  **/
1358 unsigned int
1359 cairo_scaled_font_get_reference_count (cairo_scaled_font_t *scaled_font)
1360 {
1361     if (scaled_font == NULL ||
1362             CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
1363         return 0;
1364
1365     return CAIRO_REFERENCE_COUNT_GET_VALUE (&scaled_font->ref_count);
1366 }
1367
1368 /**
1369  * cairo_scaled_font_get_user_data:
1370  * @scaled_font: a #cairo_scaled_font_t
1371  * @key: the address of the #cairo_user_data_key_t the user data was
1372  * attached to
1373  *
1374  * Return user data previously attached to @scaled_font using the
1375  * specified key.  If no user data has been attached with the given
1376  * key this function returns %NULL.
1377  *
1378  * Return value: the user data previously attached or %NULL.
1379  *
1380  * Since: 1.4
1381  **/
1382 void *
1383 cairo_scaled_font_get_user_data (cairo_scaled_font_t         *scaled_font,
1384                                  const cairo_user_data_key_t *key)
1385 {
1386     return _cairo_user_data_array_get_data (&scaled_font->user_data,
1387                                             key);
1388 }
1389 slim_hidden_def (cairo_scaled_font_get_user_data);
1390
1391 /**
1392  * cairo_scaled_font_set_user_data:
1393  * @scaled_font: a #cairo_scaled_font_t
1394  * @key: the address of a #cairo_user_data_key_t to attach the user data to
1395  * @user_data: the user data to attach to the #cairo_scaled_font_t
1396  * @destroy: a #cairo_destroy_func_t which will be called when the
1397  * #cairo_t is destroyed or when new user data is attached using the
1398  * same key.
1399  *
1400  * Attach user data to @scaled_font.  To remove user data from a surface,
1401  * call this function with the key that was used to set it and %NULL
1402  * for @data.
1403  *
1404  * Return value: %CAIRO_STATUS_SUCCESS or %CAIRO_STATUS_NO_MEMORY if a
1405  * slot could not be allocated for the user data.
1406  *
1407  * Since: 1.4
1408  **/
1409 cairo_status_t
1410 cairo_scaled_font_set_user_data (cairo_scaled_font_t         *scaled_font,
1411                                  const cairo_user_data_key_t *key,
1412                                  void                        *user_data,
1413                                  cairo_destroy_func_t         destroy)
1414 {
1415     if (CAIRO_REFERENCE_COUNT_IS_INVALID (&scaled_font->ref_count))
1416         return scaled_font->status;
1417
1418     return _cairo_user_data_array_set_data (&scaled_font->user_data,
1419                                             key, user_data, destroy);
1420 }
1421 slim_hidden_def (cairo_scaled_font_set_user_data);
1422
1423 /* Public font API follows. */
1424
1425 /**
1426  * cairo_scaled_font_extents:
1427  * @scaled_font: a #cairo_scaled_font_t
1428  * @extents: a #cairo_font_extents_t which to store the retrieved extents.
1429  *
1430  * Gets the metrics for a #cairo_scaled_font_t.
1431  *
1432  * Since: 1.0
1433  **/
1434 void
1435 cairo_scaled_font_extents (cairo_scaled_font_t  *scaled_font,
1436                            cairo_font_extents_t *extents)
1437 {
1438     if (scaled_font->status) {
1439         extents->ascent  = 0.0;
1440         extents->descent = 0.0;
1441         extents->height  = 0.0;
1442         extents->max_x_advance = 0.0;
1443         extents->max_y_advance = 0.0;
1444         return;
1445     }
1446
1447     *extents = scaled_font->extents;
1448 }
1449 slim_hidden_def (cairo_scaled_font_extents);
1450
1451 /**
1452  * cairo_scaled_font_text_extents:
1453  * @scaled_font: a #cairo_scaled_font_t
1454  * @utf8: a NUL-terminated string of text, encoded in UTF-8
1455  * @extents: a #cairo_text_extents_t which to store the retrieved extents.
1456  *
1457  * Gets the extents for a string of text. The extents describe a
1458  * user-space rectangle that encloses the "inked" portion of the text
1459  * drawn at the origin (0,0) (as it would be drawn by cairo_show_text()
1460  * if the cairo graphics state were set to the same font_face,
1461  * font_matrix, ctm, and font_options as @scaled_font).  Additionally,
1462  * the x_advance and y_advance values indicate the amount by which the
1463  * current point would be advanced by cairo_show_text().
1464  *
1465  * Note that whitespace characters do not directly contribute to the
1466  * size of the rectangle (extents.width and extents.height). They do
1467  * contribute indirectly by changing the position of non-whitespace
1468  * characters. In particular, trailing whitespace characters are
1469  * likely to not affect the size of the rectangle, though they will
1470  * affect the x_advance and y_advance values.
1471  *
1472  * Since: 1.2
1473  **/
1474 void
1475 cairo_scaled_font_text_extents (cairo_scaled_font_t   *scaled_font,
1476                                 const char            *utf8,
1477                                 cairo_text_extents_t  *extents)
1478 {
1479     cairo_status_t status;
1480     cairo_glyph_t *glyphs = NULL;
1481     int num_glyphs;
1482
1483     if (scaled_font->status)
1484         goto ZERO_EXTENTS;
1485
1486     if (utf8 == NULL)
1487         goto ZERO_EXTENTS;
1488
1489     status = cairo_scaled_font_text_to_glyphs (scaled_font, 0., 0.,
1490                                                utf8, -1,
1491                                                &glyphs, &num_glyphs,
1492                                                NULL, NULL,
1493                                                NULL);
1494     if (unlikely (status)) {
1495         status = _cairo_scaled_font_set_error (scaled_font, status);
1496         goto ZERO_EXTENTS;
1497     }
1498
1499     cairo_scaled_font_glyph_extents (scaled_font, glyphs, num_glyphs, extents);
1500     free (glyphs);
1501
1502     return;
1503
1504 ZERO_EXTENTS:
1505     extents->x_bearing = 0.0;
1506     extents->y_bearing = 0.0;
1507     extents->width  = 0.0;
1508     extents->height = 0.0;
1509     extents->x_advance = 0.0;
1510     extents->y_advance = 0.0;
1511 }
1512
1513 /**
1514  * cairo_scaled_font_glyph_extents:
1515  * @scaled_font: a #cairo_scaled_font_t
1516  * @glyphs: an array of glyph IDs with X and Y offsets.
1517  * @num_glyphs: the number of glyphs in the @glyphs array
1518  * @extents: a #cairo_text_extents_t which to store the retrieved extents.
1519  *
1520  * Gets the extents for an array of glyphs. The extents describe a
1521  * user-space rectangle that encloses the "inked" portion of the
1522  * glyphs, (as they would be drawn by cairo_show_glyphs() if the cairo
1523  * graphics state were set to the same font_face, font_matrix, ctm,
1524  * and font_options as @scaled_font).  Additionally, the x_advance and
1525  * y_advance values indicate the amount by which the current point
1526  * would be advanced by cairo_show_glyphs().
1527  *
1528  * Note that whitespace glyphs do not contribute to the size of the
1529  * rectangle (extents.width and extents.height).
1530  *
1531  * Since: 1.0
1532  **/
1533 void
1534 cairo_scaled_font_glyph_extents (cairo_scaled_font_t   *scaled_font,
1535                                  const cairo_glyph_t   *glyphs,
1536                                  int                    num_glyphs,
1537                                  cairo_text_extents_t  *extents)
1538 {
1539     cairo_status_t status;
1540     int i;
1541     double min_x = 0.0, min_y = 0.0, max_x = 0.0, max_y = 0.0;
1542     cairo_bool_t visible = FALSE;
1543     cairo_scaled_glyph_t *scaled_glyph = NULL;
1544
1545     extents->x_bearing = 0.0;
1546     extents->y_bearing = 0.0;
1547     extents->width  = 0.0;
1548     extents->height = 0.0;
1549     extents->x_advance = 0.0;
1550     extents->y_advance = 0.0;
1551
1552     if (unlikely (scaled_font->status))
1553         goto ZERO_EXTENTS;
1554
1555     if (num_glyphs == 0)
1556         goto ZERO_EXTENTS;
1557
1558     if (unlikely (num_glyphs < 0)) {
1559         _cairo_error_throw (CAIRO_STATUS_NEGATIVE_COUNT);
1560         /* XXX Can't propagate error */
1561         goto ZERO_EXTENTS;
1562     }
1563
1564     if (unlikely (glyphs == NULL)) {
1565         _cairo_error_throw (CAIRO_STATUS_NULL_POINTER);
1566         /* XXX Can't propagate error */
1567         goto ZERO_EXTENTS;
1568     }
1569
1570     _cairo_scaled_font_freeze_cache (scaled_font);
1571
1572     for (i = 0; i < num_glyphs; i++) {
1573         double                  left, top, right, bottom;
1574
1575         status = _cairo_scaled_glyph_lookup (scaled_font,
1576                                              glyphs[i].index,
1577                                              CAIRO_SCALED_GLYPH_INFO_METRICS,
1578                                              &scaled_glyph);
1579         if (unlikely (status)) {
1580             status = _cairo_scaled_font_set_error (scaled_font, status);
1581             goto UNLOCK;
1582         }
1583
1584         /* "Ink" extents should skip "invisible" glyphs */
1585         if (scaled_glyph->metrics.width == 0 || scaled_glyph->metrics.height == 0)
1586             continue;
1587
1588         left = scaled_glyph->metrics.x_bearing + glyphs[i].x;
1589         right = left + scaled_glyph->metrics.width;
1590         top = scaled_glyph->metrics.y_bearing + glyphs[i].y;
1591         bottom = top + scaled_glyph->metrics.height;
1592
1593         if (!visible) {
1594             visible = TRUE;
1595             min_x = left;
1596             max_x = right;
1597             min_y = top;
1598             max_y = bottom;
1599         } else {
1600             if (left < min_x) min_x = left;
1601             if (right > max_x) max_x = right;
1602             if (top < min_y) min_y = top;
1603             if (bottom > max_y) max_y = bottom;
1604         }
1605     }
1606
1607     if (visible) {
1608         extents->x_bearing = min_x - glyphs[0].x;
1609         extents->y_bearing = min_y - glyphs[0].y;
1610         extents->width = max_x - min_x;
1611         extents->height = max_y - min_y;
1612     } else {
1613         extents->x_bearing = 0.0;
1614         extents->y_bearing = 0.0;
1615         extents->width = 0.0;
1616         extents->height = 0.0;
1617     }
1618
1619     if (num_glyphs) {
1620         double x0, y0, x1, y1;
1621
1622         x0 = glyphs[0].x;
1623         y0 = glyphs[0].y;
1624
1625         /* scaled_glyph contains the glyph for num_glyphs - 1 already. */
1626         x1 = glyphs[num_glyphs - 1].x + scaled_glyph->metrics.x_advance;
1627         y1 = glyphs[num_glyphs - 1].y + scaled_glyph->metrics.y_advance;
1628
1629         extents->x_advance = x1 - x0;
1630         extents->y_advance = y1 - y0;
1631     } else {
1632         extents->x_advance = 0.0;
1633         extents->y_advance = 0.0;
1634     }
1635
1636  UNLOCK:
1637     _cairo_scaled_font_thaw_cache (scaled_font);
1638     return;
1639
1640 ZERO_EXTENTS:
1641     extents->x_bearing = 0.0;
1642     extents->y_bearing = 0.0;
1643     extents->width  = 0.0;
1644     extents->height = 0.0;
1645     extents->x_advance = 0.0;
1646     extents->y_advance = 0.0;
1647 }
1648 slim_hidden_def (cairo_scaled_font_glyph_extents);
1649
1650 #define GLYPH_LUT_SIZE 64
1651 static cairo_status_t
1652 cairo_scaled_font_text_to_glyphs_internal_cached (cairo_scaled_font_t            *scaled_font,
1653                                                     double                        x,
1654                                                     double                        y,
1655                                                     const char                   *utf8,
1656                                                     cairo_glyph_t                *glyphs,
1657                                                     cairo_text_cluster_t        **clusters,
1658                                                     int                           num_chars)
1659 {
1660     struct glyph_lut_elt {
1661         unsigned long index;
1662         double x_advance;
1663         double y_advance;
1664     } glyph_lut[GLYPH_LUT_SIZE];
1665     uint32_t glyph_lut_unicode[GLYPH_LUT_SIZE];
1666     cairo_status_t status;
1667     const char *p;
1668     int i;
1669
1670     for (i = 0; i < GLYPH_LUT_SIZE; i++)
1671         glyph_lut_unicode[i] = ~0U;
1672
1673     p = utf8;
1674     for (i = 0; i < num_chars; i++) {
1675         int idx, num_bytes;
1676         uint32_t unicode;
1677         cairo_scaled_glyph_t *scaled_glyph;
1678         struct glyph_lut_elt *glyph_slot;
1679
1680         num_bytes = _cairo_utf8_get_char_validated (p, &unicode);
1681         p += num_bytes;
1682
1683         glyphs[i].x = x;
1684         glyphs[i].y = y;
1685
1686         idx = unicode % ARRAY_LENGTH (glyph_lut);
1687         glyph_slot = &glyph_lut[idx];
1688         if (glyph_lut_unicode[idx] == unicode) {
1689             glyphs[i].index = glyph_slot->index;
1690             x += glyph_slot->x_advance;
1691             y += glyph_slot->y_advance;
1692         } else {
1693             unsigned long g;
1694
1695             g = scaled_font->backend->ucs4_to_index (scaled_font, unicode);
1696             status = _cairo_scaled_glyph_lookup (scaled_font,
1697                                                  g,
1698                                                  CAIRO_SCALED_GLYPH_INFO_METRICS,
1699                                                  &scaled_glyph);
1700             if (unlikely (status))
1701                 return status;
1702
1703             x += scaled_glyph->metrics.x_advance;
1704             y += scaled_glyph->metrics.y_advance;
1705
1706             glyph_lut_unicode[idx] = unicode;
1707             glyph_slot->index = g;
1708             glyph_slot->x_advance = scaled_glyph->metrics.x_advance;
1709             glyph_slot->y_advance = scaled_glyph->metrics.y_advance;
1710
1711             glyphs[i].index = g;
1712         }
1713
1714         if (clusters) {
1715             (*clusters)[i].num_bytes  = num_bytes;
1716             (*clusters)[i].num_glyphs = 1;
1717         }
1718     }
1719
1720     return CAIRO_STATUS_SUCCESS;
1721 }
1722
1723 static cairo_status_t
1724 cairo_scaled_font_text_to_glyphs_internal_uncached (cairo_scaled_font_t  *scaled_font,
1725                                                   double                  x,
1726                                                   double                  y,
1727                                                   const char             *utf8,
1728                                                   cairo_glyph_t          *glyphs,
1729                                                   cairo_text_cluster_t  **clusters,
1730                                                   int                     num_chars)
1731 {
1732     const char *p;
1733     int i;
1734
1735     p = utf8;
1736     for (i = 0; i < num_chars; i++) {
1737         unsigned long g;
1738         int num_bytes;
1739         uint32_t unicode;
1740         cairo_scaled_glyph_t *scaled_glyph;
1741         cairo_status_t status;
1742
1743         num_bytes = _cairo_utf8_get_char_validated (p, &unicode);
1744         p += num_bytes;
1745
1746         glyphs[i].x = x;
1747         glyphs[i].y = y;
1748
1749         g = scaled_font->backend->ucs4_to_index (scaled_font, unicode);
1750
1751         /*
1752          * No advance needed for a single character string. So, let's speed up
1753          * one-character strings by skipping glyph lookup.
1754          */
1755         if (num_chars > 1) {
1756             status = _cairo_scaled_glyph_lookup (scaled_font,
1757                                              g,
1758                                              CAIRO_SCALED_GLYPH_INFO_METRICS,
1759                                              &scaled_glyph);
1760             if (unlikely (status))
1761                 return status;
1762
1763             x += scaled_glyph->metrics.x_advance;
1764             y += scaled_glyph->metrics.y_advance;
1765         }
1766
1767         glyphs[i].index = g;
1768
1769         if (clusters) {
1770             (*clusters)[i].num_bytes  = num_bytes;
1771             (*clusters)[i].num_glyphs = 1;
1772         }
1773     }
1774
1775     return CAIRO_STATUS_SUCCESS;
1776 }
1777
1778 /**
1779  * cairo_scaled_font_text_to_glyphs:
1780  * @x: X position to place first glyph
1781  * @y: Y position to place first glyph
1782  * @scaled_font: a #cairo_scaled_font_t
1783  * @utf8: a string of text encoded in UTF-8
1784  * @utf8_len: length of @utf8 in bytes, or -1 if it is NUL-terminated
1785  * @glyphs: pointer to array of glyphs to fill
1786  * @num_glyphs: pointer to number of glyphs
1787  * @clusters: pointer to array of cluster mapping information to fill, or %NULL
1788  * @num_clusters: pointer to number of clusters, or %NULL
1789  * @cluster_flags: pointer to location to store cluster flags corresponding to the
1790  *                 output @clusters, or %NULL
1791  *
1792  * Converts UTF-8 text to an array of glyphs, optionally with cluster
1793  * mapping, that can be used to render later using @scaled_font.
1794  *
1795  * If @glyphs initially points to a non-%NULL value, that array is used
1796  * as a glyph buffer, and @num_glyphs should point to the number of glyph
1797  * entries available there.  If the provided glyph array is too short for
1798  * the conversion, a new glyph array is allocated using cairo_glyph_allocate()
1799  * and placed in @glyphs.  Upon return, @num_glyphs always contains the
1800  * number of generated glyphs.  If the value @glyphs points to has changed
1801  * after the call, the user is responsible for freeing the allocated glyph
1802  * array using cairo_glyph_free().  This may happen even if the provided
1803  * array was large enough.
1804  *
1805  * If @clusters is not %NULL, @num_clusters and @cluster_flags should not be %NULL,
1806  * and cluster mapping will be computed.
1807  * The semantics of how cluster array allocation works is similar to the glyph
1808  * array.  That is,
1809  * if @clusters initially points to a non-%NULL value, that array is used
1810  * as a cluster buffer, and @num_clusters should point to the number of cluster
1811  * entries available there.  If the provided cluster array is too short for
1812  * the conversion, a new cluster array is allocated using cairo_text_cluster_allocate()
1813  * and placed in @clusters.  Upon return, @num_clusters always contains the
1814  * number of generated clusters.  If the value @clusters points at has changed
1815  * after the call, the user is responsible for freeing the allocated cluster
1816  * array using cairo_text_cluster_free().  This may happen even if the provided
1817  * array was large enough.
1818  *
1819  * In the simplest case, @glyphs and @clusters can point to %NULL initially
1820  * and a suitable array will be allocated.  In code:
1821  * <informalexample><programlisting>
1822  * cairo_status_t status;
1823  *
1824  * cairo_glyph_t *glyphs = NULL;
1825  * int num_glyphs;
1826  * cairo_text_cluster_t *clusters = NULL;
1827  * int num_clusters;
1828  * cairo_text_cluster_flags_t cluster_flags;
1829  *
1830  * status = cairo_scaled_font_text_to_glyphs (scaled_font,
1831  *                                            x, y,
1832  *                                            utf8, utf8_len,
1833  *                                            &amp;glyphs, &amp;num_glyphs,
1834  *                                            &amp;clusters, &amp;num_clusters, &amp;cluster_flags);
1835  *
1836  * if (status == CAIRO_STATUS_SUCCESS) {
1837  *     cairo_show_text_glyphs (cr,
1838  *                             utf8, utf8_len,
1839  *                             glyphs, num_glyphs,
1840  *                             clusters, num_clusters, cluster_flags);
1841  *
1842  *     cairo_glyph_free (glyphs);
1843  *     cairo_text_cluster_free (clusters);
1844  * }
1845  * </programlisting></informalexample>
1846  *
1847  * If no cluster mapping is needed:
1848  * <informalexample><programlisting>
1849  * cairo_status_t status;
1850  *
1851  * cairo_glyph_t *glyphs = NULL;
1852  * int num_glyphs;
1853  *
1854  * status = cairo_scaled_font_text_to_glyphs (scaled_font,
1855  *                                            x, y,
1856  *                                            utf8, utf8_len,
1857  *                                            &amp;glyphs, &amp;num_glyphs,
1858  *                                            NULL, NULL,
1859  *                                            NULL);
1860  *
1861  * if (status == CAIRO_STATUS_SUCCESS) {
1862  *     cairo_show_glyphs (cr, glyphs, num_glyphs);
1863  *     cairo_glyph_free (glyphs);
1864  * }
1865  * </programlisting></informalexample>
1866  *
1867  * If stack-based glyph and cluster arrays are to be used for small
1868  * arrays:
1869  * <informalexample><programlisting>
1870  * cairo_status_t status;
1871  *
1872  * cairo_glyph_t stack_glyphs[40];
1873  * cairo_glyph_t *glyphs = stack_glyphs;
1874  * int num_glyphs = sizeof (stack_glyphs) / sizeof (stack_glyphs[0]);
1875  * cairo_text_cluster_t stack_clusters[40];
1876  * cairo_text_cluster_t *clusters = stack_clusters;
1877  * int num_clusters = sizeof (stack_clusters) / sizeof (stack_clusters[0]);
1878  * cairo_text_cluster_flags_t cluster_flags;
1879  *
1880  * status = cairo_scaled_font_text_to_glyphs (scaled_font,
1881  *                                            x, y,
1882  *                                            utf8, utf8_len,
1883  *                                            &amp;glyphs, &amp;num_glyphs,
1884  *                                            &amp;clusters, &amp;num_clusters, &amp;cluster_flags);
1885  *
1886  * if (status == CAIRO_STATUS_SUCCESS) {
1887  *     cairo_show_text_glyphs (cr,
1888  *                             utf8, utf8_len,
1889  *                             glyphs, num_glyphs,
1890  *                             clusters, num_clusters, cluster_flags);
1891  *
1892  *     if (glyphs != stack_glyphs)
1893  *         cairo_glyph_free (glyphs);
1894  *     if (clusters != stack_clusters)
1895  *         cairo_text_cluster_free (clusters);
1896  * }
1897  * </programlisting></informalexample>
1898  *
1899  * For details of how @clusters, @num_clusters, and @cluster_flags map input
1900  * UTF-8 text to the output glyphs see cairo_show_text_glyphs().
1901  *
1902  * The output values can be readily passed to cairo_show_text_glyphs()
1903  * cairo_show_glyphs(), or related functions, assuming that the exact
1904  * same @scaled_font is used for the operation.
1905  *
1906  * Return value: %CAIRO_STATUS_SUCCESS upon success, or an error status
1907  * if the input values are wrong or if conversion failed.  If the input
1908  * values are correct but the conversion failed, the error status is also
1909  * set on @scaled_font.
1910  *
1911  * Since: 1.8
1912  **/
1913 #define CACHING_THRESHOLD 16
1914 cairo_status_t
1915 cairo_scaled_font_text_to_glyphs (cairo_scaled_font_t   *scaled_font,
1916                                   double                 x,
1917                                   double                 y,
1918                                   const char            *utf8,
1919                                   int                    utf8_len,
1920                                   cairo_glyph_t        **glyphs,
1921                                   int                   *num_glyphs,
1922                                   cairo_text_cluster_t **clusters,
1923                                   int                   *num_clusters,
1924                                   cairo_text_cluster_flags_t *cluster_flags)
1925 {
1926     int num_chars = 0;
1927     cairo_int_status_t status;
1928     cairo_glyph_t *orig_glyphs;
1929     cairo_text_cluster_t *orig_clusters;
1930
1931     status = scaled_font->status;
1932     if (unlikely (status))
1933         return status;
1934
1935     /* A slew of sanity checks */
1936
1937     /* glyphs and num_glyphs can't be NULL */
1938     if (glyphs     == NULL ||
1939         num_glyphs == NULL) {
1940         status = _cairo_error (CAIRO_STATUS_NULL_POINTER);
1941         goto BAIL;
1942     }
1943
1944     /* Special case for NULL and -1 */
1945     if (utf8 == NULL && utf8_len == -1)
1946         utf8_len = 0;
1947
1948     /* No NULLs for non-NULLs! */
1949     if ((utf8_len && utf8          == NULL) ||
1950         (clusters && num_clusters  == NULL) ||
1951         (clusters && cluster_flags == NULL)) {
1952         status = _cairo_error (CAIRO_STATUS_NULL_POINTER);
1953         goto BAIL;
1954     }
1955
1956     /* A -1 for utf8_len means NUL-terminated */
1957     if (utf8_len == -1)
1958         utf8_len = strlen (utf8);
1959
1960     /* A NULL *glyphs means no prealloced glyphs array */
1961     if (glyphs && *glyphs == NULL)
1962         *num_glyphs = 0;
1963
1964     /* A NULL *clusters means no prealloced clusters array */
1965     if (clusters && *clusters == NULL)
1966         *num_clusters = 0;
1967
1968     if (!clusters && num_clusters) {
1969         num_clusters = NULL;
1970     }
1971
1972     if (cluster_flags) {
1973         *cluster_flags = FALSE;
1974     }
1975
1976     if (!clusters && cluster_flags) {
1977         cluster_flags = NULL;
1978     }
1979
1980     /* Apart from that, no negatives */
1981     if (utf8_len < 0 ||
1982         *num_glyphs < 0 ||
1983         (num_clusters && *num_clusters < 0)) {
1984         status = _cairo_error (CAIRO_STATUS_NEGATIVE_COUNT);
1985         goto BAIL;
1986     }
1987
1988     if (utf8_len == 0) {
1989         status = CAIRO_STATUS_SUCCESS;
1990         goto BAIL;
1991     }
1992
1993     /* validate input so backend does not have to */
1994     status = _cairo_utf8_to_ucs4 (utf8, utf8_len, NULL, &num_chars);
1995     if (unlikely (status))
1996         goto BAIL;
1997
1998     _cairo_scaled_font_freeze_cache (scaled_font);
1999
2000     orig_glyphs = *glyphs;
2001     orig_clusters = clusters ? *clusters : NULL;
2002
2003     if (scaled_font->backend->text_to_glyphs) {
2004         status = scaled_font->backend->text_to_glyphs (scaled_font, x, y,
2005                                                        utf8, utf8_len,
2006                                                        glyphs, num_glyphs,
2007                                                        clusters, num_clusters,
2008                                                        cluster_flags);
2009         if (status != CAIRO_INT_STATUS_UNSUPPORTED) {
2010             if (status == CAIRO_INT_STATUS_SUCCESS) {
2011                 /* The checks here are crude; we only should do them in
2012                  * user-font backend, but they don't hurt here.  This stuff
2013                  * can be hard to get right. */
2014
2015                 if (*num_glyphs < 0) {
2016                     status = _cairo_error (CAIRO_STATUS_NEGATIVE_COUNT);
2017                     goto DONE;
2018                 }
2019                 if (num_glyphs && *glyphs == NULL) {
2020                     status = _cairo_error (CAIRO_STATUS_NULL_POINTER);
2021                     goto DONE;
2022                 }
2023
2024                 if (clusters) {
2025                     if (*num_clusters < 0) {
2026                         status = _cairo_error (CAIRO_STATUS_NEGATIVE_COUNT);
2027                         goto DONE;
2028                     }
2029                     if (num_clusters && *clusters == NULL) {
2030                         status = _cairo_error (CAIRO_STATUS_NULL_POINTER);
2031                         goto DONE;
2032                     }
2033
2034                     /* Don't trust the backend, validate clusters! */
2035                     status =
2036                         _cairo_validate_text_clusters (utf8, utf8_len,
2037                                                        *glyphs, *num_glyphs,
2038                                                        *clusters, *num_clusters,
2039                                                        *cluster_flags);
2040                 }
2041             }
2042
2043             goto DONE;
2044         }
2045     }
2046
2047     if (*num_glyphs < num_chars) {
2048         *glyphs = cairo_glyph_allocate (num_chars);
2049         if (unlikely (*glyphs == NULL)) {
2050             status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2051             goto DONE;
2052         }
2053     }
2054     *num_glyphs = num_chars;
2055
2056     if (clusters) {
2057         if (*num_clusters < num_chars) {
2058             *clusters = cairo_text_cluster_allocate (num_chars);
2059             if (unlikely (*clusters == NULL)) {
2060                 status = _cairo_error (CAIRO_STATUS_NO_MEMORY);
2061                 goto DONE;
2062             }
2063         }
2064         *num_clusters = num_chars;
2065     }
2066
2067     if (num_chars > CACHING_THRESHOLD)
2068         status = cairo_scaled_font_text_to_glyphs_internal_cached (scaled_font,
2069                                                                      x, y,
2070                                                                      utf8,
2071                                                                      *glyphs,
2072                                                                      clusters,
2073                                                                      num_chars);
2074     else
2075         status = cairo_scaled_font_text_to_glyphs_internal_uncached (scaled_font,
2076                                                                    x, y,
2077                                                                    utf8,
2078                                                                    *glyphs,
2079                                                                    clusters,
2080                                                                    num_chars);
2081
2082  DONE: /* error that should be logged on scaled_font happened */
2083     _cairo_scaled_font_thaw_cache (scaled_font);
2084
2085     if (unlikely (status)) {
2086         *num_glyphs = 0;
2087         if (*glyphs != orig_glyphs) {
2088             cairo_glyph_free (*glyphs);
2089             *glyphs = orig_glyphs;
2090         }
2091
2092         if (clusters) {
2093             *num_clusters = 0;
2094             if (*clusters != orig_clusters) {
2095                 cairo_text_cluster_free (*clusters);
2096                 *clusters = orig_clusters;
2097             }
2098         }
2099     }
2100
2101     return _cairo_scaled_font_set_error (scaled_font, status);
2102
2103  BAIL: /* error with input arguments */
2104
2105     if (num_glyphs)
2106         *num_glyphs = 0;
2107
2108     if (num_clusters)
2109         *num_clusters = 0;
2110
2111     return status;
2112 }
2113 slim_hidden_def (cairo_scaled_font_text_to_glyphs);
2114
2115 /* XXX: Shoot me - cairo has two basic ways of rendring text in API.
2116  * The first way is cairo_show_text() and the second way is
2117  * cairo_show_glyphs().
2118  *
2119  * For the first method, each glyph location is advanced by x_advance
2120  * and y_advance computed from glyph metrics.  For the second method,
2121  * app is responsible for supplying the glyph location.  This gives us
2122  * opportunity to check whether the computed x_advance and _y_advance
2123  * is equala/larger than supplied glyphs difference for each adjacent
2124  * glyphs.  The rational is that if the spacing between glyphs is at
2125  * least larger than computed x_advance/y_advance, there should be no
2126  * overlapping in text portion of the text images.
2127  */
2128 static inline cairo_bool_t
2129 _glyph_is_next_to_glyph (cairo_glyph_t *prev,
2130                          cairo_glyph_t *current,
2131                          double x_advance,
2132                          double y_advance)
2133 {
2134     return current->x - prev->x >= x_advance - TOLERANCE &&
2135             current->y - prev->y >= y_advance - TOLERANCE;
2136 }
2137
2138 static inline cairo_bool_t
2139 _range_contains_glyph (const cairo_box_t *extents,
2140                        cairo_fixed_t left,
2141                        cairo_fixed_t top,
2142                        cairo_fixed_t right,
2143                        cairo_fixed_t bottom)
2144 {
2145     if (left == right || top == bottom)
2146         return FALSE;
2147
2148     return right > extents->p1.x &&
2149            left < extents->p2.x &&
2150            bottom > extents->p1.y &&
2151            top < extents->p2.y;
2152 }
2153
2154 static cairo_status_t
2155 _cairo_scaled_font_single_glyph_device_extents (cairo_scaled_font_t      *scaled_font,
2156                                                 const cairo_glyph_t      *glyph,
2157                                                 cairo_rectangle_int_t   *extents)
2158 {
2159     cairo_round_glyph_positions_t round_xy;
2160     cairo_scaled_glyph_t *scaled_glyph;
2161     cairo_status_t status;
2162     cairo_box_t box;
2163     cairo_fixed_t v;
2164
2165     status = _cairo_scaled_glyph_lookup (scaled_font,
2166                                          glyph->index,
2167                                          CAIRO_SCALED_GLYPH_INFO_METRICS,
2168                                          &scaled_glyph);
2169     if (unlikely (status))
2170         return status;
2171
2172     round_xy = _cairo_font_options_get_round_glyph_positions (&scaled_font->options);
2173     if (round_xy == CAIRO_ROUND_GLYPH_POS_ON)
2174         v = _cairo_fixed_from_int (_cairo_lround (glyph->x));
2175     else
2176         v = _cairo_fixed_from_double (glyph->x);
2177     box.p1.x = v + scaled_glyph->bbox.p1.x;
2178     box.p2.x = v + scaled_glyph->bbox.p2.x;
2179
2180     if (round_xy == CAIRO_ROUND_GLYPH_POS_ON)
2181         v = _cairo_fixed_from_int (_cairo_lround (glyph->y));
2182     else
2183         v = _cairo_fixed_from_double (glyph->y);
2184     box.p1.y = v + scaled_glyph->bbox.p1.y;
2185     box.p2.y = v + scaled_glyph->bbox.p2.y;
2186
2187     _cairo_box_round_to_rectangle (&box, extents);
2188     return CAIRO_STATUS_SUCCESS;
2189 }
2190
2191 /*
2192  * Compute a device-space bounding box for the glyphs.
2193  */
2194 cairo_status_t
2195 _cairo_scaled_font_glyph_device_extents (cairo_scaled_font_t     *scaled_font,
2196                                          const cairo_glyph_t     *glyphs,
2197                                          int                      num_glyphs,
2198                                          cairo_rectangle_int_t   *extents,
2199                                          cairo_bool_t *overlap_out)
2200 {
2201     cairo_status_t status = CAIRO_STATUS_SUCCESS;
2202     cairo_box_t box = { { INT_MAX, INT_MAX }, { INT_MIN, INT_MIN }};
2203     cairo_scaled_glyph_t *glyph_cache[64];
2204     cairo_bool_t overlap = overlap_out ? FALSE : TRUE;
2205     cairo_scaled_glyph_t *prev_scaled_glyph = NULL;
2206     cairo_round_glyph_positions_t round_glyph_positions = _cairo_font_options_get_round_glyph_positions (&scaled_font->options);
2207     int i;
2208     cairo_bool_t is_next = FALSE;
2209
2210     if (unlikely (scaled_font->status))
2211         return scaled_font->status;
2212
2213     if (num_glyphs == 1) {
2214         if (overlap_out)
2215             *overlap_out = FALSE;
2216         return _cairo_scaled_font_single_glyph_device_extents (scaled_font,
2217                                                                glyphs,
2218                                                                extents);
2219     }
2220
2221     _cairo_scaled_font_freeze_cache (scaled_font);
2222
2223     memset (glyph_cache, 0, sizeof (glyph_cache));
2224
2225     for (i = 0; i < num_glyphs; i++) {
2226         cairo_scaled_glyph_t    *scaled_glyph;
2227         cairo_fixed_t x, y, x1, y1, x2, y2;
2228         int cache_index = glyphs[i].index % ARRAY_LENGTH (glyph_cache);
2229
2230         scaled_glyph = glyph_cache[cache_index];
2231         if (scaled_glyph == NULL ||
2232             _cairo_scaled_glyph_index (scaled_glyph) != glyphs[i].index)
2233         {
2234             status = _cairo_scaled_glyph_lookup (scaled_font,
2235                                                  glyphs[i].index,
2236                                                  CAIRO_SCALED_GLYPH_INFO_METRICS,
2237                                                  &scaled_glyph);
2238             if (unlikely (status))
2239                 break;
2240
2241             glyph_cache[cache_index] = scaled_glyph;
2242         }
2243
2244         if (round_glyph_positions == CAIRO_ROUND_GLYPH_POS_ON)
2245             x = _cairo_fixed_from_int (_cairo_lround (glyphs[i].x));
2246         else
2247             x = _cairo_fixed_from_double (glyphs[i].x);
2248         x1 = x + scaled_glyph->bbox.p1.x;
2249         x2 = x + scaled_glyph->bbox.p2.x;
2250
2251         if (round_glyph_positions == CAIRO_ROUND_GLYPH_POS_ON)
2252             y = _cairo_fixed_from_int (_cairo_lround (glyphs[i].y));
2253         else
2254             y = _cairo_fixed_from_double (glyphs[i].y);
2255         y1 = y + scaled_glyph->bbox.p1.y;
2256         y2 = y + scaled_glyph->bbox.p2.y;
2257
2258         if (prev_scaled_glyph != NULL && overlap == FALSE) {
2259             is_next = _glyph_is_next_to_glyph ((cairo_glyph_t *)&glyphs[i-1],
2260                                                (cairo_glyph_t *)&glyphs[i],
2261                                                prev_scaled_glyph->metrics.x_advance,
2262                                                prev_scaled_glyph->metrics.y_advance);
2263
2264             if (is_next == FALSE)
2265                 overlap = _range_contains_glyph (&box, x1, y1, x2, y2);
2266         }
2267
2268         if (x1 < box.p1.x) box.p1.x = x1;
2269         if (x2 > box.p2.x) box.p2.x = x2;
2270         if (y1 < box.p1.y) box.p1.y = y1;
2271         if (y2 > box.p2.y) box.p2.y = y2;
2272
2273         prev_scaled_glyph = scaled_glyph;
2274     }
2275
2276     _cairo_scaled_font_thaw_cache (scaled_font);
2277     if (unlikely (status))
2278         return _cairo_scaled_font_set_error (scaled_font, status);
2279
2280     if (box.p1.x < box.p2.x) {
2281         _cairo_box_round_to_rectangle (&box, extents);
2282     } else {
2283         extents->x = extents->y = 0;
2284         extents->width = extents->height = 0;
2285     }
2286
2287     if (overlap_out != NULL)
2288         *overlap_out = overlap;
2289
2290     return CAIRO_STATUS_SUCCESS;
2291 }
2292
2293 cairo_bool_t
2294 _cairo_scaled_font_glyph_approximate_extents (cairo_scaled_font_t        *scaled_font,
2295                                               const cairo_glyph_t        *glyphs,
2296                                               int                      num_glyphs,
2297                                               cairo_rectangle_int_t   *extents)
2298 {
2299     double x0, x1, y0, y1, pad;
2300     int i;
2301
2302     /* If any of the factors are suspect (i.e. the font is broken), bail */
2303     if (scaled_font->fs_extents.max_x_advance == 0 ||
2304         scaled_font->fs_extents.height == 0 ||
2305         scaled_font->max_scale == 0)
2306     {
2307         return FALSE;
2308     }
2309
2310     assert (num_glyphs);
2311
2312     x0 = x1 = glyphs[0].x;
2313     y0 = y1 = glyphs[0].y;
2314     for (i = 1; i < num_glyphs; i++) {
2315         double g;
2316
2317         g = glyphs[i].x;
2318         if (g < x0) x0 = g;
2319         if (g > x1) x1 = g;
2320
2321         g = glyphs[i].y;
2322         if (g < y0) y0 = g;
2323         if (g > y1) y1 = g;
2324     }
2325
2326     pad = MAX(scaled_font->fs_extents.max_x_advance,
2327               scaled_font->fs_extents.height);
2328     pad *= scaled_font->max_scale;
2329
2330     extents->x = floor (x0 - pad);
2331     extents->width = ceil (x1 + pad) - extents->x;
2332     extents->y = floor (y0 - pad);
2333     extents->height = ceil (y1 + pad) - extents->y;
2334     return TRUE;
2335 }
2336
2337 #if 0
2338 /* XXX win32 */
2339 cairo_status_t
2340 _cairo_scaled_font_show_glyphs (cairo_scaled_font_t     *scaled_font,
2341                                 cairo_operator_t         op,
2342                                 const cairo_pattern_t   *pattern,
2343                                 cairo_surface_t         *surface,
2344                                 int                      source_x,
2345                                 int                      source_y,
2346                                 int                      dest_x,
2347                                 int                      dest_y,
2348                                 unsigned int             width,
2349                                 unsigned int             height,
2350                                 cairo_glyph_t           *glyphs,
2351                                 int                      num_glyphs,
2352                                 cairo_region_t          *clip_region)
2353 {
2354     cairo_int_status_t status;
2355     cairo_surface_t *mask = NULL;
2356     cairo_format_t mask_format = CAIRO_FORMAT_A1; /* shut gcc up */
2357     cairo_surface_pattern_t mask_pattern;
2358     int i;
2359
2360     /* These operators aren't interpreted the same way by the backends;
2361      * they are implemented in terms of other operators in cairo-gstate.c
2362      */
2363     assert (op != CAIRO_OPERATOR_SOURCE && op != CAIRO_OPERATOR_CLEAR);
2364
2365     if (scaled_font->status)
2366         return scaled_font->status;
2367
2368     if (!num_glyphs)
2369         return CAIRO_STATUS_SUCCESS;
2370
2371     if (scaled_font->backend->show_glyphs != NULL) {
2372         int remaining_glyphs = num_glyphs;
2373         status = scaled_font->backend->show_glyphs (scaled_font,
2374                                                     op, pattern,
2375                                                     surface,
2376                                                     source_x, source_y,
2377                                                     dest_x, dest_y,
2378                                                     width, height,
2379                                                     glyphs, num_glyphs,
2380                                                     clip_region,
2381                                                     &remaining_glyphs);
2382         glyphs += num_glyphs - remaining_glyphs;
2383         num_glyphs = remaining_glyphs;
2384         if (remaining_glyphs == 0)
2385             status = CAIRO_INT_STATUS_SUCCESS;
2386         if (status != CAIRO_INT_STATUS_UNSUPPORTED)
2387             return _cairo_scaled_font_set_error (scaled_font, status);
2388     }
2389
2390     /* Font display routine either does not exist or failed. */
2391
2392     _cairo_scaled_font_freeze_cache (scaled_font);
2393
2394     for (i = 0; i < num_glyphs; i++) {
2395         int x, y;
2396         cairo_image_surface_t *glyph_surface;
2397         cairo_scaled_glyph_t *scaled_glyph;
2398
2399         status = _cairo_scaled_glyph_lookup (scaled_font,
2400                                              glyphs[i].index,
2401                                              CAIRO_SCALED_GLYPH_INFO_SURFACE,
2402                                              &scaled_glyph);
2403
2404         if (unlikely (status))
2405             goto CLEANUP_MASK;
2406
2407         glyph_surface = scaled_glyph->surface;
2408
2409         /* To start, create the mask using the format from the first
2410          * glyph. Later we'll deal with different formats. */
2411         if (mask == NULL) {
2412             mask_format = glyph_surface->format;
2413             mask = cairo_image_surface_create (mask_format, width, height);
2414             status = mask->status;
2415             if (unlikely (status))
2416                 goto CLEANUP_MASK;
2417         }
2418
2419         /* If we have glyphs of different formats, we "upgrade" the mask
2420          * to the wider of the formats. */
2421         if (glyph_surface->format != mask_format &&
2422             _cairo_format_bits_per_pixel (mask_format) <
2423             _cairo_format_bits_per_pixel (glyph_surface->format) )
2424         {
2425             cairo_surface_t *new_mask;
2426
2427             switch (glyph_surface->format) {
2428             case CAIRO_FORMAT_ARGB32:
2429             case CAIRO_FORMAT_A8:
2430             case CAIRO_FORMAT_A1:
2431                 mask_format = glyph_surface->format;
2432                 break;
2433             case CAIRO_FORMAT_RGB16_565:
2434             case CAIRO_FORMAT_RGB24:
2435             case CAIRO_FORMAT_RGB30:
2436             case CAIRO_FORMAT_INVALID:
2437             default:
2438                 ASSERT_NOT_REACHED;
2439                 mask_format = CAIRO_FORMAT_ARGB32;
2440                 break;
2441             }
2442
2443             new_mask = cairo_image_surface_create (mask_format, width, height);
2444             status = new_mask->status;
2445             if (unlikely (status)) {
2446                 cairo_surface_destroy (new_mask);
2447                 goto CLEANUP_MASK;
2448             }
2449
2450             _cairo_pattern_init_for_surface (&mask_pattern, mask);
2451             /* Note that we only upgrade masks, i.e. A1 -> A8 -> ARGB32, so there is
2452              * never any component alpha here.
2453              */
2454             status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
2455                                                &_cairo_pattern_white.base,
2456                                                &mask_pattern.base,
2457                                                new_mask,
2458                                                0, 0,
2459                                                0, 0,
2460                                                0, 0,
2461                                                width, height,
2462                                                NULL);
2463
2464             _cairo_pattern_fini (&mask_pattern.base);
2465
2466             if (unlikely (status)) {
2467                 cairo_surface_destroy (new_mask);
2468                 goto CLEANUP_MASK;
2469             }
2470
2471             cairo_surface_destroy (mask);
2472             mask = new_mask;
2473         }
2474
2475         if (glyph_surface->width && glyph_surface->height) {
2476             cairo_surface_pattern_t glyph_pattern;
2477
2478             /* round glyph locations to the nearest pixel */
2479             /* XXX: FRAGILE: We're ignoring device_transform scaling here. A bug? */
2480             x = _cairo_lround (glyphs[i].x -
2481                                glyph_surface->base.device_transform.x0);
2482             y = _cairo_lround (glyphs[i].y -
2483                                glyph_surface->base.device_transform.y0);
2484
2485             _cairo_pattern_init_for_surface (&glyph_pattern,
2486                                              &glyph_surface->base);
2487             if (mask_format == CAIRO_FORMAT_ARGB32)
2488                 glyph_pattern.base.has_component_alpha = TRUE;
2489
2490             status = _cairo_surface_composite (CAIRO_OPERATOR_ADD,
2491                                                &_cairo_pattern_white.base,
2492                                                &glyph_pattern.base,
2493                                                mask,
2494                                                0, 0,
2495                                                0, 0,
2496                                                x - dest_x, y - dest_y,
2497                                                glyph_surface->width,
2498                                                glyph_surface->height,
2499                                                NULL);
2500
2501             _cairo_pattern_fini (&glyph_pattern.base);
2502
2503             if (unlikely (status))
2504                 goto CLEANUP_MASK;
2505         }
2506     }
2507
2508     _cairo_pattern_init_for_surface (&mask_pattern, mask);
2509     if (mask_format == CAIRO_FORMAT_ARGB32)
2510         mask_pattern.base.has_component_alpha = TRUE;
2511
2512     status = _cairo_surface_composite (op, pattern, &mask_pattern.base,
2513                                        surface,
2514                                        source_x, source_y,
2515                                        0,        0,
2516                                        dest_x,   dest_y,
2517                                        width,    height,
2518                                        clip_region);
2519
2520     _cairo_pattern_fini (&mask_pattern.base);
2521
2522 CLEANUP_MASK:
2523     _cairo_scaled_font_thaw_cache (scaled_font);
2524
2525     if (mask != NULL)
2526         cairo_surface_destroy (mask);
2527     return _cairo_scaled_font_set_error (scaled_font, status);
2528 }
2529 #endif
2530
2531 /* Add a single-device-unit rectangle to a path. */
2532 static cairo_status_t
2533 _add_unit_rectangle_to_path (cairo_path_fixed_t *path,
2534                              cairo_fixed_t x,
2535                              cairo_fixed_t y)
2536 {
2537     cairo_status_t status;
2538
2539     status = _cairo_path_fixed_move_to (path, x, y);
2540     if (unlikely (status))
2541         return status;
2542
2543     status = _cairo_path_fixed_rel_line_to (path,
2544                                             _cairo_fixed_from_int (1),
2545                                             _cairo_fixed_from_int (0));
2546     if (unlikely (status))
2547         return status;
2548
2549     status = _cairo_path_fixed_rel_line_to (path,
2550                                             _cairo_fixed_from_int (0),
2551                                             _cairo_fixed_from_int (1));
2552     if (unlikely (status))
2553         return status;
2554
2555     status = _cairo_path_fixed_rel_line_to (path,
2556                                             _cairo_fixed_from_int (-1),
2557                                             _cairo_fixed_from_int (0));
2558     if (unlikely (status))
2559         return status;
2560
2561     return _cairo_path_fixed_close_path (path);
2562 }
2563
2564 /**
2565  * _trace_mask_to_path:
2566  * @bitmap: An alpha mask (either %CAIRO_FORMAT_A1 or %CAIRO_FORMAT_A8)
2567  * @path: An initialized path to hold the result
2568  *
2569  * Given a mask surface, (an alpha image), fill out the provided path
2570  * so that when filled it would result in something that approximates
2571  * the mask.
2572  *
2573  * Note: The current tracing code here is extremely primitive. It
2574  * operates only on an A1 surface, (converting an A8 surface to A1 if
2575  * necessary), and performs the tracing by drawing a little square
2576  * around each pixel that is on in the mask. We do not pretend that
2577  * this is a high-quality result. But we are leaving it up to someone
2578  * who cares enough about getting a better result to implement
2579  * something more sophisticated.
2580  **/
2581 static cairo_status_t
2582 _trace_mask_to_path (cairo_image_surface_t *mask,
2583                      cairo_path_fixed_t *path,
2584                      double tx, double ty)
2585 {
2586     const uint8_t *row;
2587     int rows, cols, bytes_per_row;
2588     int x, y, bit;
2589     double xoff, yoff;
2590     cairo_fixed_t x0, y0;
2591     cairo_fixed_t px, py;
2592     cairo_status_t status;
2593
2594     mask = _cairo_image_surface_coerce_to_format (mask, CAIRO_FORMAT_A1);
2595     status = mask->base.status;
2596     if (unlikely (status))
2597         return status;
2598
2599     cairo_surface_get_device_offset (&mask->base, &xoff, &yoff);
2600     x0 = _cairo_fixed_from_double (tx - xoff);
2601     y0 = _cairo_fixed_from_double (ty - yoff);
2602
2603     bytes_per_row = (mask->width + 7) / 8;
2604     row = mask->data;
2605     for (y = 0, rows = mask->height; rows--; row += mask->stride, y++) {
2606         const uint8_t *byte_ptr = row;
2607         x = 0;
2608         py = _cairo_fixed_from_int (y);
2609         for (cols = bytes_per_row; cols--; ) {
2610             uint8_t byte = *byte_ptr++;
2611             if (byte == 0) {
2612                 x += 8;
2613                 continue;
2614             }
2615
2616             byte = CAIRO_BITSWAP8_IF_LITTLE_ENDIAN (byte);
2617             for (bit = 1 << 7; bit && x < mask->width; bit >>= 1, x++) {
2618                 if (byte & bit) {
2619                     px = _cairo_fixed_from_int (x);
2620                     status = _add_unit_rectangle_to_path (path,
2621                                                           px + x0,
2622                                                           py + y0);
2623                     if (unlikely (status))
2624                         goto BAIL;
2625                 }
2626             }
2627         }
2628     }
2629
2630 BAIL:
2631     cairo_surface_destroy (&mask->base);
2632
2633     return status;
2634 }
2635
2636 cairo_status_t
2637 _cairo_scaled_font_glyph_path (cairo_scaled_font_t *scaled_font,
2638                                const cairo_glyph_t *glyphs,
2639                                int                  num_glyphs,
2640                                cairo_path_fixed_t  *path)
2641 {
2642     cairo_int_status_t status;
2643     int i;
2644
2645     status = scaled_font->status;
2646     if (unlikely (status))
2647         return status;
2648
2649     _cairo_scaled_font_freeze_cache (scaled_font);
2650     for (i = 0; i < num_glyphs; i++) {
2651         cairo_scaled_glyph_t *scaled_glyph;
2652
2653         status = _cairo_scaled_glyph_lookup (scaled_font,
2654                                              glyphs[i].index,
2655                                              CAIRO_SCALED_GLYPH_INFO_PATH,
2656                                              &scaled_glyph);
2657         if (status == CAIRO_INT_STATUS_SUCCESS) {
2658             status = _cairo_path_fixed_append (path,
2659                                                scaled_glyph->path,
2660                                                _cairo_fixed_from_double (glyphs[i].x),
2661                                                _cairo_fixed_from_double (glyphs[i].y));
2662
2663         } else if (status == CAIRO_INT_STATUS_UNSUPPORTED) {
2664             /* If the font is incapable of providing a path, then we'll
2665              * have to trace our own from a surface.
2666              */
2667             status = _cairo_scaled_glyph_lookup (scaled_font,
2668                                                  glyphs[i].index,
2669                                                  CAIRO_SCALED_GLYPH_INFO_SURFACE,
2670                                                  &scaled_glyph);
2671             if (unlikely (status))
2672                 goto BAIL;
2673
2674             status = _trace_mask_to_path (scaled_glyph->surface, path,
2675                                           glyphs[i].x, glyphs[i].y);
2676         }
2677
2678         if (unlikely (status))
2679             goto BAIL;
2680     }
2681   BAIL:
2682     _cairo_scaled_font_thaw_cache (scaled_font);
2683
2684     return _cairo_scaled_font_set_error (scaled_font, status);
2685 }
2686
2687 /**
2688  * _cairo_scaled_glyph_set_metrics:
2689  * @scaled_glyph: a #cairo_scaled_glyph_t
2690  * @scaled_font: a #cairo_scaled_font_t
2691  * @fs_metrics: a #cairo_text_extents_t in font space
2692  *
2693  * _cairo_scaled_glyph_set_metrics() stores user space metrics
2694  * for the specified glyph given font space metrics. It is
2695  * called by the font backend when initializing a glyph with
2696  * %CAIRO_SCALED_GLYPH_INFO_METRICS.
2697  **/
2698 void
2699 _cairo_scaled_glyph_set_metrics (cairo_scaled_glyph_t *scaled_glyph,
2700                                  cairo_scaled_font_t *scaled_font,
2701                                  cairo_text_extents_t *fs_metrics)
2702 {
2703     cairo_bool_t first = TRUE;
2704     double hm, wm;
2705     double min_user_x = 0.0, max_user_x = 0.0, min_user_y = 0.0, max_user_y = 0.0;
2706     double min_device_x = 0.0, max_device_x = 0.0, min_device_y = 0.0, max_device_y = 0.0;
2707     double device_x_advance, device_y_advance;
2708
2709     scaled_glyph->fs_metrics = *fs_metrics;
2710
2711     for (hm = 0.0; hm <= 1.0; hm += 1.0)
2712         for (wm = 0.0; wm <= 1.0; wm += 1.0) {
2713             double x, y;
2714
2715             /* Transform this corner to user space */
2716             x = fs_metrics->x_bearing + fs_metrics->width * wm;
2717             y = fs_metrics->y_bearing + fs_metrics->height * hm;
2718             cairo_matrix_transform_point (&scaled_font->font_matrix,
2719                                           &x, &y);
2720             if (first) {
2721                 min_user_x = max_user_x = x;
2722                 min_user_y = max_user_y = y;
2723             } else {
2724                 if (x < min_user_x) min_user_x = x;
2725                 if (x > max_user_x) max_user_x = x;
2726                 if (y < min_user_y) min_user_y = y;
2727                 if (y > max_user_y) max_user_y = y;
2728             }
2729
2730             /* Transform this corner to device space from glyph origin */
2731             x = fs_metrics->x_bearing + fs_metrics->width * wm;
2732             y = fs_metrics->y_bearing + fs_metrics->height * hm;
2733             cairo_matrix_transform_distance (&scaled_font->scale,
2734                                              &x, &y);
2735
2736             if (first) {
2737                 min_device_x = max_device_x = x;
2738                 min_device_y = max_device_y = y;
2739             } else {
2740                 if (x < min_device_x) min_device_x = x;
2741                 if (x > max_device_x) max_device_x = x;
2742                 if (y < min_device_y) min_device_y = y;
2743                 if (y > max_device_y) max_device_y = y;
2744             }
2745             first = FALSE;
2746         }
2747     scaled_glyph->metrics.x_bearing = min_user_x;
2748     scaled_glyph->metrics.y_bearing = min_user_y;
2749     scaled_glyph->metrics.width = max_user_x - min_user_x;
2750     scaled_glyph->metrics.height = max_user_y - min_user_y;
2751
2752     scaled_glyph->metrics.x_advance = fs_metrics->x_advance;
2753     scaled_glyph->metrics.y_advance = fs_metrics->y_advance;
2754     cairo_matrix_transform_distance (&scaled_font->font_matrix,
2755                                      &scaled_glyph->metrics.x_advance,
2756                                      &scaled_glyph->metrics.y_advance);
2757
2758     device_x_advance = fs_metrics->x_advance;
2759     device_y_advance = fs_metrics->y_advance;
2760     cairo_matrix_transform_distance (&scaled_font->scale,
2761                                      &device_x_advance,
2762                                      &device_y_advance);
2763
2764     scaled_glyph->bbox.p1.x = _cairo_fixed_from_double (min_device_x);
2765     scaled_glyph->bbox.p1.y = _cairo_fixed_from_double (min_device_y);
2766     scaled_glyph->bbox.p2.x = _cairo_fixed_from_double (max_device_x);
2767     scaled_glyph->bbox.p2.y = _cairo_fixed_from_double (max_device_y);
2768
2769     scaled_glyph->x_advance = _cairo_lround (device_x_advance);
2770     scaled_glyph->y_advance = _cairo_lround (device_y_advance);
2771
2772     scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_METRICS;
2773 }
2774
2775 void
2776 _cairo_scaled_glyph_set_surface (cairo_scaled_glyph_t *scaled_glyph,
2777                                  cairo_scaled_font_t *scaled_font,
2778                                  cairo_image_surface_t *surface)
2779 {
2780     if (scaled_glyph->surface != NULL)
2781         cairo_surface_destroy (&scaled_glyph->surface->base);
2782
2783     /* sanity check the backend glyph contents */
2784     _cairo_debug_check_image_surface_is_defined (&surface->base);
2785     scaled_glyph->surface = surface;
2786
2787     if (surface != NULL)
2788         scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_SURFACE;
2789     else
2790         scaled_glyph->has_info &= ~CAIRO_SCALED_GLYPH_INFO_SURFACE;
2791 }
2792
2793 void
2794 _cairo_scaled_glyph_set_path (cairo_scaled_glyph_t *scaled_glyph,
2795                               cairo_scaled_font_t *scaled_font,
2796                               cairo_path_fixed_t *path)
2797 {
2798     if (scaled_glyph->path != NULL)
2799         _cairo_path_fixed_destroy (scaled_glyph->path);
2800
2801     scaled_glyph->path = path;
2802
2803     if (path != NULL)
2804         scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_PATH;
2805     else
2806         scaled_glyph->has_info &= ~CAIRO_SCALED_GLYPH_INFO_PATH;
2807 }
2808
2809 void
2810 _cairo_scaled_glyph_set_recording_surface (cairo_scaled_glyph_t *scaled_glyph,
2811                                            cairo_scaled_font_t *scaled_font,
2812                                            cairo_surface_t *recording_surface)
2813 {
2814     if (scaled_glyph->recording_surface != NULL) {
2815         cairo_surface_finish (scaled_glyph->recording_surface);
2816         cairo_surface_destroy (scaled_glyph->recording_surface);
2817     }
2818
2819     scaled_glyph->recording_surface = recording_surface;
2820
2821     if (recording_surface != NULL)
2822         scaled_glyph->has_info |= CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE;
2823     else
2824         scaled_glyph->has_info &= ~CAIRO_SCALED_GLYPH_INFO_RECORDING_SURFACE;
2825 }
2826
2827 static cairo_bool_t
2828 _cairo_scaled_glyph_page_can_remove (const void *closure)
2829 {
2830     const cairo_scaled_glyph_page_t *page = closure;
2831     const cairo_scaled_font_t *scaled_font;
2832
2833     scaled_font = (cairo_scaled_font_t *) page->cache_entry.hash;
2834     return scaled_font->cache_frozen == 0;
2835 }
2836
2837 static cairo_status_t
2838 _cairo_scaled_font_allocate_glyph (cairo_scaled_font_t *scaled_font,
2839                                    cairo_scaled_glyph_t **scaled_glyph)
2840 {
2841     cairo_scaled_glyph_page_t *page;
2842     cairo_status_t status;
2843
2844     /* only the first page in the list may contain available slots */
2845     if (! cairo_list_is_empty (&scaled_font->glyph_pages)) {
2846         page = cairo_list_last_entry (&scaled_font->glyph_pages,
2847                                       cairo_scaled_glyph_page_t,
2848                                       link);
2849         if (page->num_glyphs < CAIRO_SCALED_GLYPH_PAGE_SIZE) {
2850             *scaled_glyph = &page->glyphs[page->num_glyphs++];
2851             return CAIRO_STATUS_SUCCESS;
2852         }
2853     }
2854
2855     page = malloc (sizeof (cairo_scaled_glyph_page_t));
2856     if (unlikely (page == NULL))
2857         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2858
2859     page->cache_entry.hash = (unsigned long) scaled_font;
2860     page->cache_entry.size = 1; /* XXX occupancy weighting? */
2861     page->num_glyphs = 0;
2862
2863     CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
2864     if (scaled_font->global_cache_frozen == FALSE) {
2865         if (unlikely (cairo_scaled_glyph_page_cache.hash_table == NULL)) {
2866             status = _cairo_cache_init (&cairo_scaled_glyph_page_cache,
2867                                         NULL,
2868                                         _cairo_scaled_glyph_page_can_remove,
2869                                         _cairo_scaled_glyph_page_destroy,
2870                                         MAX_GLYPH_PAGES_CACHED);
2871             if (unlikely (status)) {
2872                 CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
2873                 free (page);
2874                 return status;
2875             }
2876         }
2877
2878         _cairo_cache_freeze (&cairo_scaled_glyph_page_cache);
2879         scaled_font->global_cache_frozen = TRUE;
2880     }
2881
2882     status = _cairo_cache_insert (&cairo_scaled_glyph_page_cache,
2883                                   &page->cache_entry);
2884     CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
2885     if (unlikely (status)) {
2886         free (page);
2887         return status;
2888     }
2889
2890     cairo_list_add_tail (&page->link, &scaled_font->glyph_pages);
2891
2892     *scaled_glyph = &page->glyphs[page->num_glyphs++];
2893     return CAIRO_STATUS_SUCCESS;
2894 }
2895
2896 static void
2897 _cairo_scaled_font_free_last_glyph (cairo_scaled_font_t *scaled_font,
2898                                    cairo_scaled_glyph_t *scaled_glyph)
2899 {
2900     cairo_scaled_glyph_page_t *page;
2901
2902     assert (! cairo_list_is_empty (&scaled_font->glyph_pages));
2903     page = cairo_list_last_entry (&scaled_font->glyph_pages,
2904                                   cairo_scaled_glyph_page_t,
2905                                   link);
2906     assert (scaled_glyph == &page->glyphs[page->num_glyphs-1]);
2907
2908     _cairo_scaled_glyph_fini (scaled_font, scaled_glyph);
2909
2910     if (--page->num_glyphs == 0) {
2911         CAIRO_MUTEX_LOCK (_cairo_scaled_glyph_page_cache_mutex);
2912         _cairo_cache_remove (&cairo_scaled_glyph_page_cache,
2913                              &page->cache_entry);
2914         CAIRO_MUTEX_UNLOCK (_cairo_scaled_glyph_page_cache_mutex);
2915     }
2916 }
2917
2918 /**
2919  * _cairo_scaled_glyph_lookup:
2920  * @scaled_font: a #cairo_scaled_font_t
2921  * @index: the glyph to create
2922  * @info: a #cairo_scaled_glyph_info_t marking which portions of
2923  * the glyph should be filled in.
2924  * @scaled_glyph_ret: a #cairo_scaled_glyph_t where the glyph
2925  * is returned.
2926  *
2927  * If the desired info is not available, (for example, when trying to
2928  * get INFO_PATH with a bitmapped font), this function will return
2929  * %CAIRO_INT_STATUS_UNSUPPORTED.
2930  *
2931  * Note: This function must be called with the scaled font frozen, and it must
2932  * remain frozen for as long as the @scaled_glyph_ret is alive. (If the scaled
2933  * font was not frozen, then there is no guarantee that the glyph would not be
2934  * evicted before you tried to access it.) See
2935  * _cairo_scaled_font_freeze_cache() and _cairo_scaled_font_thaw_cache().
2936  *
2937  * Returns: a glyph with the requested portions filled in. Glyph
2938  * lookup is cached and glyph will be automatically freed along
2939  * with the scaled_font so no explicit free is required.
2940  * @info can be one or more of:
2941  *  %CAIRO_SCALED_GLYPH_INFO_METRICS - glyph metrics and bounding box
2942  *  %CAIRO_SCALED_GLYPH_INFO_SURFACE - surface holding glyph image
2943  *  %CAIRO_SCALED_GLYPH_INFO_PATH - path holding glyph outline in device space
2944  **/
2945 cairo_int_status_t
2946 _cairo_scaled_glyph_lookup (cairo_scaled_font_t *scaled_font,
2947                             unsigned long index,
2948                             cairo_scaled_glyph_info_t info,
2949                             cairo_scaled_glyph_t **scaled_glyph_ret)
2950 {
2951     cairo_int_status_t           status = CAIRO_INT_STATUS_SUCCESS;
2952     cairo_scaled_glyph_t        *scaled_glyph;
2953     cairo_scaled_glyph_info_t    need_info;
2954
2955     *scaled_glyph_ret = NULL;
2956
2957     if (unlikely (scaled_font->status))
2958         return scaled_font->status;
2959
2960     assert (CAIRO_MUTEX_IS_LOCKED(scaled_font->mutex));
2961
2962     if (CAIRO_INJECT_FAULT ())
2963         return _cairo_error (CAIRO_STATUS_NO_MEMORY);
2964
2965     /*
2966      * Check cache for glyph
2967      */
2968     scaled_glyph = _cairo_hash_table_lookup (scaled_font->glyphs,
2969                                              (cairo_hash_entry_t *) &index);
2970     if (scaled_glyph == NULL) {
2971         status = _cairo_scaled_font_allocate_glyph (scaled_font, &scaled_glyph);
2972         if (unlikely (status))
2973             goto err;
2974
2975         memset (scaled_glyph, 0, sizeof (cairo_scaled_glyph_t));
2976         _cairo_scaled_glyph_set_index (scaled_glyph, index);
2977         cairo_list_init (&scaled_glyph->dev_privates);
2978
2979         /* ask backend to initialize metrics and shape fields */
2980         status =
2981             scaled_font->backend->scaled_glyph_init (scaled_font,
2982                                                      scaled_glyph,
2983                                                      info | CAIRO_SCALED_GLYPH_INFO_METRICS);
2984         if (unlikely (status)) {
2985             _cairo_scaled_font_free_last_glyph (scaled_font, scaled_glyph);
2986             goto err;
2987         }
2988
2989         status = _cairo_hash_table_insert (scaled_font->glyphs,
2990                                            &scaled_glyph->hash_entry);
2991         if (unlikely (status)) {
2992             _cairo_scaled_font_free_last_glyph (scaled_font, scaled_glyph);
2993             goto err;
2994         }
2995     }
2996
2997     /*
2998      * Check and see if the glyph, as provided,
2999      * already has the requested data and amend it if not
3000      */
3001     need_info = info & ~scaled_glyph->has_info;
3002     if (need_info) {
3003         status = scaled_font->backend->scaled_glyph_init (scaled_font,
3004                                                           scaled_glyph,
3005                                                           need_info);
3006         if (unlikely (status))
3007             goto err;
3008
3009         /* Don't trust the scaled_glyph_init() return value, the font
3010          * backend may not even know about some of the info.  For example,
3011          * no backend other than the user-fonts knows about recording-surface
3012          * glyph info. */
3013         if (info & ~scaled_glyph->has_info)
3014             return CAIRO_INT_STATUS_UNSUPPORTED;
3015     }
3016
3017     *scaled_glyph_ret = scaled_glyph;
3018     return CAIRO_STATUS_SUCCESS;
3019
3020 err:
3021     /* It's not an error for the backend to not support the info we want. */
3022     if (status != CAIRO_INT_STATUS_UNSUPPORTED)
3023         status = _cairo_scaled_font_set_error (scaled_font, status);
3024     return status;
3025 }
3026
3027 double
3028 _cairo_scaled_font_get_max_scale (cairo_scaled_font_t *scaled_font)
3029 {
3030     return scaled_font->max_scale;
3031 }
3032
3033
3034 /**
3035  * cairo_scaled_font_get_font_face:
3036  * @scaled_font: a #cairo_scaled_font_t
3037  *
3038  * Gets the font face that this scaled font uses.  This might be the
3039  * font face passed to cairo_scaled_font_create(), but this does not
3040  * hold true for all possible cases.
3041  *
3042  * Return value: The #cairo_font_face_t with which @scaled_font was
3043  * created.
3044  *
3045  * Since: 1.2
3046  **/
3047 cairo_font_face_t *
3048 cairo_scaled_font_get_font_face (cairo_scaled_font_t *scaled_font)
3049 {
3050     if (scaled_font->status)
3051         return (cairo_font_face_t*) &_cairo_font_face_nil;
3052
3053     if (scaled_font->original_font_face != NULL)
3054         return scaled_font->original_font_face;
3055
3056     return scaled_font->font_face;
3057 }
3058 slim_hidden_def (cairo_scaled_font_get_font_face);
3059
3060 /**
3061  * cairo_scaled_font_get_font_matrix:
3062  * @scaled_font: a #cairo_scaled_font_t
3063  * @font_matrix: return value for the matrix
3064  *
3065  * Stores the font matrix with which @scaled_font was created into
3066  * @matrix.
3067  *
3068  * Since: 1.2
3069  **/
3070 void
3071 cairo_scaled_font_get_font_matrix (cairo_scaled_font_t  *scaled_font,
3072                                    cairo_matrix_t       *font_matrix)
3073 {
3074     if (scaled_font->status) {
3075         cairo_matrix_init_identity (font_matrix);
3076         return;
3077     }
3078
3079     *font_matrix = scaled_font->font_matrix;
3080 }
3081 slim_hidden_def (cairo_scaled_font_get_font_matrix);
3082
3083 /**
3084  * cairo_scaled_font_get_ctm:
3085  * @scaled_font: a #cairo_scaled_font_t
3086  * @ctm: return value for the CTM
3087  *
3088  * Stores the CTM with which @scaled_font was created into @ctm.
3089  * Note that the translation offsets (x0, y0) of the CTM are ignored
3090  * by cairo_scaled_font_create().  So, the matrix this
3091  * function returns always has 0,0 as x0,y0.
3092  *
3093  * Since: 1.2
3094  **/
3095 void
3096 cairo_scaled_font_get_ctm (cairo_scaled_font_t  *scaled_font,
3097                            cairo_matrix_t       *ctm)
3098 {
3099     if (scaled_font->status) {
3100         cairo_matrix_init_identity (ctm);
3101         return;
3102     }
3103
3104     *ctm = scaled_font->ctm;
3105 }
3106 slim_hidden_def (cairo_scaled_font_get_ctm);
3107
3108 /**
3109  * cairo_scaled_font_get_scale_matrix:
3110  * @scaled_font: a #cairo_scaled_font_t
3111  * @scale_matrix: return value for the matrix
3112  *
3113  * Stores the scale matrix of @scaled_font into @matrix.
3114  * The scale matrix is product of the font matrix and the ctm
3115  * associated with the scaled font, and hence is the matrix mapping from
3116  * font space to device space.
3117  *
3118  * Since: 1.8
3119  **/
3120 void
3121 cairo_scaled_font_get_scale_matrix (cairo_scaled_font_t *scaled_font,
3122                                     cairo_matrix_t      *scale_matrix)
3123 {
3124     if (scaled_font->status) {
3125         cairo_matrix_init_identity (scale_matrix);
3126         return;
3127     }
3128
3129     *scale_matrix = scaled_font->scale;
3130 }
3131
3132 /**
3133  * cairo_scaled_font_get_font_options:
3134  * @scaled_font: a #cairo_scaled_font_t
3135  * @options: return value for the font options
3136  *
3137  * Stores the font options with which @scaled_font was created into
3138  * @options.
3139  *
3140  * Since: 1.2
3141  **/
3142 void
3143 cairo_scaled_font_get_font_options (cairo_scaled_font_t         *scaled_font,
3144                                     cairo_font_options_t        *options)
3145 {
3146     if (cairo_font_options_status (options))
3147         return;
3148
3149     if (scaled_font->status) {
3150         _cairo_font_options_init_default (options);
3151         return;
3152     }
3153
3154     _cairo_font_options_init_copy (options, &scaled_font->options);
3155 }
3156 slim_hidden_def (cairo_scaled_font_get_font_options);