st/vega: Add primitive text support.
authorChia-I Wu <olv@lunarg.com>
Tue, 23 Nov 2010 17:24:38 +0000 (01:24 +0800)
committerChia-I Wu <olv@lunarg.com>
Wed, 1 Dec 2010 03:23:52 +0000 (11:23 +0800)
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
src/gallium/state_trackers/vega/api_params.c
src/gallium/state_trackers/vega/api_text.c
src/gallium/state_trackers/vega/text.c [new file with mode: 0644]
src/gallium/state_trackers/vega/text.h [new file with mode: 0644]

index 0543fac09469a9f64cee27fdc72eaacf8fd29616..deafa39aa62f103b39316299456436543785bb4d 100644 (file)
@@ -38,6 +38,7 @@ C_SOURCES = \
            renderer.c \
            stroker.c \
            mask.c \
+           text.c \
            shader.c \
            shaders_cache.c
 
index a10b009e6314440728ddbdf0b6e6075ffd982db9..c94fd2e537e84e594cae037b4ff25ef5323c9d71 100644 (file)
@@ -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
index d8264f7c9699f4b41f7a52bdc7584d5f54dbd951..7c6b479409921154c0e022f5317fa6ea97c86e35 100644 (file)
 #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 (file)
index 0000000..01ff602
--- /dev/null
@@ -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 (file)
index 0000000..6b3fa73
--- /dev/null
@@ -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 */