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
/* cairo - a vector graphics library with display and print output
1
/* cairo - a vector graphics library with display and print output
2
 *
2
 *
3
 * Copyright © 2006, 2008 Red Hat, Inc
3
 * Copyright © 2006, 2008 Red Hat, Inc
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 Red Hat, Inc.
30
 * The Initial Developer of the Original Code is Red Hat, Inc.
31
 *
31
 *
32
 * Contributor(s):
32
 * Contributor(s):
33
 *      Kristian Høgsberg 
33
 *      Kristian Høgsberg 
34
 *      Behdad Esfahbod 
34
 *      Behdad Esfahbod 
35
 */
35
 */
36
 
36
 
37
#include "cairoint.h"
37
#include "cairoint.h"
38
#include "cairo-user-font-private.h"
38
#include "cairo-user-font-private.h"
39
#include "cairo-recording-surface-private.h"
39
#include "cairo-recording-surface-private.h"
40
#include "cairo-analysis-surface-private.h"
40
#include "cairo-analysis-surface-private.h"
41
#include "cairo-error-private.h"
41
#include "cairo-error-private.h"
42
 
42
 
43
/**
43
/**
44
 * SECTION:cairo-user-fonts
44
 * SECTION:cairo-user-fonts
45
 * @Title:User Fonts
45
 * @Title:User Fonts
46
 * @Short_Description: Font support with font data provided by the user
46
 * @Short_Description: Font support with font data provided by the user
47
 * 
47
 * 
48
 * The user-font feature allows the cairo user to provide drawings for glyphs
48
 * The user-font feature allows the cairo user to provide drawings for glyphs
49
 * in a font.  This is most useful in implementing fonts in non-standard
49
 * in a font.  This is most useful in implementing fonts in non-standard
50
 * formats, like SVG fonts and Flash fonts, but can also be used by games and
50
 * formats, like SVG fonts and Flash fonts, but can also be used by games and
51
 * other application to draw "funky" fonts.
51
 * other application to draw "funky" fonts.
52
 */
52
 **/
53
 
53
 
54
/**
54
/**
55
 * CAIRO_HAS_USER_FONT:
55
 * CAIRO_HAS_USER_FONT:
56
 *
56
 *
57
 * Defined if the user font backend is available.
57
 * Defined if the user font backend is available.
58
 * This macro can be used to conditionally compile backend-specific code.
58
 * This macro can be used to conditionally compile backend-specific code.
59
 * The user font backend is always built in versions of cairo that support
59
 * The user font backend is always built in versions of cairo that support
60
 * this feature (1.8 and later).
60
 * this feature (1.8 and later).
61
 *
61
 *
62
 * @Since: 1.8
62
 * Since: 1.8
63
 */
63
 **/
64
 
64
 
65
typedef struct _cairo_user_scaled_font_methods {
65
typedef struct _cairo_user_scaled_font_methods {
66
    cairo_user_scaled_font_init_func_t			init;
66
    cairo_user_scaled_font_init_func_t			init;
67
    cairo_user_scaled_font_render_glyph_func_t		render_glyph;
67
    cairo_user_scaled_font_render_glyph_func_t		render_glyph;
68
    cairo_user_scaled_font_unicode_to_glyph_func_t	unicode_to_glyph;
68
    cairo_user_scaled_font_unicode_to_glyph_func_t	unicode_to_glyph;
69
    cairo_user_scaled_font_text_to_glyphs_func_t	text_to_glyphs;
69
    cairo_user_scaled_font_text_to_glyphs_func_t	text_to_glyphs;
70
} cairo_user_scaled_font_methods_t;
70
} cairo_user_scaled_font_methods_t;
71
 
71
 
72
typedef struct _cairo_user_font_face {
72
typedef struct _cairo_user_font_face {
73
    cairo_font_face_t	             base;
73
    cairo_font_face_t	             base;
74
 
74
 
75
    /* Set to true after first scaled font is created.  At that point,
75
    /* Set to true after first scaled font is created.  At that point,
76
     * the scaled_font_methods cannot change anymore. */
76
     * the scaled_font_methods cannot change anymore. */
77
    cairo_bool_t		     immutable;
77
    cairo_bool_t		     immutable;
78
 
78
 
79
    cairo_user_scaled_font_methods_t scaled_font_methods;
79
    cairo_user_scaled_font_methods_t scaled_font_methods;
80
} cairo_user_font_face_t;
80
} cairo_user_font_face_t;
81
 
81
 
82
typedef struct _cairo_user_scaled_font {
82
typedef struct _cairo_user_scaled_font {
83
    cairo_scaled_font_t  base;
83
    cairo_scaled_font_t  base;
84
 
84
 
85
    cairo_text_extents_t default_glyph_extents;
85
    cairo_text_extents_t default_glyph_extents;
86
 
86
 
87
    /* space to compute extents in, and factors to convert back to user space */
87
    /* space to compute extents in, and factors to convert back to user space */
88
    cairo_matrix_t extent_scale;
88
    cairo_matrix_t extent_scale;
89
    double extent_x_scale;
89
    double extent_x_scale;
90
    double extent_y_scale;
90
    double extent_y_scale;
91
 
91
 
92
    /* multiplier for metrics hinting */
92
    /* multiplier for metrics hinting */
93
    double snap_x_scale;
93
    double snap_x_scale;
94
    double snap_y_scale;
94
    double snap_y_scale;
95
 
95
 
96
} cairo_user_scaled_font_t;
96
} cairo_user_scaled_font_t;
97
 
97
 
98
/* #cairo_user_scaled_font_t */
98
/* #cairo_user_scaled_font_t */
99
 
99
 
100
static cairo_surface_t *
100
static cairo_surface_t *
101
_cairo_user_scaled_font_create_recording_surface (const cairo_user_scaled_font_t *scaled_font)
101
_cairo_user_scaled_font_create_recording_surface (const cairo_user_scaled_font_t *scaled_font)
102
{
102
{
103
    cairo_content_t content;
103
    cairo_content_t content;
104
 
104
 
105
    content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ?
105
    content = scaled_font->base.options.antialias == CAIRO_ANTIALIAS_SUBPIXEL ?
106
						     CAIRO_CONTENT_COLOR_ALPHA :
106
						     CAIRO_CONTENT_COLOR_ALPHA :
107
						     CAIRO_CONTENT_ALPHA;
107
						     CAIRO_CONTENT_ALPHA;
108
 
108
 
109
    return cairo_recording_surface_create (content, NULL);
109
    return cairo_recording_surface_create (content, NULL);
110
}
110
}
111
 
111
 
112
 
112
 
113
static cairo_t *
113
static cairo_t *
114
_cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t *scaled_font,
114
_cairo_user_scaled_font_create_recording_context (const cairo_user_scaled_font_t *scaled_font,
115
						  cairo_surface_t                *recording_surface)
115
						  cairo_surface_t                *recording_surface)
116
{
116
{
117
    cairo_t *cr;
117
    cairo_t *cr;
118
 
118
 
119
    cr = cairo_create (recording_surface);
119
    cr = cairo_create (recording_surface);
120
 
120
 
121
    if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
121
    if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
122
        cairo_matrix_t scale;
122
        cairo_matrix_t scale;
123
	scale = scaled_font->base.scale;
123
	scale = scaled_font->base.scale;
124
	scale.x0 = scale.y0 = 0.;
124
	scale.x0 = scale.y0 = 0.;
125
	cairo_set_matrix (cr, &scale);
125
	cairo_set_matrix (cr, &scale);
126
    }
126
    }
127
 
127
 
