text.c revision 5d64a06a6322b6e6f88233e79c6431e96eda7de6
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#include "api.h" 34 35#ifdef OPENVG_VERSION_1_1 36 37struct vg_font { 38 struct vg_object base; 39 struct cso_hash *glyphs; 40}; 41 42struct vg_glyph { 43 struct vg_object *object; /* it could be NULL */ 44 VGboolean is_hinted; 45 VGfloat glyph_origin[2]; 46 VGfloat escapement[2]; 47}; 48 49static VGboolean del_glyph(struct vg_font *font, 50 VGuint glyphIndex) 51{ 52 struct vg_glyph *glyph; 53 54 glyph = (struct vg_glyph *) 55 cso_hash_take(font->glyphs, (unsigned) glyphIndex); 56 if (glyph) 57 FREE(glyph); 58 59 return (glyph != NULL); 60} 61 62static void add_glyph(struct vg_font *font, 63 VGuint glyphIndex, 64 struct vg_object *obj, 65 VGboolean isHinted, 66 const VGfloat glyphOrigin[2], 67 const VGfloat escapement[2]) 68{ 69 struct vg_glyph *glyph; 70 71 /* remove the existing one */ 72 del_glyph(font, glyphIndex); 73 74 glyph = CALLOC_STRUCT(vg_glyph); 75 glyph->object = obj; 76 glyph->is_hinted = isHinted; 77 memcpy(glyph->glyph_origin, glyphOrigin, sizeof(glyphOrigin)); 78 memcpy(glyph->escapement, escapement, sizeof(escapement)); 79 80 cso_hash_insert(font->glyphs, (unsigned) glyphIndex, glyph); 81} 82 83static struct vg_glyph *get_glyph(struct vg_font *font, 84 VGuint glyphIndex) 85{ 86 struct cso_hash_iter iter; 87 88 iter = cso_hash_find(font->glyphs, (unsigned) glyphIndex); 89 return (struct vg_glyph *) cso_hash_iter_data(iter); 90} 91 92static void vg_render_glyph(struct vg_context *ctx, 93 struct vg_glyph *glyph, 94 VGbitfield paintModes, 95 VGboolean allowAutoHinting) 96{ 97 if (glyph->object && paintModes) { 98 struct vg_state *state = &ctx->state.vg; 99 struct matrix m; 100 101 m = state->glyph_user_to_surface_matrix; 102 matrix_translate(&m, 103 state->glyph_origin[0].f - glyph->glyph_origin[0], 104 state->glyph_origin[1].f - glyph->glyph_origin[1]); 105 106 if (glyph->object->type == VG_OBJECT_PATH) { 107 path_render((struct path *) glyph->object, paintModes, &m); 108 } 109 else { 110 assert(glyph->object->type == VG_OBJECT_IMAGE); 111 image_draw((struct vg_image *) glyph->object, &m); 112 } 113 } 114} 115 116static void vg_advance_glyph(struct vg_context *ctx, 117 struct vg_glyph *glyph, 118 VGfloat adjustment_x, 119 VGfloat adjustment_y, 120 VGboolean last) 121{ 122 struct vg_value *glyph_origin = ctx->state.vg.glyph_origin; 123 124 glyph_origin[0].f += glyph->escapement[0] + adjustment_x; 125 glyph_origin[1].f += glyph->escapement[1] + adjustment_y; 126 127 if (last) { 128 glyph_origin[0].i = float_to_int_floor(glyph_origin[0].f); 129 glyph_origin[1].i = float_to_int_floor(glyph_origin[1].f); 130 } 131} 132 133struct vg_font *font_create(VGint glyphCapacityHint) 134{ 135 struct vg_context *ctx = vg_current_context(); 136 struct vg_font *font; 137 138 font = CALLOC_STRUCT(vg_font); 139 vg_init_object(&font->base, ctx, VG_OBJECT_FONT); 140 font->glyphs = cso_hash_create(); 141 142 vg_context_add_object(ctx, VG_OBJECT_FONT, font); 143 144 return font; 145} 146 147void font_destroy(struct vg_font *font) 148{ 149 struct vg_context *ctx = vg_current_context(); 150 struct cso_hash_iter iter; 151 152 vg_context_remove_object(ctx, VG_OBJECT_FONT, font); 153 154 iter = cso_hash_first_node(font->glyphs); 155 while (!cso_hash_iter_is_null(iter)) { 156 struct vg_glyph *glyph = (struct vg_glyph *) cso_hash_iter_data(iter); 157 FREE(glyph); 158 iter = cso_hash_iter_next(iter); 159 } 160 cso_hash_delete(font->glyphs); 161 162 FREE(font); 163} 164 165void 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 176void 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 186void 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 195void 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 213void 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 245VGint font_num_glyphs(struct vg_font *font) 246{ 247 return cso_hash_size(font->glyphs); 248} 249 250#endif /* OPENVG_VERSION_1_1 */ 251