1 /**************************************************************************
2 *
3 * Copyright 2010 LunarG, Inc. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 **************************************************************************/
26
27 #include "util/u_memory.h"
28 #include "cso_cache/cso_hash.h"
29
30 #include "text.h"
31 #include "image.h"
32 #include "path.h"
33
34 #ifdef OPENVG_VERSION_1_1
35
36 struct vg_font {
37 struct vg_object base;
38 struct cso_hash *glyphs;
39 };
40
41 struct vg_glyph {
42 struct vg_object *object; /* it could be NULL */
43 VGboolean is_hinted;
44 VGfloat glyph_origin[2];
45 VGfloat escapement[2];
46 };
47
del_glyph(struct vg_font * font,VGuint glyphIndex)48 static VGboolean del_glyph(struct vg_font *font,
49 VGuint glyphIndex)
50 {
51 struct vg_glyph *glyph;
52
53 glyph = (struct vg_glyph *)
54 cso_hash_take(font->glyphs, (unsigned) glyphIndex);
55 if (glyph)
56 FREE(glyph);
57
58 return (glyph != NULL);
59 }
60
add_glyph(struct vg_font * font,VGuint glyphIndex,struct vg_object * obj,VGboolean isHinted,const VGfloat glyphOrigin[2],const VGfloat escapement[2])61 static void add_glyph(struct vg_font *font,
62 VGuint glyphIndex,
63 struct vg_object *obj,
64 VGboolean isHinted,
65 const VGfloat glyphOrigin[2],
66 const VGfloat escapement[2])
67 {
68 struct vg_glyph *glyph;
69
70 /* remove the existing one */
71 del_glyph(font, glyphIndex);
72
73 glyph = CALLOC_STRUCT(vg_glyph);
74 glyph->object = obj;
75 glyph->is_hinted = isHinted;
76 memcpy(glyph->glyph_origin, glyphOrigin, sizeof(glyph->glyph_origin));
77 memcpy(glyph->escapement, escapement, sizeof(glyph->glyph_origin));
78
79 cso_hash_insert(font->glyphs, (unsigned) glyphIndex, glyph);
80 }
81
get_glyph(struct vg_font * font,VGuint glyphIndex)82 static struct vg_glyph *get_glyph(struct vg_font *font,
83 VGuint glyphIndex)
84 {
85 struct cso_hash_iter iter;
86
87 iter = cso_hash_find(font->glyphs, (unsigned) glyphIndex);
88 return (struct vg_glyph *) cso_hash_iter_data(iter);
89 }
90
vg_render_glyph(struct vg_context * ctx,struct vg_glyph * glyph,VGbitfield paintModes,VGboolean allowAutoHinting)91 static void vg_render_glyph(struct vg_context *ctx,
92 struct vg_glyph *glyph,
93 VGbitfield paintModes,
94 VGboolean allowAutoHinting)
95 {
96 if (glyph->object && paintModes) {
97 struct vg_state *state = &ctx->state.vg;
98 struct matrix m;
99
100 m = state->glyph_user_to_surface_matrix;
101 matrix_translate(&m,
102 state->glyph_origin[0].f - glyph->glyph_origin[0],
103 state->glyph_origin[1].f - glyph->glyph_origin[1]);
104
105 if (glyph->object->type == VG_OBJECT_PATH) {
106 path_render((struct path *) glyph->object, paintModes, &m);
107 }
108 else {
109 assert(glyph->object->type == VG_OBJECT_IMAGE);
110 image_draw((struct vg_image *) glyph->object, &m);
111 }
112 }
113 }
114
vg_advance_glyph(struct vg_context * ctx,struct vg_glyph * glyph,VGfloat adjustment_x,VGfloat adjustment_y,VGboolean last)115 static void vg_advance_glyph(struct vg_context *ctx,
116 struct vg_glyph *glyph,
117 VGfloat adjustment_x,
118 VGfloat adjustment_y,
119 VGboolean last)
120 {
121 struct vg_value *glyph_origin = ctx->state.vg.glyph_origin;
122
123 glyph_origin[0].f += glyph->escapement[0] + adjustment_x;
124 glyph_origin[1].f += glyph->escapement[1] + adjustment_y;
125
126 if (last) {
127 glyph_origin[0].i = float_to_int_floor(glyph_origin[0].f);
128 glyph_origin[1].i = float_to_int_floor(glyph_origin[1].f);
129 }
130 }
131
font_create(VGint glyphCapacityHint)132 struct vg_font *font_create(VGint glyphCapacityHint)
133 {
134 struct vg_context *ctx = vg_current_context();
135 struct vg_font *font;
136
137 font = CALLOC_STRUCT(vg_font);
138 vg_init_object(&font->base, ctx, VG_OBJECT_FONT);
139 font->glyphs = cso_hash_create();
140
141 vg_context_add_object(ctx, &font->base);
142
143 return font;
144 }
145
font_destroy(struct vg_font * font)146 void font_destroy(struct vg_font *font)
147 {
148 struct vg_context *ctx = vg_current_context();
149 struct cso_hash_iter iter;
150
151 vg_context_remove_object(ctx, &font->base);
152
153 iter = cso_hash_first_node(font->glyphs);
154 while (!cso_hash_iter_is_null(iter)) {
155 struct vg_glyph *glyph = (struct vg_glyph *) cso_hash_iter_data(iter);
156 FREE(glyph);
157 iter = cso_hash_iter_next(iter);
158 }
159 cso_hash_delete(font->glyphs);
160
161 FREE(font);
162 }
163
font_set_glyph_to_path(struct vg_font * font,VGuint glyphIndex,struct path * path,VGboolean isHinted,const VGfloat glyphOrigin[2],const VGfloat escapement[2])164 void font_set_glyph_to_path(struct vg_font *font,
165 VGuint glyphIndex,
166 struct path *path,
167 VGboolean isHinted,
168 const VGfloat glyphOrigin[2],
169 const VGfloat escapement[2])
170 {
171 add_glyph(font, glyphIndex, (struct vg_object *) path,
172 isHinted, glyphOrigin, escapement);
173 }
174
font_set_glyph_to_image(struct vg_font * font,VGuint glyphIndex,struct vg_image * image,const VGfloat glyphOrigin[2],const VGfloat escapement[2])175 void font_set_glyph_to_image(struct vg_font *font,
176 VGuint glyphIndex,
177 struct vg_image *image,
178 const VGfloat glyphOrigin[2],
179 const VGfloat escapement[2])
180 {
181 add_glyph(font, glyphIndex, (struct vg_object *) image,
182 VG_TRUE, glyphOrigin, escapement);
183 }
184
font_clear_glyph(struct vg_font * font,VGuint glyphIndex)185 void font_clear_glyph(struct vg_font *font,
186 VGuint glyphIndex)
187 {
188 if (!del_glyph(font, glyphIndex)) {
189 struct vg_context *ctx = vg_current_context();
190 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
191 }
192 }
193
font_draw_glyph(struct vg_font * font,VGuint glyphIndex,VGbitfield paintModes,VGboolean allowAutoHinting)194 void font_draw_glyph(struct vg_font *font,
195 VGuint glyphIndex,
196 VGbitfield paintModes,
197 VGboolean allowAutoHinting)
198 {
199 struct vg_context *ctx = vg_current_context();
200 struct vg_glyph *glyph;
201
202 glyph = get_glyph(font, glyphIndex);
203 if (!glyph) {
204 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
205 return;
206 }
207
208 vg_render_glyph(ctx, glyph, paintModes, allowAutoHinting);
209 vg_advance_glyph(ctx, glyph, 0.0f, 0.0f, VG_TRUE);
210 }
211
font_draw_glyphs(struct vg_font * font,VGint glyphCount,const VGuint * glyphIndices,const VGfloat * adjustments_x,const VGfloat * adjustments_y,VGbitfield paintModes,VGboolean allowAutoHinting)212 void font_draw_glyphs(struct vg_font *font,
213 VGint glyphCount,
214 const VGuint *glyphIndices,
215 const VGfloat *adjustments_x,
216 const VGfloat *adjustments_y,
217 VGbitfield paintModes,
218 VGboolean allowAutoHinting)
219 {
220 struct vg_context *ctx = vg_current_context();
221 VGint i;
222
223 for (i = 0; i < glyphCount; ++i) {
224 if (!get_glyph(font, glyphIndices[i])) {
225 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
226 return;
227 }
228 }
229
230 for (i = 0; i < glyphCount; ++i) {
231 struct vg_glyph *glyph;
232 VGfloat adj_x, adj_y;
233
234 glyph = get_glyph(font, glyphIndices[i]);
235
236 vg_render_glyph(ctx, glyph, paintModes, allowAutoHinting);
237
238 adj_x = (adjustments_x) ? adjustments_x[i] : 0.0f;
239 adj_y = (adjustments_y) ? adjustments_y[i] : 0.0f;
240 vg_advance_glyph(ctx, glyph, adj_x, adj_y, (i == glyphCount - 1));
241 }
242 }
243
font_num_glyphs(struct vg_font * font)244 VGint font_num_glyphs(struct vg_font *font)
245 {
246 return cso_hash_size(font->glyphs);
247 }
248
249 #endif /* OPENVG_VERSION_1_1 */
250