128
    cairo_set_font_size (cr, 1.0);
128
    cairo_set_font_size (cr, 1.0);
129
    cairo_set_font_options (cr, &scaled_font->base.options);
129
    cairo_set_font_options (cr, &scaled_font->base.options);
130
    cairo_set_source_rgb (cr, 1., 1., 1.);
130
    cairo_set_source_rgb (cr, 1., 1., 1.);
131
 
131
 
132
    return cr;
132
    return cr;
133
}
133
}
134
 
134
 
135
static cairo_int_status_t
135
static cairo_int_status_t
136
_cairo_user_scaled_glyph_init (void			 *abstract_font,
136
_cairo_user_scaled_glyph_init (void			 *abstract_font,
137
			       cairo_scaled_glyph_t	 *scaled_glyph,
137
			       cairo_scaled_glyph_t	 *scaled_glyph,
138
			       cairo_scaled_glyph_info_t  info)
138
			       cairo_scaled_glyph_info_t  info)
139
{
139
{
140
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
140
    cairo_int_status_t status = CAIRO_STATUS_SUCCESS;
141
    cairo_user_scaled_font_t *scaled_font = abstract_font;
141
    cairo_user_scaled_font_t *scaled_font = abstract_font;
142
    cairo_surface_t *recording_surface = scaled_glyph->recording_surface;
142
    cairo_surface_t *recording_surface = scaled_glyph->recording_surface;
143
 
143
 
144
    if (!scaled_glyph->recording_surface) {
144
    if (!scaled_glyph->recording_surface) {
145
	cairo_user_font_face_t *face =
145
	cairo_user_font_face_t *face =
146
	    (cairo_user_font_face_t *) scaled_font->base.font_face;
146
	    (cairo_user_font_face_t *) scaled_font->base.font_face;
147
	cairo_text_extents_t extents = scaled_font->default_glyph_extents;
147
	cairo_text_extents_t extents = scaled_font->default_glyph_extents;
148
	cairo_t *cr;
148
	cairo_t *cr;
149
 
149
 
150
	if (!face->scaled_font_methods.render_glyph)
150
	if (!face->scaled_font_methods.render_glyph)
151
	    return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
151
	    return CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED;
152
 
152
 
153
	recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font);
153
	recording_surface = _cairo_user_scaled_font_create_recording_surface (scaled_font);
154
 
154
 
155
	/* special case for 0 rank matrix (as in _cairo_scaled_font_init): empty surface */
155
	/* special case for 0 rank matrix (as in _cairo_scaled_font_init): empty surface */
156
        if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
156
        if (!_cairo_matrix_is_scale_0 (&scaled_font->base.scale)) {
157
	    cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface);
157
	    cr = _cairo_user_scaled_font_create_recording_context (scaled_font, recording_surface);
158
	    status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
158
	    status = face->scaled_font_methods.render_glyph ((cairo_scaled_font_t *)scaled_font,
159
							     _cairo_scaled_glyph_index(scaled_glyph),
159
							     _cairo_scaled_glyph_index(scaled_glyph),
160
							     cr, &extents);
160
							     cr, &extents);
161
	    if (status == CAIRO_STATUS_SUCCESS)
161
	    if (status == CAIRO_INT_STATUS_SUCCESS)
162
	        status = cairo_status (cr);
162
	        status = cairo_status (cr);
163
 
163
 
164
	    cairo_destroy (cr);
164
	    cairo_destroy (cr);
165
 
165
 
166
	    if (unlikely (status)) {
166
	    if (unlikely (status)) {
167
	        cairo_surface_destroy (recording_surface);
167
	        cairo_surface_destroy (recording_surface);
168
	        return status;
168
	        return status;
169
	    }
169
	    }
170
	}
170
	}
171
 
171
 
172
	_cairo_scaled_glyph_set_recording_surface (scaled_glyph,
172
	_cairo_scaled_glyph_set_recording_surface (scaled_glyph,
173
						   &scaled_font->base,
173
						   &scaled_font->base,
174
						   recording_surface);
174
						   recording_surface);
175
 
175
 
176
 
176
 
177
	/* set metrics */
177
	/* set metrics */
178
 
178
 
179
	if (extents.width == 0.) {
179
	if (extents.width == 0.) {
180
	    cairo_box_t bbox;
180
	    cairo_box_t bbox;
181
	    double x1, y1, x2, y2;
181
	    double x1, y1, x2, y2;
182
	    double x_scale, y_scale;
182
	    double x_scale, y_scale;
183
 
183
 
184
	    /* Compute extents.x/y/width/height from recording_surface,
184
	    /* Compute extents.x/y/width/height from recording_surface,
185
	     * in font space.
185
	     * in font space.
186
	     */
186
	     */
187
	    status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
187
	    status = _cairo_recording_surface_get_bbox ((cairo_recording_surface_t *) recording_surface,
188
							&bbox,
188
							&bbox,
189
							&scaled_font->extent_scale);
189
							&scaled_font->extent_scale);
190
	    if (unlikely (status))
190
	    if (unlikely (status))
191
		return status;
191
		return status;
192
 
192
 
193
	    _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
193
	    _cairo_box_to_doubles (&bbox, &x1, &y1, &x2, &y2);
194
 
194
 
195
	    x_scale = scaled_font->extent_x_scale;
195
	    x_scale = scaled_font->extent_x_scale;
196
	    y_scale = scaled_font->extent_y_scale;
196
	    y_scale = scaled_font->extent_y_scale;
197
	    extents.x_bearing = x1 * x_scale;
197
	    extents.x_bearing = x1 * x_scale;
198
	    extents.y_bearing = y1 * y_scale;
198
	    extents.y_bearing = y1 * y_scale;
199
	    extents.width     = (x2 - x1) * x_scale;
199
	    extents.width     = (x2 - x1) * x_scale;
200
	    extents.height    = (y2 - y1) * y_scale;
200
	    extents.height    = (y2 - y1) * y_scale;
201
	}
201
	}
202
 
202
 
203
	if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
203
	if (scaled_font->base.options.hint_metrics != CAIRO_HINT_METRICS_OFF) {
204
	    extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale;
204
	    extents.x_advance = _cairo_lround (extents.x_advance / scaled_font->snap_x_scale) * scaled_font->snap_x_scale;
205
	    extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale;
205
	    extents.y_advance = _cairo_lround (extents.y_advance / scaled_font->snap_y_scale) * scaled_font->snap_y_scale;
206
	}
206
	}
207
 
207
 
208
	_cairo_scaled_glyph_set_metrics (scaled_glyph,
208
	_cairo_scaled_glyph_set_metrics (scaled_glyph,
209
					 &scaled_font->base,
209
					 &scaled_font->base,
210
					 &extents);
210
					 &extents);
211
    }
211
    }
212
 
212
 
213
    if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
213
    if (info & CAIRO_SCALED_GLYPH_INFO_SURFACE) {
214
	cairo_surface_t	*surface;
214
	cairo_surface_t	*surface;
215
	cairo_format_t format;
215
	cairo_format_t format;
216
	int width, height;
216
	int width, height;
217
 
217
 
218
	/* TODO
218
	/* TODO
219
	 * extend the glyph cache to support argb glyphs.
219
	 * extend the glyph cache to support argb glyphs.
220
	 * need to figure out the semantics and interaction with subpixel
220
	 * need to figure out the semantics and interaction with subpixel
221
	 * rendering first.
221
	 * rendering first.
222
	 */
222
	 */
223
 
223
 
224
	width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
224
	width = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.x) -
225
	  _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
