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 | }>> |