From 5d64a06a6322b6e6f88233e79c6431e96eda7de6 Mon Sep 17 00:00:00 2001 From: Chia-I Wu Date: Wed, 24 Nov 2010 01:24:38 +0800 Subject: [PATCH] st/vega: Add primitive text support. Optional features such as auth-hinting are not implemented. There is no anti-aliasing, and no effort is done to keep the glyph origin integral. So the text quality is poor. --- src/gallium/state_trackers/vega/Makefile | 1 + src/gallium/state_trackers/vega/api_params.c | 4 +- src/gallium/state_trackers/vega/api_text.c | 107 +++----- src/gallium/state_trackers/vega/text.c | 250 +++++++++++++++++++ src/gallium/state_trackers/vega/text.h | 71 ++++++ 5 files changed, 353 insertions(+), 80 deletions(-) create mode 100644 src/gallium/state_trackers/vega/text.c create mode 100644 src/gallium/state_trackers/vega/text.h diff --git a/src/gallium/state_trackers/vega/Makefile b/src/gallium/state_trackers/vega/Makefile index 0543fac0946..deafa39aa62 100644 --- a/src/gallium/state_trackers/vega/Makefile +++ b/src/gallium/state_trackers/vega/Makefile @@ -38,6 +38,7 @@ C_SOURCES = \ renderer.c \ stroker.c \ mask.c \ + text.c \ shader.c \ shaders_cache.c diff --git a/src/gallium/state_trackers/vega/api_params.c b/src/gallium/state_trackers/vega/api_params.c index a10b009e631..c94fd2e537e 100644 --- a/src/gallium/state_trackers/vega/api_params.c +++ b/src/gallium/state_trackers/vega/api_params.c @@ -30,6 +30,7 @@ #include "paint.h" #include "path.h" #include "image.h" +#include "text.h" #include "matrix.h" #include "api_consts.h" #include "api.h" @@ -1500,7 +1501,8 @@ VGint vegaGetParameteri(VGHandle object, #ifdef OPENVG_VERSION_1_1 case VG_FONT_NUM_GLYPHS: { - return 1; + struct vg_font *font = (struct vg_font*)object; + return font_num_glyphs(font); } break; #endif diff --git a/src/gallium/state_trackers/vega/api_text.c b/src/gallium/state_trackers/vega/api_text.c index d8264f7c969..7c6b4794099 100644 --- a/src/gallium/state_trackers/vega/api_text.c +++ b/src/gallium/state_trackers/vega/api_text.c @@ -27,22 +27,15 @@ #include "VG/openvg.h" #include "vg_context.h" +#include "text.h" #include "api.h" #include "util/u_memory.h" #ifdef OPENVG_VERSION_1_1 -struct vg_font { - struct vg_object base; - - VGint glyph_indices[200]; - VGint num_glyphs; -}; - VGFont vegaCreateFont(VGint glyphCapacityHint) { - struct vg_font *font = 0; struct vg_context *ctx = vg_current_context(); if (glyphCapacityHint < 0) { @@ -50,10 +43,7 @@ VGFont vegaCreateFont(VGint glyphCapacityHint) return VG_INVALID_HANDLE; } - font = CALLOC_STRUCT(vg_font); - vg_init_object(&font->base, ctx, VG_OBJECT_FONT); - vg_context_add_object(ctx, VG_OBJECT_FONT, font); - return (VGFont)font; + return (VGFont) font_create(glyphCapacityHint); } void vegaDestroyFont(VGFont f) @@ -65,9 +55,12 @@ void vegaDestroyFont(VGFont f) vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } + if (!vg_object_is_valid((void *) font, VG_OBJECT_FONT)) { + vg_set_error(ctx, VG_BAD_HANDLE_ERROR); + return; + } - vg_context_remove_object(ctx, VG_OBJECT_FONT, font); - /*free(font);*/ + font_destroy(font); } void vegaSetGlyphToPath(VGFont font, @@ -78,7 +71,7 @@ void vegaSetGlyphToPath(VGFont font, const VGfloat escapement[2]) { struct vg_context *ctx = vg_current_context(); - struct vg_object *pathObj; + struct path *pathObj; struct vg_font *f; if (font == VG_INVALID_HANDLE || @@ -96,15 +89,12 @@ void vegaSetGlyphToPath(VGFont font, vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - pathObj = (struct vg_object*)path; - if (pathObj && pathObj->type != VG_OBJECT_PATH) { - vg_set_error(ctx, VG_BAD_HANDLE_ERROR); - return; - } - f = (struct vg_font*)font; - f->glyph_indices[f->num_glyphs] = glyphIndex; - ++f->num_glyphs; + pathObj = (struct path*) path; + f = (struct vg_font*) font; + + font_set_glyph_to_path(f, glyphIndex, pathObj, + isHinted, glyphOrigin, escapement); } void vegaSetGlyphToImage(VGFont font, @@ -114,7 +104,7 @@ void vegaSetGlyphToImage(VGFont font, const VGfloat escapement[2]) { struct vg_context *ctx = vg_current_context(); - struct vg_object *img_obj; + struct vg_image *img_obj; struct vg_font *f; if (font == VG_INVALID_HANDLE || @@ -132,26 +122,11 @@ void vegaSetGlyphToImage(VGFont font, vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - img_obj = (struct vg_object*)image; - if (img_obj && img_obj->type != VG_OBJECT_IMAGE) { - vg_set_error(ctx, VG_BAD_HANDLE_ERROR); - return; - } + + img_obj = (struct vg_image*)image; f = (struct vg_font*)font; - f->glyph_indices[f->num_glyphs] = glyphIndex; - ++f->num_glyphs; -} -static INLINE VGboolean font_contains_glyph(struct vg_font *font, - VGuint glyph_index) -{ - VGint i; - for (i = 0; i < font->num_glyphs; ++i) { - if (font->glyph_indices[i] == glyph_index) { - return VG_TRUE; - } - } - return VG_FALSE; + font_set_glyph_to_image(f, glyphIndex, img_obj, glyphOrigin, escapement); } void vegaClearGlyph(VGFont font, @@ -159,30 +134,15 @@ void vegaClearGlyph(VGFont font, { struct vg_context *ctx = vg_current_context(); struct vg_font *f; - VGint i; if (font == VG_INVALID_HANDLE) { vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - if (glyphIndex <= 0) { - vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); - return; - } - f = (struct vg_font*)font; - if (!font_contains_glyph(f, glyphIndex)) { - vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); - return; - } - for (i = 0; i < f->num_glyphs; ++i) { - if (f->glyph_indices[i] == glyphIndex) { - /*FIXME*/ - f->glyph_indices[f->num_glyphs] = 0; - --f->num_glyphs; - return; - } - } + f = (struct vg_font*) font; + + font_clear_glyph(f, glyphIndex); } void vegaDrawGlyph(VGFont font, @@ -197,19 +157,13 @@ void vegaDrawGlyph(VGFont font, vg_set_error(ctx, VG_BAD_HANDLE_ERROR); return; } - if (glyphIndex <= 0) { - vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); - return; - } if (paintModes & (~(VG_STROKE_PATH|VG_FILL_PATH))) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } f = (struct vg_font*)font; - if (!font_contains_glyph(f, glyphIndex)) { - vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); - return; - } + + font_draw_glyph(f, glyphIndex, paintModes, allowAutoHinting); } void vegaDrawGlyphs(VGFont font, @@ -221,7 +175,6 @@ void vegaDrawGlyphs(VGFont font, VGboolean allowAutoHinting) { struct vg_context *ctx = vg_current_context(); - VGint i; struct vg_font *f; if (font == VG_INVALID_HANDLE) { @@ -236,8 +189,8 @@ void vegaDrawGlyphs(VGFont font, vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } - if (!adjustments_x || !is_aligned(adjustments_x) || - !adjustments_y || !is_aligned(adjustments_y)) { + if ((adjustments_x && !is_aligned(adjustments_x)) || + (adjustments_y && !is_aligned(adjustments_y))) { vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); return; } @@ -247,13 +200,9 @@ void vegaDrawGlyphs(VGFont font, } f = (struct vg_font*)font; - for (i = 0; i < glyphCount; ++i) { - VGuint glyph_index = glyphIndices[i]; - if (!font_contains_glyph(f, glyph_index)) { - vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); - return; - } - } + + font_draw_glyphs(f, glyphCount, glyphIndices, + adjustments_x, adjustments_y, paintModes, allowAutoHinting); } -#endif +#endif /* OPENVG_VERSION_1_1 */ diff --git a/src/gallium/state_trackers/vega/text.c b/src/gallium/state_trackers/vega/text.c new file mode 100644 index 00000000000..01ff602f58a --- /dev/null +++ b/src/gallium/state_trackers/vega/text.c @@ -0,0 +1,250 @@ +/************************************************************************** + * + * Copyright 2010 LunarG, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "util/u_memory.h" +#include "cso_cache/cso_hash.h" + +#include "text.h" +#include "image.h" +#include "path.h" +#include "api.h" + +#ifdef OPENVG_VERSION_1_1 + +struct vg_font { + struct vg_object base; + struct cso_hash *glyphs; +}; + +struct vg_glyph { + struct vg_object *object; /* it could be NULL */ + VGboolean is_hinted; + VGfloat glyph_origin[2]; + VGfloat escapement[2]; +}; + +static VGboolean del_glyph(struct vg_font *font, + VGuint glyphIndex) +{ + struct vg_glyph *glyph; + + glyph = (struct vg_glyph *) + cso_hash_take(font->glyphs, (unsigned) glyphIndex); + if (glyph) + FREE(glyph); + + return (glyph != NULL); +} + +static void add_glyph(struct vg_font *font, + VGuint glyphIndex, + struct vg_object *obj, + VGboolean isHinted, + const VGfloat glyphOrigin[2], + const VGfloat escapement[2]) +{ + struct vg_glyph *glyph; + + /* remove the existing one */ + del_glyph(font, glyphIndex); + + glyph = CALLOC_STRUCT(vg_glyph); + glyph->object = obj; + glyph->is_hinted = isHinted; + memcpy(glyph->glyph_origin, glyphOrigin, sizeof(glyphOrigin)); + memcpy(glyph->escapement, escapement, sizeof(escapement)); + + cso_hash_insert(font->glyphs, (unsigned) glyphIndex, glyph); +} + +static struct vg_glyph *get_glyph(struct vg_font *font, + VGuint glyphIndex) +{ + struct cso_hash_iter iter; + + iter = cso_hash_find(font->glyphs, (unsigned) glyphIndex); + return (struct vg_glyph *) cso_hash_iter_data(iter); +} + +static void vg_render_glyph(struct vg_context *ctx, + struct vg_glyph *glyph, + VGbitfield paintModes, + VGboolean allowAutoHinting) +{ + if (glyph->object && paintModes) { + struct vg_state *state = &ctx->state.vg; + struct matrix m; + + m = state->glyph_user_to_surface_matrix; + matrix_translate(&m, + state->glyph_origin[0].f - glyph->glyph_origin[0], + state->glyph_origin[1].f - glyph->glyph_origin[1]); + + if (glyph->object->type == VG_OBJECT_PATH) { + path_render((struct path *) glyph->object, paintModes, &m); + } + else { + assert(glyph->object->type == VG_OBJECT_IMAGE); + image_draw((struct vg_image *) glyph->object, &m); + } + } +} + +static void vg_advance_glyph(struct vg_context *ctx, + struct vg_glyph *glyph, + VGfloat adjustment_x, + VGfloat adjustment_y, + VGboolean last) +{ + struct vg_value *glyph_origin = ctx->state.vg.glyph_origin; + + glyph_origin[0].f += glyph->escapement[0] + adjustment_x; + glyph_origin[1].f += glyph->escapement[1] + adjustment_y; + + if (last) { + glyph_origin[0].i = float_to_int_floor(glyph_origin[0].f); + glyph_origin[1].i = float_to_int_floor(glyph_origin[1].f); + } +} + +struct vg_font *font_create(VGint glyphCapacityHint) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_font *font; + + font = CALLOC_STRUCT(vg_font); + vg_init_object(&font->base, ctx, VG_OBJECT_FONT); + font->glyphs = cso_hash_create(); + + vg_context_add_object(ctx, VG_OBJECT_FONT, font); + + return font; +} + +void font_destroy(struct vg_font *font) +{ + struct vg_context *ctx = vg_current_context(); + struct cso_hash_iter iter; + + vg_context_remove_object(ctx, VG_OBJECT_FONT, font); + + iter = cso_hash_first_node(font->glyphs); + while (!cso_hash_iter_is_null(iter)) { + struct vg_glyph *glyph = (struct vg_glyph *) cso_hash_iter_data(iter); + FREE(glyph); + iter = cso_hash_iter_next(iter); + } + cso_hash_delete(font->glyphs); + + FREE(font); +} + +void font_set_glyph_to_path(struct vg_font *font, + VGuint glyphIndex, + struct path *path, + VGboolean isHinted, + const VGfloat glyphOrigin[2], + const VGfloat escapement[2]) +{ + add_glyph(font, glyphIndex, (struct vg_object *) path, + isHinted, glyphOrigin, escapement); +} + +void font_set_glyph_to_image(struct vg_font *font, + VGuint glyphIndex, + struct vg_image *image, + const VGfloat glyphOrigin[2], + const VGfloat escapement[2]) +{ + add_glyph(font, glyphIndex, (struct vg_object *) image, + VG_TRUE, glyphOrigin, escapement); +} + +void font_clear_glyph(struct vg_font *font, + VGuint glyphIndex) +{ + if (!del_glyph(font, glyphIndex)) { + struct vg_context *ctx = vg_current_context(); + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + } +} + +void font_draw_glyph(struct vg_font *font, + VGuint glyphIndex, + VGbitfield paintModes, + VGboolean allowAutoHinting) +{ + struct vg_context *ctx = vg_current_context(); + struct vg_glyph *glyph; + + glyph = get_glyph(font, glyphIndex); + if (!glyph) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + + vg_render_glyph(ctx, glyph, paintModes, allowAutoHinting); + vg_advance_glyph(ctx, glyph, 0.0f, 0.0f, VG_TRUE); +} + +void font_draw_glyphs(struct vg_font *font, + VGint glyphCount, + const VGuint *glyphIndices, + const VGfloat *adjustments_x, + const VGfloat *adjustments_y, + VGbitfield paintModes, + VGboolean allowAutoHinting) +{ + struct vg_context *ctx = vg_current_context(); + VGint i; + + for (i = 0; i < glyphCount; ++i) { + if (!get_glyph(font, glyphIndices[i])) { + vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); + return; + } + } + + for (i = 0; i < glyphCount; ++i) { + struct vg_glyph *glyph; + VGfloat adj_x, adj_y; + + glyph = get_glyph(font, glyphIndices[i]); + + vg_render_glyph(ctx, glyph, paintModes, allowAutoHinting); + + adj_x = (adjustments_x) ? adjustments_x[i] : 0.0f; + adj_y = (adjustments_y) ? adjustments_y[i] : 0.0f; + vg_advance_glyph(ctx, glyph, adj_x, adj_y, (i == glyphCount - 1)); + } +} + +VGint font_num_glyphs(struct vg_font *font) +{ + return cso_hash_size(font->glyphs); +} + +#endif /* OPENVG_VERSION_1_1 */ diff --git a/src/gallium/state_trackers/vega/text.h b/src/gallium/state_trackers/vega/text.h new file mode 100644 index 00000000000..6b3fa7323e9 --- /dev/null +++ b/src/gallium/state_trackers/vega/text.h @@ -0,0 +1,71 @@ +/************************************************************************** + * + * Copyright 2010 LunarG, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef _TEXT_H +#define _TEXT_H + +#include "vg_context.h" +#include "cso_cache/cso_hash.h" + +struct vg_font; +struct vg_image; +struct path; + +struct vg_font *font_create(VGint glyphCapacityHint); +void font_destroy(struct vg_font *font); + +void font_set_glyph_to_path(struct vg_font *font, + VGuint glyphIndex, + struct path *path, + VGboolean isHinted, + const VGfloat glyphOrigin[2], + const VGfloat escapement[2]); + +void font_set_glyph_to_image(struct vg_font *font, + VGuint glyphIndex, + struct vg_image *image, + const VGfloat glyphOrigin[2], + const VGfloat escapement[2]); + +void font_clear_glyph(struct vg_font *font, + VGuint glyphIndex); + +void font_draw_glyph(struct vg_font *font, + VGuint glyphIndex, + VGbitfield paintModes, + VGboolean allowAutoHinting); + +void font_draw_glyphs(struct vg_font *font, + VGint glyphCount, + const VGuint *glyphIndices, + const VGfloat *adjustments_x, + const VGfloat *adjustments_y, + VGbitfield paintModes, + VGboolean allowAutoHinting); + +VGint font_num_glyphs(struct vg_font *font); + +#endif /* _TEXT_H */ -- 2.30.2