225
	  _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x);
226
	height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
226
	height = _cairo_fixed_integer_ceil (scaled_glyph->bbox.p2.y) -
227
	  _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
227
	  _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y);
228
 
228
 
229
	switch (scaled_font->base.options.antialias) {
229
	switch (scaled_font->base.options.antialias) {
230
	default:
230
	default:
231
	case CAIRO_ANTIALIAS_DEFAULT:
231
	case CAIRO_ANTIALIAS_DEFAULT:
-
 
232
	case CAIRO_ANTIALIAS_FAST:
-
 
233
	case CAIRO_ANTIALIAS_GOOD:
232
	case CAIRO_ANTIALIAS_GRAY:	format = CAIRO_FORMAT_A8;	break;
234
	case CAIRO_ANTIALIAS_GRAY:	format = CAIRO_FORMAT_A8;	break;
233
	case CAIRO_ANTIALIAS_NONE:	format = CAIRO_FORMAT_A1;	break;
235
	case CAIRO_ANTIALIAS_NONE:	format = CAIRO_FORMAT_A1;	break;
-
 
236
	case CAIRO_ANTIALIAS_BEST:
234
	case CAIRO_ANTIALIAS_SUBPIXEL:	format = CAIRO_FORMAT_ARGB32;	break;
237
	case CAIRO_ANTIALIAS_SUBPIXEL:	format = CAIRO_FORMAT_ARGB32;	break;
235
	}
238
	}
236
	surface = cairo_image_surface_create (format, width, height);
239
	surface = cairo_image_surface_create (format, width, height);
237
 
240
 
238
	cairo_surface_set_device_offset (surface,
241
	cairo_surface_set_device_offset (surface,
239
	                                 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
242
	                                 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.x),
240
	                                 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
243
	                                 - _cairo_fixed_integer_floor (scaled_glyph->bbox.p1.y));
241
	status = _cairo_recording_surface_replay (recording_surface, surface);
244
	status = _cairo_recording_surface_replay (recording_surface, surface);
242
 
245
 
243
	if (unlikely (status)) {
246
	if (unlikely (status)) {
244
	    cairo_surface_destroy(surface);
247
	    cairo_surface_destroy(surface);
245
	    return status;
248
	    return status;
246
	}
249
	}
247
 
250
 
248
	_cairo_scaled_glyph_set_surface (scaled_glyph,
251
	_cairo_scaled_glyph_set_surface (scaled_glyph,
249
					 &scaled_font->base,
252
					 &scaled_font->base,
250
					 (cairo_image_surface_t *) surface);
253
					 (cairo_image_surface_t *) surface);
251
    }
254
    }
252
 
255
 
253
    if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
256
    if (info & CAIRO_SCALED_GLYPH_INFO_PATH) {
254
	cairo_path_fixed_t *path = _cairo_path_fixed_create ();
257
	cairo_path_fixed_t *path = _cairo_path_fixed_create ();
255
	if (!path)
258
	if (!path)
256
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
259
	    return _cairo_error (CAIRO_STATUS_NO_MEMORY);
257
 
260
 
258
	status = _cairo_recording_surface_get_path (recording_surface, path);
261
	status = _cairo_recording_surface_get_path (recording_surface, path);
259
	if (unlikely (status)) {
262
	if (unlikely (status)) {
260
	    _cairo_path_fixed_destroy (path);
263
	    _cairo_path_fixed_destroy (path);
261
	    return status;
264
	    return status;
262
	}
265
	}
263
 
266
 
264
	_cairo_scaled_glyph_set_path (scaled_glyph,
267
	_cairo_scaled_glyph_set_path (scaled_glyph,
265
				      &scaled_font->base,
268
				      &scaled_font->base,
266
				      path);
269
				      path);
267
    }
270
    }
268
 
271
 
269
    return status;
272
    return status;
270
}
273
}
271
 
274
 
272
static unsigned long
275
static unsigned long
273
_cairo_user_ucs4_to_index (void	    *abstract_font,
276
_cairo_user_ucs4_to_index (void	    *abstract_font,
274
			   uint32_t  ucs4)
277
			   uint32_t  ucs4)
275
{
278
{
276
    cairo_user_scaled_font_t *scaled_font = abstract_font;
279
    cairo_user_scaled_font_t *scaled_font = abstract_font;
277
    cairo_user_font_face_t *face =
280
    cairo_user_font_face_t *face =
278
	(cairo_user_font_face_t *) scaled_font->base.font_face;
281
	(cairo_user_font_face_t *) scaled_font->base.font_face;
279
    unsigned long glyph = 0;
282
    unsigned long glyph = 0;
280
 
283
 
281
    if (face->scaled_font_methods.unicode_to_glyph) {
284
    if (face->scaled_font_methods.unicode_to_glyph) {
282
	cairo_status_t status;
285
	cairo_status_t status;
283
 
286
 
284
	status = face->scaled_font_methods.unicode_to_glyph (&scaled_font->base,
287
	status = face->scaled_font_methods.unicode_to_glyph (&scaled_font->base,
285
							     ucs4, &glyph);
288
							     ucs4, &glyph);
286
 
289
 
287
	if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
290
	if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
288
	    goto not_implemented;
291
	    goto not_implemented;
289
 
292
 
290
	if (status != CAIRO_STATUS_SUCCESS) {
293
	if (status != CAIRO_STATUS_SUCCESS) {
291
	    status = _cairo_scaled_font_set_error (&scaled_font->base, status);
294
	    status = _cairo_scaled_font_set_error (&scaled_font->base, status);
292
	    glyph = 0;
295
	    glyph = 0;
293
	}
296
	}
294
 
297
 
295
    } else {
298
    } else {
296
not_implemented:
299
not_implemented:
297
	glyph = ucs4;
300
	glyph = ucs4;
298
    }
301
    }
299
 
302
 
300
    return glyph;
303
    return glyph;
301
}
304
}
302
 
305
 
303
static cairo_int_status_t
306
static cairo_int_status_t
304
_cairo_user_text_to_glyphs (void		      *abstract_font,
307
_cairo_user_text_to_glyphs (void		      *abstract_font,
305
			    double		       x,
308
			    double		       x,
306
			    double		       y,
309
			    double		       y,
307
			    const char		      *utf8,
310
			    const char		      *utf8,
308
			    int			       utf8_len,
311
			    int			       utf8_len,
309
			    cairo_glyph_t	     **glyphs,
312
			    cairo_glyph_t	     **glyphs,
310
			    int			       *num_glyphs,
313
			    int			       *num_glyphs,
311
			    cairo_text_cluster_t      **clusters,
314
			    cairo_text_cluster_t      **clusters,
312
			    int			       *num_clusters,
315
			    int			       *num_clusters,
313
			    cairo_text_cluster_flags_t *cluster_flags)
316
			    cairo_text_cluster_flags_t *cluster_flags)
