summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChia-I Wu <olv@lunarg.com>2010-11-24 01:24:38 +0800
committerChia-I Wu <olv@lunarg.com>2010-12-01 11:23:52 +0800
commit5d64a06a6322b6e6f88233e79c6431e96eda7de6 (patch)
treeada420dd47351d758bc61643aae984648f46f920
parent34f466d4e6a720138c0846ab6233c32dc039fe58 (diff)
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.
-rw-r--r--src/gallium/state_trackers/vega/Makefile1
-rw-r--r--src/gallium/state_trackers/vega/api_params.c4
-rw-r--r--src/gallium/state_trackers/vega/api_text.c107
-rw-r--r--src/gallium/state_trackers/vega/text.c250
-rw-r--r--src/gallium/state_trackers/vega/text.h71
5 files changed, 353 insertions, 80 deletions
diff --git a/src/gallium/state_trackers/vega/Makefile b/src/gallium/state_trackers/vega/Makefile
index 0543fac094..deafa39aa6 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 a10b009e63..c94fd2e537 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 d8264f7c96..7c6b479409 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 0000000000..01ff602f58
--- /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 0000000000..6b3fa7323e
--- /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 */