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