314
{
317
{
315
    cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
318
    cairo_int_status_t status = CAIRO_INT_STATUS_UNSUPPORTED;
316
 
319
 
317
    cairo_user_scaled_font_t *scaled_font = abstract_font;
320
    cairo_user_scaled_font_t *scaled_font = abstract_font;
318
    cairo_user_font_face_t *face =
321
    cairo_user_font_face_t *face =
319
	(cairo_user_font_face_t *) scaled_font->base.font_face;
322
	(cairo_user_font_face_t *) scaled_font->base.font_face;
320
 
323
 
321
    if (face->scaled_font_methods.text_to_glyphs) {
324
    if (face->scaled_font_methods.text_to_glyphs) {
322
	int i;
325
	int i;
323
	cairo_glyph_t *orig_glyphs = *glyphs;
326
	cairo_glyph_t *orig_glyphs = *glyphs;
324
	int orig_num_glyphs = *num_glyphs;
327
	int orig_num_glyphs = *num_glyphs;
325
 
328
 
326
	status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
329
	status = face->scaled_font_methods.text_to_glyphs (&scaled_font->base,
327
							   utf8, utf8_len,
330
							   utf8, utf8_len,
328
							   glyphs, num_glyphs,
331
							   glyphs, num_glyphs,
329
							   clusters, num_clusters, cluster_flags);
332
							   clusters, num_clusters, cluster_flags);
330
 
333
 
331
	if (status != CAIRO_STATUS_SUCCESS &&
334
	if (status != CAIRO_INT_STATUS_SUCCESS &&
332
	    status != CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
335
	    status != CAIRO_INT_STATUS_USER_FONT_NOT_IMPLEMENTED)
333
	    return status;
336
	    return status;
-
 
337
 
334
 
338
	if (status == CAIRO_INT_STATUS_USER_FONT_NOT_IMPLEMENTED ||
335
	if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED || *num_glyphs < 0) {
339
	    *num_glyphs < 0) {
336
	    if (orig_glyphs != *glyphs) {
340
	    if (orig_glyphs != *glyphs) {
337
		cairo_glyph_free (*glyphs);
341
		cairo_glyph_free (*glyphs);
338
		*glyphs = orig_glyphs;
342
		*glyphs = orig_glyphs;
339
	    }
343
	    }
340
	    *num_glyphs = orig_num_glyphs;
344
	    *num_glyphs = orig_num_glyphs;
341
	    return CAIRO_INT_STATUS_UNSUPPORTED;
345
	    return CAIRO_INT_STATUS_UNSUPPORTED;
342
	}
346
	}
343
 
347
 
344
	/* Convert from font space to user space and add x,y */
348
	/* Convert from font space to user space and add x,y */
345
	for (i = 0; i < *num_glyphs; i++) {
349
	for (i = 0; i < *num_glyphs; i++) {
346
	    double gx = (*glyphs)[i].x;
350
	    double gx = (*glyphs)[i].x;
347
	    double gy = (*glyphs)[i].y;
351
	    double gy = (*glyphs)[i].y;
348
 
352
 
349
	    cairo_matrix_transform_point (&scaled_font->base.font_matrix,
353
	    cairo_matrix_transform_point (&scaled_font->base.font_matrix,
350
					  &gx, &gy);
354
					  &gx, &gy);
351
 
355
 
352
	    (*glyphs)[i].x = gx + x;
356
	    (*glyphs)[i].x = gx + x;
353
	    (*glyphs)[i].y = gy + y;
357
	    (*glyphs)[i].y = gy + y;
354
	}
358
	}
355
    }
359
    }
356
 
360
 
357
    return status;
361
    return status;
358
}
362
}
359
 
363
 
360
static cairo_status_t
364
static cairo_status_t
361
_cairo_user_font_face_scaled_font_create (void                        *abstract_face,
365
_cairo_user_font_face_scaled_font_create (void                        *abstract_face,
362
					  const cairo_matrix_t        *font_matrix,
366
					  const cairo_matrix_t        *font_matrix,
363
					  const cairo_matrix_t        *ctm,
367
					  const cairo_matrix_t        *ctm,
364
					  const cairo_font_options_t  *options,
368
					  const cairo_font_options_t  *options,
365
					  cairo_scaled_font_t        **scaled_font);
369
					  cairo_scaled_font_t        **scaled_font);
366
 
370
 
367
static cairo_status_t
371
static cairo_status_t
368
_cairo_user_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
372
_cairo_user_font_face_create_for_toy (cairo_toy_font_face_t   *toy_face,
369
				      cairo_font_face_t      **font_face)
373
				      cairo_font_face_t      **font_face)
370
{
374
{
371
    return _cairo_font_face_twin_create_for_toy (toy_face, font_face);
375
    return _cairo_font_face_twin_create_for_toy (toy_face, font_face);
372
}
376
}
373
 
377
 
374
static const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = {
378
static const cairo_scaled_font_backend_t _cairo_user_scaled_font_backend = {
375
    CAIRO_FONT_TYPE_USER,
379
    CAIRO_FONT_TYPE_USER,
376
    NULL,	/* scaled_font_fini */
380
    NULL,	/* scaled_font_fini */
377
    _cairo_user_scaled_glyph_init,
381
    _cairo_user_scaled_glyph_init,
378
    _cairo_user_text_to_glyphs,
382
    _cairo_user_text_to_glyphs,
379
    _cairo_user_ucs4_to_index,
383
    _cairo_user_ucs4_to_index,
380
    NULL,	/* show_glyphs */
384
    NULL,	/* show_glyphs */
381
    NULL,	/* load_truetype_table */
385
    NULL,	/* load_truetype_table */
382
    NULL	/* index_to_ucs4 */
386
    NULL	/* index_to_ucs4 */
383
};
387
};
384
 
388
 
385
/* #cairo_user_font_face_t */
389
/* #cairo_user_font_face_t */
386
 
390
 
387
static cairo_status_t
391
static cairo_status_t
388
_cairo_user_font_face_scaled_font_create (void                        *abstract_face,
392
_cairo_user_font_face_scaled_font_create (void                        *abstract_face,
389
					  const cairo_matrix_t        *font_matrix,
393
					  const cairo_matrix_t        *font_matrix,
390
					  const cairo_matrix_t        *ctm,
394
					  const cairo_matrix_t        *ctm,
391
					  const cairo_font_options_t  *options,
395
					  const cairo_font_options_t  *options,
392
					  cairo_scaled_font_t        **scaled_font)
396
					  cairo_scaled_font_t        **scaled_font)
393
{
397
{
394
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
398
    cairo_status_t status = CAIRO_STATUS_SUCCESS;
395
    cairo_user_font_face_t *font_face = abstract_face;
399
    cairo_user_font_face_t *font_face = abstract_face;
396
    cairo_user_scaled_font_t *user_scaled_font = NULL;
400
    cairo_user_scaled_font_t *user_scaled_font = NULL;
397
    cairo_font_extents_t font_extents = {1., 0., 1., 1., 0.};
401
    cairo_font_extents_t font_extents = {1., 0., 1., 1., 0.};
398
 
402
 
399
    font_face->immutable = TRUE;
403
    font_face->immutable = TRUE;
400
 
404
 
401
    user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t));
405
    user_scaled_font = malloc (sizeof (cairo_user_scaled_font_t));
402
    if (unlikely (user_scaled_font == NULL))
406
    if (unlikely (user_scaled_font == NULL))
403
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
407
	return _cairo_error (CAIRO_STATUS_NO_MEMORY);
404
 
408
 
405
    status = _cairo_scaled_font_init (&user_scaled_font->base,
409
    status = _cairo_scaled_font_init (&user_scaled_font->base,
406
				      &font_face->base,
410
				      &font_face->base,
407
				      font_matrix, ctm, options,
411
				      font_matrix, ctm, options,
408
				      &_cairo_user_scaled_font_backend);
412
				      &_cairo_user_scaled_font_backend);
409
 
413
 
410
    if (unlikely (status)) {
414
    if (unlikely (status)) {
411
	free (user_scaled_font);
415
	free (user_scaled_font);
412
	return status;
416
	return status;
413
    }
417
    }
414
 
418
 
415
    /* XXX metrics hinting? */
