st/egl: Remove.
[mesa.git] / src / gallium / state_trackers / vega / text.c
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
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 FREE(glyph);
56
57 return (glyph != NULL);
58 }
59
60 static void add_glyph(struct vg_font *font,
61 VGuint glyphIndex,
62 struct vg_object *obj,
63 VGboolean isHinted,
64 const VGfloat glyphOrigin[2],
65 const VGfloat escapement[2])
66 {
67 struct vg_glyph *glyph;
68
69 /* remove the existing one */
70 del_glyph(font, glyphIndex);
71
72 glyph = CALLOC_STRUCT(vg_glyph);
73 glyph->object = obj;
74 glyph->is_hinted = isHinted;
75 memcpy(glyph->glyph_origin, glyphOrigin, sizeof(glyph->glyph_origin));
76 memcpy(glyph->escapement, escapement, sizeof(glyph->glyph_origin));
77
78 cso_hash_insert(font->glyphs, (unsigned) glyphIndex, glyph);
79 }
80
81 static struct vg_glyph *get_glyph(struct vg_font *font,
82 VGuint glyphIndex)
83 {
84 struct cso_hash_iter iter;
85
86 iter = cso_hash_find(font->glyphs, (unsigned) glyphIndex);
87 return (struct vg_glyph *) cso_hash_iter_data(iter);
88 }
89
90 static void vg_render_glyph(struct vg_context *ctx,
91 struct vg_glyph *glyph,
92 VGbitfield paintModes,
93 VGboolean allowAutoHinting)
94 {
95 if (glyph->object && paintModes) {
96 struct vg_state *state = &ctx->state.vg;
97 struct matrix m;
98
99 m = state->glyph_user_to_surface_matrix;
100 matrix_translate(&m,
101 state->glyph_origin[0].f - glyph->glyph_origin[0],
102 state->glyph_origin[1].f - glyph->glyph_origin[1]);
103
104 if (glyph->object->type == VG_OBJECT_PATH) {
105 path_render((struct path *) glyph->object, paintModes, &m);
106 }
107 else {
108 assert(glyph->object->type == VG_OBJECT_IMAGE);
109 image_draw((struct vg_image *) glyph->object, &m);
110 }
111 }
112 }
113
114 static void vg_advance_glyph(struct vg_context *ctx,
115 struct vg_glyph *glyph,
116 VGfloat adjustment_x,
117 VGfloat adjustment_y,
118 VGboolean last)
119 {
120 struct vg_value *glyph_origin = ctx->state.vg.glyph_origin;
121
122 glyph_origin[0].f += glyph->escapement[0] + adjustment_x;
123 glyph_origin[1].f += glyph->escapement[1] + adjustment_y;
124
125 if (last) {
126 glyph_origin[0].i = float_to_int_floor(glyph_origin[0].f);
127 glyph_origin[1].i = float_to_int_floor(glyph_origin[1].f);
128 }
129 }
130
131 struct vg_font *font_create(VGint glyphCapacityHint)
132 {
133 struct vg_context *ctx = vg_current_context();
134 struct vg_font *font;
135
136 font = CALLOC_STRUCT(vg_font);
137 vg_init_object(&font->base, ctx, VG_OBJECT_FONT);
138 font->glyphs = cso_hash_create();
139
140 vg_context_add_object(ctx, &font->base);
141
142 return font;
143 }
144
145 void font_destroy(struct vg_font *font)
146 {
147 struct vg_context *ctx = vg_current_context();
148 struct cso_hash_iter iter;
149
150 vg_context_remove_object(ctx, &font->base);
151
152 iter = cso_hash_first_node(font->glyphs);
153 while (!cso_hash_iter_is_null(iter)) {
154 struct vg_glyph *glyph = (struct vg_glyph *) cso_hash_iter_data(iter);
155 FREE(glyph);
156 iter = cso_hash_iter_next(iter);
157 }
158 cso_hash_delete(font->glyphs);
159
160 vg_free_object(&font->base);
161
162 FREE(font);
163 }
164
165 void font_set_glyph_to_path(struct vg_font *font,
166 VGuint glyphIndex,
167 struct path *path,
168 VGboolean isHinted,
169 const VGfloat glyphOrigin[2],
170 const VGfloat escapement[2])
171 {
172 add_glyph(font, glyphIndex, (struct vg_object *) path,
173 isHinted, glyphOrigin, escapement);
174 }
175
176 void font_set_glyph_to_image(struct vg_font *font,
177 VGuint glyphIndex,
178 struct vg_image *image,
179 const VGfloat glyphOrigin[2],
180 const VGfloat escapement[2])
181 {
182 add_glyph(font, glyphIndex, (struct vg_object *) image,
183 VG_TRUE, glyphOrigin, escapement);
184 }
185
186 void font_clear_glyph(struct vg_font *font,
187 VGuint glyphIndex)
188 {
189 if (!del_glyph(font, glyphIndex)) {
190 struct vg_context *ctx = vg_current_context();
191 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
192 }
193 }
194
195 void font_draw_glyph(struct vg_font *font,
196 VGuint glyphIndex,
197 VGbitfield paintModes,
198 VGboolean allowAutoHinting)
199 {
200 struct vg_context *ctx = vg_current_context();
201 struct vg_glyph *glyph;
202
203 glyph = get_glyph(font, glyphIndex);
204 if (!glyph) {
205 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
206 return;
207 }
208
209 vg_render_glyph(ctx, glyph, paintModes, allowAutoHinting);
210 vg_advance_glyph(ctx, glyph, 0.0f, 0.0f, VG_TRUE);
211 }
212
213 void font_draw_glyphs(struct vg_font *font,
214 VGint glyphCount,
215 const VGuint *glyphIndices,
216 const VGfloat *adjustments_x,
217 const VGfloat *adjustments_y,
218 VGbitfield paintModes,
219 VGboolean allowAutoHinting)
220 {
221 struct vg_context *ctx = vg_current_context();
222 VGint i;
223
224 for (i = 0; i < glyphCount; ++i) {
225 if (!get_glyph(font, glyphIndices[i])) {
226 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
227 return;
228 }
229 }
230
231 for (i = 0; i < glyphCount; ++i) {
232 struct vg_glyph *glyph;
233 VGfloat adj_x, adj_y;
234
235 glyph = get_glyph(font, glyphIndices[i]);
236
237 vg_render_glyph(ctx, glyph, paintModes, allowAutoHinting);
238
239 adj_x = (adjustments_x) ? adjustments_x[i] : 0.0f;
240 adj_y = (adjustments_y) ? adjustments_y[i] : 0.0f;
241 vg_advance_glyph(ctx, glyph, adj_x, adj_y, (i == glyphCount - 1));
242 }
243 }
244
245 VGint font_num_glyphs(struct vg_font *font)
246 {
247 return cso_hash_size(font->glyphs);
248 }
249
250 #endif /* OPENVG_VERSION_1_1 */