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