419
    /* XXX metrics hinting? */
416
 
420
 
417
    /* compute a normalized version of font scale matrix to compute
421
    /* compute a normalized version of font scale matrix to compute
418
     * extents in.  This is to minimize error caused by the cairo_fixed_t
422
     * extents in.  This is to minimize error caused by the cairo_fixed_t
419
     * representation. */
423
     * representation. */
420
    {
424
    {
421
	double fixed_scale, x_scale, y_scale;
425
	double fixed_scale, x_scale, y_scale;
422
 
426
 
423
	user_scaled_font->extent_scale = user_scaled_font->base.scale_inverse;
427
	user_scaled_font->extent_scale = user_scaled_font->base.scale_inverse;
424
	status = _cairo_matrix_compute_basis_scale_factors (&user_scaled_font->extent_scale,
428
	status = _cairo_matrix_compute_basis_scale_factors (&user_scaled_font->extent_scale,
425
						      &x_scale, &y_scale,
429
						      &x_scale, &y_scale,
426
						      1);
430
						      1);
427
	if (status == CAIRO_STATUS_SUCCESS) {
431
	if (status == CAIRO_STATUS_SUCCESS) {
428
 
432
 
429
	    if (x_scale == 0) x_scale = 1.;
433
	    if (x_scale == 0) x_scale = 1.;
430
	    if (y_scale == 0) y_scale = 1.;
434
	    if (y_scale == 0) y_scale = 1.;
431
 
435
 
432
	    user_scaled_font->snap_x_scale = x_scale;
436
	    user_scaled_font->snap_x_scale = x_scale;
433
	    user_scaled_font->snap_y_scale = y_scale;
437
	    user_scaled_font->snap_y_scale = y_scale;
434
 
438
 
435
	    /* since glyphs are pretty much 1.0x1.0, we can reduce error by
439
	    /* since glyphs are pretty much 1.0x1.0, we can reduce error by
436
	     * scaling to a larger square.  say, 1024.x1024. */
440
	     * scaling to a larger square.  say, 1024.x1024. */
437
	    fixed_scale = 1024.;
441
	    fixed_scale = 1024.;
438
	    x_scale /= fixed_scale;
442
	    x_scale /= fixed_scale;
439
	    y_scale /= fixed_scale;
443
	    y_scale /= fixed_scale;
440
 
444
 
441
	    cairo_matrix_scale (&user_scaled_font->extent_scale, 1. / x_scale, 1. / y_scale);
445
	    cairo_matrix_scale (&user_scaled_font->extent_scale, 1. / x_scale, 1. / y_scale);
442
 
446
 
443
	    user_scaled_font->extent_x_scale = x_scale;
447
	    user_scaled_font->extent_x_scale = x_scale;
444
	    user_scaled_font->extent_y_scale = y_scale;
448
	    user_scaled_font->extent_y_scale = y_scale;
445
	}
449
	}
446
    }
450
    }
447
 
451
 
448
    if (status == CAIRO_STATUS_SUCCESS &&
452
    if (status == CAIRO_STATUS_SUCCESS &&
449
	font_face->scaled_font_methods.init != NULL)
453
	font_face->scaled_font_methods.init != NULL)
450
    {
454
    {
451
	/* Lock the scaled_font mutex such that user doesn't accidentally try
455
	/* Lock the scaled_font mutex such that user doesn't accidentally try
452
         * to use it just yet. */
456
         * to use it just yet. */
453
	CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex);
457
	CAIRO_MUTEX_LOCK (user_scaled_font->base.mutex);
454
 
458
 
455
	/* Give away fontmap lock such that user-font can use other fonts */
459
	/* Give away fontmap lock such that user-font can use other fonts */
456
	status = _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base);
460
	status = _cairo_scaled_font_register_placeholder_and_unlock_font_map (&user_scaled_font->base);
457
	if (status == CAIRO_STATUS_SUCCESS) {
461
	if (status == CAIRO_STATUS_SUCCESS) {
458
	    cairo_surface_t *recording_surface;
462
	    cairo_surface_t *recording_surface;
459
	    cairo_t *cr;
463
	    cairo_t *cr;
460
 
464
 
461
	    recording_surface = _cairo_user_scaled_font_create_recording_surface (user_scaled_font);
465
	    recording_surface = _cairo_user_scaled_font_create_recording_surface (user_scaled_font);
462
	    cr = _cairo_user_scaled_font_create_recording_context (user_scaled_font, recording_surface);
466
	    cr = _cairo_user_scaled_font_create_recording_context (user_scaled_font, recording_surface);
463
	    cairo_surface_destroy (recording_surface);
467
	    cairo_surface_destroy (recording_surface);
464
 
468
 
465
	    status = font_face->scaled_font_methods.init (&user_scaled_font->base,
469
	    status = font_face->scaled_font_methods.init (&user_scaled_font->base,
466
							  cr,
470
							  cr,
467
							  &font_extents);
471
							  &font_extents);
468
 
472
 
469
	    if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
473
	    if (status == CAIRO_STATUS_USER_FONT_NOT_IMPLEMENTED)
470
		status = CAIRO_STATUS_SUCCESS;
474
		status = CAIRO_STATUS_SUCCESS;
471
 
475
 
472
	    if (status == CAIRO_STATUS_SUCCESS)
476
	    if (status == CAIRO_STATUS_SUCCESS)
473
		status = cairo_status (cr);
477
		status = cairo_status (cr);
474
 
478
 
475
	    cairo_destroy (cr);
479
	    cairo_destroy (cr);
476
 
480
 
477
	    _cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base);
481
	    _cairo_scaled_font_unregister_placeholder_and_lock_font_map (&user_scaled_font->base);
478
	}
482
	}
479
 
483
 
480
	CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex);
484
	CAIRO_MUTEX_UNLOCK (user_scaled_font->base.mutex);
481
    }
485
    }
482
 
486
 
483
    if (status == CAIRO_STATUS_SUCCESS)
487
    if (status == CAIRO_STATUS_SUCCESS)
484
	status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
488
	status = _cairo_scaled_font_set_metrics (&user_scaled_font->base, &font_extents);
485
 
489
 
486
    if (status != CAIRO_STATUS_SUCCESS) {
490
    if (status != CAIRO_STATUS_SUCCESS) {
487
        _cairo_scaled_font_fini (&user_scaled_font->base);
491
        _cairo_scaled_font_fini (&user_scaled_font->base);
488
	free (user_scaled_font);
492
	free (user_scaled_font);
489
    } else {
493
    } else {
490
        user_scaled_font->default_glyph_extents.x_bearing = 0.;
494
        user_scaled_font->default_glyph_extents.x_bearing = 0.;
491
        user_scaled_font->default_glyph_extents.y_bearing = -font_extents.ascent;
495
        user_scaled_font->default_glyph_extents.y_bearing = -font_extents.ascent;
492
        user_scaled_font->default_glyph_extents.width = 0.;
496
        user_scaled_font->default_glyph_extents.width = 0.;
493
        user_scaled_font->default_glyph_extents.height = font_extents.ascent + font_extents.descent;
497
        user_scaled_font->default_glyph_extents.height = font_extents.ascent + font_extents.descent;
494
        user_scaled_font->default_glyph_extents.x_advance = font_extents.max_x_advance;
498
        user_scaled_font->default_glyph_extents.x_advance = font_extents.max_x_advance;
495
        user_scaled_font->default_glyph_extents.y_advance = 0.;
499
        user_scaled_font->default_glyph_extents.y_advance = 0.;
496
 
500
 
497
	*scaled_font = &user_scaled_font->base;
501
	*scaled_font = &user_scaled_font->base;
498
    }
502
    }
