Subversion Repositories Kolibri OS

Rev

Rev 1892 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed

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