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