499
 
503
 
500
    return status;
504
    return status;
501
}
505
}
502
 
506
 
503
const cairo_font_face_backend_t _cairo_user_font_face_backend = {
507
const cairo_font_face_backend_t _cairo_user_font_face_backend = {
504
    CAIRO_FONT_TYPE_USER,
508
    CAIRO_FONT_TYPE_USER,
505
    _cairo_user_font_face_create_for_toy,
509
    _cairo_user_font_face_create_for_toy,
506
    NULL,	/* destroy */
510
    NULL,	/* destroy */
507
    _cairo_user_font_face_scaled_font_create
511
    _cairo_user_font_face_scaled_font_create
508
};
512
};
509
 
513
 
510
 
514
 
511
cairo_bool_t
515
cairo_bool_t
512
_cairo_font_face_is_user (cairo_font_face_t *font_face)
516
_cairo_font_face_is_user (cairo_font_face_t *font_face)
513
{
517
{
514
    return font_face->backend == &_cairo_user_font_face_backend;
518
    return font_face->backend == &_cairo_user_font_face_backend;
515
}
519
}
516
 
520
 
517
/* Implement the public interface */
521
/* Implement the public interface */
518
 
522
 
519
/**
523
/**
520
 * cairo_user_font_face_create:
524
 * cairo_user_font_face_create:
521
 *
525
 *
522
 * Creates a new user font-face.
526
 * Creates a new user font-face.
523
 *
527
 *
524
 * Use the setter functions to associate callbacks with the returned
528
 * Use the setter functions to associate callbacks with the returned
525
 * user font.  The only mandatory callback is render_glyph.
529
 * user font.  The only mandatory callback is render_glyph.
526
 *
530
 *
527
 * After the font-face is created, the user can attach arbitrary data
531
 * After the font-face is created, the user can attach arbitrary data
528
 * (the actual font data) to it using cairo_font_face_set_user_data()
532
 * (the actual font data) to it using cairo_font_face_set_user_data()
529
 * and access it from the user-font callbacks by using
533
 * and access it from the user-font callbacks by using
530
 * cairo_scaled_font_get_font_face() followed by
534
 * cairo_scaled_font_get_font_face() followed by
531
 * cairo_font_face_get_user_data().
535
 * cairo_font_face_get_user_data().
532
 *
536
 *
533
 * Return value: a newly created #cairo_font_face_t. Free with
537
 * Return value: a newly created #cairo_font_face_t. Free with
534
 *  cairo_font_face_destroy() when you are done using it.
538
 *  cairo_font_face_destroy() when you are done using it.
535
 *
539
 *
536
 * Since: 1.8
540
 * Since: 1.8
537
 **/
541
 **/
538
cairo_font_face_t *
542
cairo_font_face_t *
539
cairo_user_font_face_create (void)
543
cairo_user_font_face_create (void)
540
{
544
{
541
    cairo_user_font_face_t *font_face;
545
    cairo_user_font_face_t *font_face;
542
 
546
 
543
    font_face = malloc (sizeof (cairo_user_font_face_t));
547
    font_face = malloc (sizeof (cairo_user_font_face_t));
544
    if (!font_face) {
548
    if (!font_face) {
545
	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
549
	_cairo_error_throw (CAIRO_STATUS_NO_MEMORY);
546
	return (cairo_font_face_t *)&_cairo_font_face_nil;
550
	return (cairo_font_face_t *)&_cairo_font_face_nil;
547
    }
551
    }
548
 
552
 
549
    _cairo_font_face_init (&font_face->base, &_cairo_user_font_face_backend);
553
    _cairo_font_face_init (&font_face->base, &_cairo_user_font_face_backend);
550
 
554
 
551
    font_face->immutable = FALSE;
555
    font_face->immutable = FALSE;
552
    memset (&font_face->scaled_font_methods, 0, sizeof (font_face->scaled_font_methods));
556
    memset (&font_face->scaled_font_methods, 0, sizeof (font_face->scaled_font_methods));
553
 
557
 
554
    return &font_face->base;
558
    return &font_face->base;
555
}
559
}
556
slim_hidden_def(cairo_user_font_face_create);
560
slim_hidden_def(cairo_user_font_face_create);
557
 
561
 
558
/* User-font method setters */
562
/* User-font method setters */
559
 
563
 
560
 
564
 
561
/**
565
/**
562
 * cairo_user_font_face_set_init_func:
566
 * cairo_user_font_face_set_init_func:
563
 * @font_face: A user font face
567
 * @font_face: A user font face
564
 * @init_func: The init callback, or %NULL
568
 * @init_func: The init callback, or %NULL
565
 *
569
 *
566
 * Sets the scaled-font initialization function of a user-font.
570
 * Sets the scaled-font initialization function of a user-font.
567
 * See #cairo_user_scaled_font_init_func_t for details of how the callback
571
 * See #cairo_user_scaled_font_init_func_t for details of how the callback
568
 * works.
572
 * works.
569
 *
573
 *
570
 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
574
 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
571
 * error will occur.  A user font-face is immutable as soon as a scaled-font
575
 * error will occur.  A user font-face is immutable as soon as a scaled-font
572
 * is created from it.
576
 * is created from it.
573
 *
577
 *
574
 * Since: 1.8
578
 * Since: 1.8
575
 **/
579
 **/
576
void
580
void
577
cairo_user_font_face_set_init_func (cairo_font_face_t                  *font_face,
581
cairo_user_font_face_set_init_func (cairo_font_face_t                  *font_face,
578
				    cairo_user_scaled_font_init_func_t  init_func)
582
				    cairo_user_scaled_font_init_func_t  init_func)
579
{
583
{
580
    cairo_user_font_face_t *user_font_face;
584
    cairo_user_font_face_t *user_font_face;
581
 
585
 
582
    if (font_face->status)
586
    if (font_face->status)
583
	return;
587
	return;
584
 
588
 
585
    if (! _cairo_font_face_is_user (font_face)) {
589
    if (! _cairo_font_face_is_user (font_face)) {
586
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
590
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
587
	    return;
591
	    return;
588
    }
592
    }
589
 
593
 
590
    user_font_face = (cairo_user_font_face_t *) font_face;
594
    user_font_face = (cairo_user_font_face_t *) font_face;
591
    if (user_font_face->immutable) {
595
    if (user_font_face->immutable) {
592
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
596
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
593
	    return;
597
	    return;
594
    }
598
    }
595
    user_font_face->scaled_font_methods.init = init_func;
599
    user_font_face->scaled_font_methods.init = init_func;
596
}
600
}
597
slim_hidden_def(cairo_user_font_face_set_init_func);
601
slim_hidden_def(cairo_user_font_face_set_init_func);
598
 
602
 
