Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 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 */