599
/**
603
/**
600
 * cairo_user_font_face_set_render_glyph_func:
604
 * cairo_user_font_face_set_render_glyph_func:
601
 * @font_face: A user font face
605
 * @font_face: A user font face
602
 * @render_glyph_func: The render_glyph callback, or %NULL
606
 * @render_glyph_func: The render_glyph callback, or %NULL
603
 *
607
 *
604
 * Sets the glyph rendering function of a user-font.
608
 * Sets the glyph rendering function of a user-font.
605
 * See #cairo_user_scaled_font_render_glyph_func_t for details of how the callback
609
 * See #cairo_user_scaled_font_render_glyph_func_t for details of how the callback
606
 * works.
610
 * works.
607
 *
611
 *
608
 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
612
 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
609
 * error will occur.  A user font-face is immutable as soon as a scaled-font
613
 * error will occur.  A user font-face is immutable as soon as a scaled-font
610
 * is created from it.
614
 * is created from it.
611
 *
615
 *
612
 * The render_glyph callback is the only mandatory callback of a user-font.
616
 * The render_glyph callback is the only mandatory callback of a user-font.
613
 * If the callback is %NULL and a glyph is tried to be rendered using
617
 * If the callback is %NULL and a glyph is tried to be rendered using
614
 * @font_face, a %CAIRO_STATUS_USER_FONT_ERROR will occur.
618
 * @font_face, a %CAIRO_STATUS_USER_FONT_ERROR will occur.
615
 *
619
 *
616
 * Since: 1.8
620
 * Since: 1.8
617
 **/
621
 **/
618
void
622
void
619
cairo_user_font_face_set_render_glyph_func (cairo_font_face_t                          *font_face,
623
cairo_user_font_face_set_render_glyph_func (cairo_font_face_t                          *font_face,
620
					    cairo_user_scaled_font_render_glyph_func_t  render_glyph_func)
624
					    cairo_user_scaled_font_render_glyph_func_t  render_glyph_func)
621
{
625
{
622
    cairo_user_font_face_t *user_font_face;
626
    cairo_user_font_face_t *user_font_face;
623
 
627
 
624
    if (font_face->status)
628
    if (font_face->status)
625
	return;
629
	return;
626
 
630
 
627
    if (! _cairo_font_face_is_user (font_face)) {
631
    if (! _cairo_font_face_is_user (font_face)) {
628
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
632
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
629
	    return;
633
	    return;
630
    }
634
    }
631
 
635
 
632
    user_font_face = (cairo_user_font_face_t *) font_face;
636
    user_font_face = (cairo_user_font_face_t *) font_face;
633
    if (user_font_face->immutable) {
637
    if (user_font_face->immutable) {
634
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
638
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
635
	    return;
639
	    return;
636
    }
640
    }
637
    user_font_face->scaled_font_methods.render_glyph = render_glyph_func;
641
    user_font_face->scaled_font_methods.render_glyph = render_glyph_func;
638
}
642
}
639
slim_hidden_def(cairo_user_font_face_set_render_glyph_func);
643
slim_hidden_def(cairo_user_font_face_set_render_glyph_func);
640
 
644
 
641
/**
645
/**
642
 * cairo_user_font_face_set_text_to_glyphs_func:
646
 * cairo_user_font_face_set_text_to_glyphs_func:
643
 * @font_face: A user font face
647
 * @font_face: A user font face
644
 * @text_to_glyphs_func: The text_to_glyphs callback, or %NULL
648
 * @text_to_glyphs_func: The text_to_glyphs callback, or %NULL
645
 *
649
 *
646
 * Sets th text-to-glyphs conversion function of a user-font.
650
 * Sets th text-to-glyphs conversion function of a user-font.
647
 * See #cairo_user_scaled_font_text_to_glyphs_func_t for details of how the callback
651
 * See #cairo_user_scaled_font_text_to_glyphs_func_t for details of how the callback
648
 * works.
652
 * works.
649
 *
653
 *
650
 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
654
 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
651
 * error will occur.  A user font-face is immutable as soon as a scaled-font
655
 * error will occur.  A user font-face is immutable as soon as a scaled-font
652
 * is created from it.
656
 * is created from it.
653
 *
657
 *
654
 * Since: 1.8
658
 * Since: 1.8
655
 **/
659
 **/
656
void
660
void
657
cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t                            *font_face,
661
cairo_user_font_face_set_text_to_glyphs_func (cairo_font_face_t                            *font_face,
658
					      cairo_user_scaled_font_text_to_glyphs_func_t  text_to_glyphs_func)
662
					      cairo_user_scaled_font_text_to_glyphs_func_t  text_to_glyphs_func)
659
{
663
{
660
    cairo_user_font_face_t *user_font_face;
664
    cairo_user_font_face_t *user_font_face;
661
 
665
 
662
    if (font_face->status)
666
    if (font_face->status)
663
	return;
667
	return;
664
 
668
 
665
    if (! _cairo_font_face_is_user (font_face)) {
669
    if (! _cairo_font_face_is_user (font_face)) {
666
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
670
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
667
	    return;
671
	    return;
668
    }
672
    }
669
 
673
 
670
    user_font_face = (cairo_user_font_face_t *) font_face;
674
    user_font_face = (cairo_user_font_face_t *) font_face;
671
    if (user_font_face->immutable) {
675
    if (user_font_face->immutable) {
672
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
676
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
673
	    return;
677
	    return;
674
    }
678
    }
675
    user_font_face->scaled_font_methods.text_to_glyphs = text_to_glyphs_func;
679
    user_font_face->scaled_font_methods.text_to_glyphs = text_to_glyphs_func;
676
}
680
}
677
 
681
 
678
/**
682
/**
679
 * cairo_user_font_face_set_unicode_to_glyph_func:
683
 * cairo_user_font_face_set_unicode_to_glyph_func:
680
 * @font_face: A user font face
684
 * @font_face: A user font face
681
 * @unicode_to_glyph_func: The unicode_to_glyph callback, or %NULL
685
 * @unicode_to_glyph_func: The unicode_to_glyph callback, or %NULL
682
 *
686
 *
683
 * Sets the unicode-to-glyph conversion function of a user-font.
687
 * Sets the unicode-to-glyph conversion function of a user-font.
684
 * See #cairo_user_scaled_font_unicode_to_glyph_func_t for details of how the callback
688
 * See #cairo_user_scaled_font_unicode_to_glyph_func_t for details of how the callback
685
 * works.
689
 * works.
686
 *
690
 *
687
 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
691
 * The font-face should not be immutable or a %CAIRO_STATUS_USER_FONT_IMMUTABLE
688
 * error will occur.  A user font-face is immutable as soon as a scaled-font
692
 * error will occur.  A user font-face is immutable as soon as a scaled-font
689
 * is created from it.
693
 * is created from it.
690
 *
694
 *
691
 * Since: 1.8
695
 * Since: 1.8
692
 **/
696
 **/
693
void
697
void
694
cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t                              *font_face,
698
cairo_user_font_face_set_unicode_to_glyph_func (cairo_font_face_t                              *font_face,
695
						cairo_user_scaled_font_unicode_to_glyph_func_t  unicode_to_glyph_func)
699
						cairo_user_scaled_font_unicode_to_glyph_func_t  unicode_to_glyph_func)
696
{
700
{
697
    cairo_user_font_face_t *user_font_face;
701
    cairo_user_font_face_t *user_font_face;
698
    if (font_face->status)
702
    if (font_face->status)
699
	return;
703
	return;
700
 
704
 
701
    if (! _cairo_font_face_is_user (font_face)) {
705
    if (! _cairo_font_face_is_user (font_face)) {
702
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
706
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
703
	    return;
707
	    return;
704
    }
708
    }
705
 
709
 
706
    user_font_face = (cairo_user_font_face_t *) font_face;
710
    user_font_face = (cairo_user_font_face_t *) font_face;
707
    if (user_font_face->immutable) {
711
    if (user_font_face->immutable) {
708
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
712
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_USER_FONT_IMMUTABLE))
709
	    return;
713
	    return;
710
    }
714
    }
711
    user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func;
715
    user_font_face->scaled_font_methods.unicode_to_glyph = unicode_to_glyph_func;
712
}
716
}
713
slim_hidden_def(cairo_user_font_face_set_unicode_to_glyph_func);
717
slim_hidden_def(cairo_user_font_face_set_unicode_to_glyph_func);
714
 
718
 
715
/* User-font method getters */
719
/* User-font method getters */
716
 
720
 
717
/**
721
/**
718
 * cairo_user_font_face_get_init_func:
722
 * cairo_user_font_face_get_init_func:
719
 * @font_face: A user font face
723
 * @font_face: A user font face
720
 *
724
 *
721
 * Gets the scaled-font initialization function of a user-font.
725
 * Gets the scaled-font initialization function of a user-font.
722
 *
726
 *
723
 * Return value: The init callback of @font_face
727
 * Return value: The init callback of @font_face
724
 * or %NULL if none set or an error has occurred.
728
 * or %NULL if none set or an error has occurred.
725
 *
729
 *
726
 * Since: 1.8
730
 * Since: 1.8
727
 **/
731
 **/
728
cairo_user_scaled_font_init_func_t
732
cairo_user_scaled_font_init_func_t
729
cairo_user_font_face_get_init_func (cairo_font_face_t *font_face)
733
cairo_user_font_face_get_init_func (cairo_font_face_t *font_face)
730
{
734
{
731
    cairo_user_font_face_t *user_font_face;
735
    cairo_user_font_face_t *user_font_face;
732
 
736
 
733
    if (font_face->status)
737
    if (font_face->status)
734
	return NULL;
738
	return NULL;
735
 
739
 
736
    if (! _cairo_font_face_is_user (font_face)) {
740
    if (! _cairo_font_face_is_user (font_face)) {
737
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
741
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
738
	    return NULL;
742
	    return NULL;
739
    }
743
    }
740
 
744
 
741
    user_font_face = (cairo_user_font_face_t *) font_face;
745
    user_font_face = (cairo_user_font_face_t *) font_face;
742
    return user_font_face->scaled_font_methods.init;
746
    return user_font_face->scaled_font_methods.init;
743
}
747
}
744
 
748
 
745
/**
749
/**
746
 * cairo_user_font_face_get_render_glyph_func:
750
 * cairo_user_font_face_get_render_glyph_func:
747
 * @font_face: A user font face
751
 * @font_face: A user font face
748
 *
752
 *
749
 * Gets the glyph rendering function of a user-font.
753
 * Gets the glyph rendering function of a user-font.
750
 *
754
 *
751
 * Return value: The render_glyph callback of @font_face
755
 * Return value: The render_glyph callback of @font_face
752
 * or %NULL if none set or an error has occurred.
756
 * or %NULL if none set or an error has occurred.
753
 *
757
 *
754
 * Since: 1.8
758
 * Since: 1.8
755
 **/
759
 **/
756
cairo_user_scaled_font_render_glyph_func_t
760
cairo_user_scaled_font_render_glyph_func_t
757
cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face)
761
cairo_user_font_face_get_render_glyph_func (cairo_font_face_t *font_face)
758
{
762
{
759
    cairo_user_font_face_t *user_font_face;
763
    cairo_user_font_face_t *user_font_face;
760
 
764
 
761
    if (font_face->status)
765
    if (font_face->status)
762
	return NULL;
766
	return NULL;
763
 
767
 
764
    if (! _cairo_font_face_is_user (font_face)) {
768
    if (! _cairo_font_face_is_user (font_face)) {
765
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
769
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
766
	    return NULL;
770
	    return NULL;
767
    }
771
    }
768
 
772
 
769
    user_font_face = (cairo_user_font_face_t *) font_face;
773
    user_font_face = (cairo_user_font_face_t *) font_face;
770
    return user_font_face->scaled_font_methods.render_glyph;
774
    return user_font_face->scaled_font_methods.render_glyph;
771
}
775
}
772
 
776
 
773
/**
777
/**
774
 * cairo_user_font_face_get_text_to_glyphs_func:
778
 * cairo_user_font_face_get_text_to_glyphs_func:
775
 * @font_face: A user font face
779
 * @font_face: A user font face
776
 *
780
 *
777
 * Gets the text-to-glyphs conversion function of a user-font.
781
 * Gets the text-to-glyphs conversion function of a user-font.
778
 *
782
 *
779
 * Return value: The text_to_glyphs callback of @font_face
783
 * Return value: The text_to_glyphs callback of @font_face
780
 * or %NULL if none set or an error occurred.
784
 * or %NULL if none set or an error occurred.
781
 *
785
 *
782
 * Since: 1.8
786
 * Since: 1.8
783
 **/
787
 **/
784
cairo_user_scaled_font_text_to_glyphs_func_t
788
cairo_user_scaled_font_text_to_glyphs_func_t
785
cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face)
789
cairo_user_font_face_get_text_to_glyphs_func (cairo_font_face_t *font_face)
786
{
790
{
787
    cairo_user_font_face_t *user_font_face;
791
    cairo_user_font_face_t *user_font_face;
788
 
792
 
789
    if (font_face->status)
793
    if (font_face->status)
790
	return NULL;
794
	return NULL;
791
 
795
 
792
    if (! _cairo_font_face_is_user (font_face)) {
796
    if (! _cairo_font_face_is_user (font_face)) {
793
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
797
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
794
	    return NULL;
798
	    return NULL;
795
    }
799
    }
796
 
800
 
797
    user_font_face = (cairo_user_font_face_t *) font_face;
801
    user_font_face = (cairo_user_font_face_t *) font_face;
798
    return user_font_face->scaled_font_methods.text_to_glyphs;
802
    return user_font_face->scaled_font_methods.text_to_glyphs;
799
}
803
}
800
 
804
 
801
/**
805
/**
802
 * cairo_user_font_face_get_unicode_to_glyph_func:
806
 * cairo_user_font_face_get_unicode_to_glyph_func:
803
 * @font_face: A user font face
807
 * @font_face: A user font face
804
 *
808
 *
805
 * Gets the unicode-to-glyph conversion function of a user-font.
809
 * Gets the unicode-to-glyph conversion function of a user-font.
806
 *
810
 *
807
 * Return value: The unicode_to_glyph callback of @font_face
811
 * Return value: The unicode_to_glyph callback of @font_face
808
 * or %NULL if none set or an error occurred.
812
 * or %NULL if none set or an error occurred.
809
 *
813
 *
810
 * Since: 1.8
814
 * Since: 1.8
811
 **/
815
 **/
812
cairo_user_scaled_font_unicode_to_glyph_func_t
816
cairo_user_scaled_font_unicode_to_glyph_func_t
813
cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face)
817
cairo_user_font_face_get_unicode_to_glyph_func (cairo_font_face_t *font_face)
814
{
818
{
815
    cairo_user_font_face_t *user_font_face;
819
    cairo_user_font_face_t *user_font_face;
816
 
820
 
817
    if (font_face->status)
821
    if (font_face->status)
818
	return NULL;
822
	return NULL;
819
 
823
 
820
    if (! _cairo_font_face_is_user (font_face)) {
824
    if (! _cairo_font_face_is_user (font_face)) {
821
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
825
	if (_cairo_font_face_set_error (font_face, CAIRO_STATUS_FONT_TYPE_MISMATCH))
822
	    return NULL;
826
	    return NULL;
823
    }
827
    }
824
 
828
 
825
    user_font_face = (cairo_user_font_face_t *) font_face;
829
    user_font_face = (cairo_user_font_face_t *) font_face;
826
    return user_font_face->scaled_font_methods.unicode_to_glyph;
830
    return user_font_face->scaled_font_methods.unicode_to_glyph;
827
}
831
}