diff options
Diffstat (limited to 'tests/font/main.c')
-rw-r--r-- | tests/font/main.c | 663 |
1 files changed, 663 insertions, 0 deletions
diff --git a/tests/font/main.c b/tests/font/main.c new file mode 100644 index 0000000..d65cc09 --- /dev/null +++ b/tests/font/main.c @@ -0,0 +1,663 @@ +/*------------------------------------------------------------------------ + * + * OpenVG 1.0.1 Reference Implementation sample code + * ------------------------------------------------- + * + * Copyright (c) 2007 The Khronos Group Inc. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and /or associated documentation files + * (the "Materials "), to deal in the Materials without restriction, + * including without limitation the rights to use, copy, modify, merge, + * publish, distribute, sublicense, and/or sell copies of the Materials, + * and to permit persons to whom the Materials are furnished to do so, + * subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Materials. + * + * THE MATERIALS ARE 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 NONINFRINGEMENT. + * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS 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 MATERIALS OR + * THE USE OR OTHER DEALINGS IN THE MATERIALS. + * + *//** + * \file + * \brief Tiger sample application. Resizing the application window + * rerenders the tiger in the new resolution. Pressing 1,2,3 + * or 4 sets pixel zoom factor, mouse moves inside the zoomed + * image (mouse move works on OpenGL >= 1.2). + * \note + *//*-------------------------------------------------------------------*/ + +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <assert.h> +#include <string.h> +#define UNREF(X) ((void)(X)) + +#include <VG/openvg.h> +#include <VG/vgext.h> +#include <VG/vgu.h> +#include <EGL/egl.h> +#include <GLES2/gl2.h> + +#include "DejaVuSans.inc" // font data +#include "DejaVuSerif.inc" +#include "DejaVuSansMono.inc" +#include "fontinfo.h" // font data structure +#include "eglstate.h" + +#include "esUtil.h" + + +#define DEBUG +#ifdef DEBUG +#define DBG(M, ...) printf("[FONT][%s]:" M "\n", __func__, ##__VA_ARGS__) +#else +#define DBG(M, ...) +#endif + +#define GL_CHECK(x) \ + x; \ + { \ + GLenum glError = glGetError(); \ + if(glError != GL_NO_ERROR) { \ + DBG("glGetError() = %i (0x%.8x) at %s:%i\n", glError, glError, __FILE__, __LINE__); \ + exit(1); \ + } \ + } + +/*--------------------------------------------------------------*/ +#define WINDOW_W 1024 +#define WINDOW_H 768 + +unsigned char tgTextureBuffer [1024 * 768 * 4]; + +static STATE_T _state, *state = &_state; // global graphics state +static const int MAXFONTPATH = 256; + +Fontinfo SansTypeface, SerifTypeface, MonoTypeface; + +//EGLDisplay egldisplay; +//EGLConfig eglconfig; +//EGLSurface eglsurface; +//EGLContext eglcontext; + + + VGFont font; + VGPath fontpath1; + VGImage fontimg1; + +/*--------------------------------------------------------------*/ + +void init(NativeWindowType window) +{ + static const EGLint s_configAttribs[] = + { + EGL_SAMPLES, 4, + EGL_RED_SIZE, 8, + EGL_GREEN_SIZE, 8, + EGL_BLUE_SIZE, 8, + EGL_ALPHA_SIZE, 0, + EGL_BUFFER_SIZE, 32, + //EGL_LUMINANCE_SIZE, EGL_DONT_CARE, //EGL_DONT_CARE + EGL_STENCIL_SIZE, 0, + EGL_RENDERABLE_TYPE, EGL_OPENVG_BIT,//EGL_OPENGL_ES2_BIT, + EGL_SURFACE_TYPE, EGL_WINDOW_BIT, + EGL_DEPTH_SIZE, 0, + EGL_NONE + }; + + EGLint numconfigs; + + static const EGLint contextAttributes[] = + { +// EGL_CONTEXT_CLIENT_VERSION, 2, /* This field will be completed according to application request. */ + EGL_NONE + }; + + static const EGLint windowAttributes[] = + { + //EGL_RENDER_BUFFER, EGL_SINGLE_BUFFER, + EGL_NONE + /* + * Uncomment and remove EGL_NONE above to specify EGL_RENDER_BUFFER value to eglCreateWindowSurface. + * EGL_RENDER_BUFFER, EGL_BACK_BUFFER, + * EGL_NONE + */ + }; + + + state->display = eglGetDisplay(EGL_DEFAULT_DISPLAY); + eglInitialize(state->display, NULL, NULL); + assert(eglGetError() == EGL_SUCCESS); +// eglBindAPI(EGL_OPENVG_API); + eglBindAPI(EGL_OPENGL_ES_API); + eglChooseConfig(state->display, s_configAttribs, &state->config, 1, &numconfigs); + assert(eglGetError() == EGL_SUCCESS); + assert(numconfigs == 1); + + state->surface = eglCreateWindowSurface(state->display, state->config, window, windowAttributes); + assert(eglGetError() == EGL_SUCCESS); + state->context = eglCreateContext(state->display, state->config, EGL_NO_CONTEXT, contextAttributes); + assert(eglGetError() == EGL_SUCCESS); + eglMakeCurrent(state->display, state->surface, state->surface, state->context); + assert(eglGetError() == EGL_SUCCESS); + +} + +/*--------------------------------------------------------------*/ + +void deinit(void) +{ + eglMakeCurrent(state->display, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + assert(eglGetError() == EGL_SUCCESS); + eglTerminate(state->display); + assert(eglGetError() == EGL_SUCCESS); + eglReleaseThread(); +} + +/*--------------------------------------------------------------*/ + +typedef struct +{ + // Handle to a program object + GLuint programObject; + + // Attribute locations + GLint positionLoc; + GLint texCoordLoc; + + // Sampler location + GLint samplerLoc; + + // Texture handle + GLuint textureId; + + float time; +} UserData; + + +// newpath creates path data +VGPath newpath() +{ + return vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0.0f, 0.0f, VG_PATH_CAPABILITY_ALL); +} + +// Rect makes a rectangle at the specified location and dimensions +void Rect(VGfloat x, VGfloat y, VGfloat w, VGfloat h) +{ + + VGPath path = newpath(); + vguRect(path, x, y, w, h); + vgDrawPath(path, VG_FILL_PATH); + vgDrawPath(path, VG_STROKE_PATH); + vgDestroyPath(path); +} + +// setfill sets the fill color +void setfill(VGfloat color[4]) { + VGPaint fillPaint = vgCreatePaint(); + vgSetParameteri(fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + vgSetParameterfv(fillPaint, VG_PAINT_COLOR, 4, color); + vgSetPaint(fillPaint, VG_FILL_PATH); + vgDestroyPaint(fillPaint); +} + +// setstroke sets the stroke color +void setstroke(VGfloat color[4]) { + VGPaint strokePaint = vgCreatePaint(); + vgSetParameteri(strokePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + vgSetParameterfv(strokePaint, VG_PAINT_COLOR, 4, color); + vgSetPaint(strokePaint, VG_STROKE_PATH); + vgDestroyPaint(strokePaint); +} + +// StrokeWidth sets the stroke width +void StrokeWidth(VGfloat width) { + vgSetf(VG_STROKE_LINE_WIDTH, width); + vgSeti(VG_STROKE_CAP_STYLE, VG_CAP_BUTT); + vgSeti(VG_STROKE_JOIN_STYLE, VG_JOIN_MITER); +} + +// RGBA fills a color vectors from a RGBA quad. +void RGBA(unsigned int r, unsigned int g, unsigned int b, VGfloat a, VGfloat color[4]) { + if (r > 255) { + r = 0; + } + if (g > 255) { + g = 0; + } + if (b > 255) { + b = 0; + } + if (a < 0.0 || a > 1.0) { + a = 1.0; + } + color[0] = (VGfloat) r / 255.0f; + color[1] = (VGfloat) g / 255.0f; + color[2] = (VGfloat) b / 255.0f; + color[3] = a; +} + +// RGB returns a solid color from a RGB triple +void RGB(unsigned int r, unsigned int g, unsigned int b, VGfloat color[4]) { + RGBA(r, g, b, 1.0f, color); +} + +// Fill sets the fillcolor, defined as a RGBA quad. +void Fill(unsigned int r, unsigned int g, unsigned int b, VGfloat a) { + VGfloat color[4]; + RGBA(r, g, b, a, color); + setfill(color); +} + +// Ellipse makes an ellipse at the specified location and dimensions +void Ellipse(VGfloat x, VGfloat y, VGfloat w, VGfloat h) { + VGPath path = newpath(); + vguEllipse(path, x, y, w, h); + vgDrawPath(path, VG_FILL_PATH | VG_STROKE_PATH); + vgDestroyPath(path); +} + +// Circle makes a circle at the specified location and dimensions +void Circle(VGfloat x, VGfloat y, VGfloat r) { + Ellipse(x, y, r, r); +} + + +// Text renders a string of text at a specified location, size, using the specified font glyphs +// derived from http://web.archive.org/web/20070808195131/http://developer.hybrid.fi/font2openvg/renderFont.cpp.txt +void Text(VGfloat x, VGfloat y, char *s, Fontinfo f, int pointsize) { + VGfloat size = (VGfloat) pointsize, xx = x, mm[9]; + int i; + + vgGetMatrix(mm); + for (i = 0; i < (int)strlen(s); i++) { + unsigned int character = (unsigned int)s[i]; + int glyph = f.CharacterMap[character]; + if (glyph == -1) { + continue; //glyph is undefined + } + VGfloat mat[9] = { + size, 0.0f, 0.0f, + 0.0f, size, 0.0f, + xx, y, 1.0f + }; + vgLoadMatrix(mm); + vgMultMatrix(mat); + vgDrawPath(f.Glyphs[glyph], VG_FILL_PATH); + xx += size * f.GlyphAdvances[glyph] / 65536.0f; + } + vgLoadMatrix(mm); +} + +// TextWidth returns the width of a text string at the specified font and size. +VGfloat TextWidth(char *s, Fontinfo f, int pointsize) { + int i; + VGfloat tw = 0.0; + VGfloat size = (VGfloat) pointsize; + for (i = 0; i < (int)strlen(s); i++) { + unsigned int character = (unsigned int)s[i]; + int glyph = f.CharacterMap[character]; + if (glyph == -1) { + continue; //glyph is undefined + } + tw += size * f.GlyphAdvances[glyph] / 65536.0f; + } + return tw; +} + +// TextMid draws text, centered on (x,y) +void TextMid(VGfloat x, VGfloat y, char *s, Fontinfo f, int pointsize) { + VGfloat tw = TextWidth(s, f, pointsize); + Text(x - (tw / 2.0), y, s, f, pointsize); +} + +// TextEnd draws text, with its end aligned to (x,y) +void TextEnd(VGfloat x, VGfloat y, char *s, Fontinfo f, int pointsize) { + VGfloat tw = TextWidth(s, f, pointsize); + Text(x - tw, y, s, f, pointsize); +} + +// Start begins the picture, clearing a rectangular region with a specified color +void Start(int width, int height) { + VGfloat color[4] = { 255, 255, 255, 1 }; + vgSetfv(VG_CLEAR_COLOR, 4, color); + vgClear(0, 0, width, height); + color[0] = 0, color[1] = 0, color[2] = 0; + setfill(color); + setstroke(color); + StrokeWidth(0); + vgLoadIdentity(); +} + +// End checks for errors, and renders to the display +void End() { + assert(vgGetError() == VG_NO_ERROR); + eglSwapBuffers(state->display, state->surface); + assert(eglGetError() == EGL_SUCCESS); +} + +// clear the screen to a solid background color +void Background(ESContext *esContext, unsigned int r, unsigned int g, unsigned int b) +{ + Fill(r, g, b, 1); + +// DBG("state->screen_width = %d", state->screen_width); +// DBG("state->screen_height = %d", state->screen_height); + + Rect(0, 0, esContext->width, esContext->height); +} + +// clear the screen to a background color with alpha +void BackgroundRGB(ESContext * esContext, unsigned int r, unsigned int g, unsigned int b, VGfloat a) { + Fill(r, g, b, a); + Rect(0, 0, esContext->width, esContext->height); +} + + +/*--------------------------------------------------------------*/ +// +// Font functions +// +/*--------------------------------------------------------------*/ +// loadfont loads font path data +// derived from http://web.archive.org/web/20070808195131/http://developer.hybrid.fi/font2openvg/renderFont.cpp.txt +Fontinfo loadfont(const int *Points, + const int *PointIndices, + const unsigned char *Instructions, + const int *InstructionIndices, const int *InstructionCounts, const int *adv, const short *cmap, int ng) { + + Fontinfo f; + int i; + + memset(f.Glyphs, 0, MAXFONTPATH * sizeof(VGPath)); + if (ng > MAXFONTPATH) { + return f; + } + for (i = 0; i < ng; i++) { + const int *p = &Points[PointIndices[i] * 2]; + const unsigned char *instructions = &Instructions[InstructionIndices[i]]; + int ic = InstructionCounts[i]; + VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_S_32, +// VGPath path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, + 1.0f / 65536.0f, 0.0f, 0, 0, + VG_PATH_CAPABILITY_ALL); + f.Glyphs[i] = path; + if (ic) { + vgAppendPathData(path, ic, instructions, p); + } + } + f.CharacterMap = cmap; + f.GlyphAdvances = adv; + f.Count = ng; + return f; +} + +// unloadfont frees font path data +void unloadfont(VGPath * glyphs, int n) { + int i; + for (i = 0; i < n; i++) { + vgDestroyPath(glyphs[i]); + } +} + +void initFont() +{ + + SansTypeface = loadfont(DejaVuSans_glyphPoints, + DejaVuSans_glyphPointIndices, + DejaVuSans_glyphInstructions, + DejaVuSans_glyphInstructionIndices, + DejaVuSans_glyphInstructionCounts, + DejaVuSans_glyphAdvances, DejaVuSans_characterMap, DejaVuSans_glyphCount); + + SerifTypeface = loadfont(DejaVuSerif_glyphPoints, + DejaVuSerif_glyphPointIndices, + DejaVuSerif_glyphInstructions, + DejaVuSerif_glyphInstructionIndices, + DejaVuSerif_glyphInstructionCounts, + DejaVuSerif_glyphAdvances, DejaVuSerif_characterMap, DejaVuSerif_glyphCount); + + MonoTypeface = loadfont(DejaVuSansMono_glyphPoints, + DejaVuSansMono_glyphPointIndices, + DejaVuSansMono_glyphInstructions, + DejaVuSansMono_glyphInstructionIndices, + DejaVuSansMono_glyphInstructionCounts, + DejaVuSansMono_glyphAdvances, DejaVuSansMono_characterMap, DejaVuSansMono_glyphCount); + +} + +void deinitFont() +{ + unloadfont(SansTypeface.Glyphs, SansTypeface.Count); + unloadfont(SerifTypeface.Glyphs, SerifTypeface.Count); + unloadfont(MonoTypeface.Glyphs, MonoTypeface.Count); +} + +/*--------------------------------------------------------------*/ +GLuint CreateSimpleTexture2D( ) +{ + // Texture object handle + GLuint textureId; + + // 2x2 Image, 3 bytes per pixel (R, G, B) + GLubyte pixels[4 * 3] = + { + 255, 0, 0, // Red + 0, 255, 0, // Green + 0, 0, 255, // Blue + 255, 255, 0 // Yellow + }; + + // Use tightly packed data + glPixelStorei ( GL_UNPACK_ALIGNMENT, 1 ); + + // Generate a texture object + glGenTextures ( 1, &textureId ); + + // Bind the texture object + glBindTexture ( GL_TEXTURE_2D, textureId ); + + // Load the texture + glTexImage2D ( GL_TEXTURE_2D, 0, GL_RGB, 2, 2, 0, GL_RGB, GL_UNSIGNED_BYTE, pixels ); + + // Set the filtering mode + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST ); + glTexParameteri ( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST ); + + return textureId; + +} + +/// +// Initialize the shader and program object +// +int Init ( ESContext *esContext ) +{ + esContext->userData = malloc(sizeof(UserData)); + UserData *userData = esContext->userData; + GLbyte vShaderStr[] = + "attribute vec4 a_position; \n" + "attribute vec2 a_texCoord; \n" + "varying vec2 v_texCoord; \n" + "void main() \n" + "{ \n" + " gl_Position = a_position; \n" + " v_texCoord = a_texCoord; \n" + "} \n"; + + GLbyte fShaderStr[] = + "precision mediump float; \n" + "varying vec2 v_texCoord; \n" + "uniform sampler2D s_texture; \n" + "void main() \n" + "{ \n" + " gl_FragColor = texture2D( s_texture, v_texCoord );\n" + "} \n"; + + // Load the shaders and get a linked program object + userData->programObject = esLoadProgram ( vShaderStr, fShaderStr ); + + // Get the attribute locations + userData->positionLoc = glGetAttribLocation ( userData->programObject, "a_position" ); + userData->texCoordLoc = glGetAttribLocation ( userData->programObject, "a_texCoord" ); + + // Get the sampler location + userData->samplerLoc = glGetUniformLocation ( userData->programObject, "s_texture" ); + + // Load the texture + userData->textureId = CreateSimpleTexture2D (); + userData->time = 1.0f; + + glClearColor ( 0.0f, 0.0f, 0.0f, 0.0f ); + return GL_TRUE; +} + +void Draw ( ESContext *esContext ) +{ + UserData *userData = esContext->userData; + GLfloat vVertices[] = { -0.5f, 0.5f, 0.0f, // Position 0 + 0.0f, 0.0f, // TexCoord 0 + -0.5f, -0.5f, 0.0f, // Position 1 + 0.0f, 1.0f, // TexCoord 1 + 0.5f, -0.5f, 0.0f, // Position 2 + 1.0f, 1.0f, // TexCoord 2 + 0.5f, 0.5f, 0.0f, // Position 3 + 1.0f, 0.0f // TexCoord 3 + }; + GLushort indices[] = { 0, 1, 2, 0, 2, 3 }; + VGImageFormat f; + char text[] = "hello world\0"; + + + Start(esContext->width, esContext->height); // Start the picture + Background(esContext, 5, 5, 5); // Black background + Fill(44, 77, 232, 1.0); // Big blue marble + Circle((VGfloat) (esContext->width / 2), 0.0, (VGfloat)esContext->width); // The "world" + Fill(255, 255, 255, 1.0); // White text + TextMid((VGfloat)(esContext->width / 2),(VGfloat) ( esContext->height / 2),(char *) &text, SerifTypeface, esContext->width/10); // Greetings +// End(); + + f = VG_sARGB_8888; + + vgReadPixels(tgTextureBuffer, esContext->width*sizeof(unsigned int), f, 0, 0, esContext->width, esContext->height); + + // Set the viewport + glViewport ( 0, 0, esContext->width, esContext->height ); + + // Clear the color buffer + glClear ( GL_COLOR_BUFFER_BIT ); + + // Use the program object + glUseProgram ( userData->programObject ); + + // Load the vertex position + glVertexAttribPointer ( userData->positionLoc, 3, GL_FLOAT, + GL_FALSE, 5 * sizeof(GLfloat), vVertices ); + // Load the texture coordinate + glVertexAttribPointer ( userData->texCoordLoc, 2, GL_FLOAT, + GL_FALSE, 5 * sizeof(GLfloat), &vVertices[3] ); + + glEnableVertexAttribArray ( userData->positionLoc ); + glEnableVertexAttribArray ( userData->texCoordLoc ); + + // Bind the texture + glActiveTexture ( GL_TEXTURE0 ); + glBindTexture ( GL_TEXTURE_2D, userData->textureId ); + + // Set the sampler texture unit to 0 + glUniform1i ( userData->samplerLoc, 0 ); + + glDrawElements ( GL_TRIANGLES, 6, GL_UNSIGNED_SHORT, indices ); + +} + +int main ( int argc, char *argv[] ) +{ + ESContext esContext; + UserData userData; + VGPath myvgPath; + + memset(tgTextureBuffer, 0x00, WINDOW_W * WINDOW_H * 4); + + esInitContext ( &esContext ); + esContext.userData = &userData; + + DBG("Step 1. initial EGL"); + esCreateWindow ( &esContext, "Simple Texture 2D", WINDOW_W, WINDOW_H, ES_WINDOW_RGB ); + + Init(&esContext); + initFont(); + + esRegisterDrawFunc ( &esContext, Draw ); + + esMainLoop ( &esContext ); + +// ShutDown ( &esContext ); + + return 0; +} + + +#if 0 + +int main(void) +{ + fbdev_window window; + + VGPath myvgPath; + + window.width= WINDOW_W; + window.height= WINDOW_H; + + state->screen_width = window.width; + state->screen_height = window.height; + + + DBG("Step 1. initial EGL"); + init((NativeWindowType)&window); + +// vgCreateContextMNK((VGint)window.width, (VGint)window.height, VG_RENDERING_BACKEND_TYPE_OPENGLES20); + +#if 1 /* font */ + //font = vgCreateFont(0); + //fontpath1 = vgCreatePath(VG_PATH_FORMAT_STANDARD,VG_PATH_DATATYPE_F, 1, 0, 0, 0, VG_PATH_CAPABILITY_ALL); + //fontimg1 = vgCreateImage( VG_sRGBA_8888, window.width, window.height, VG_IMAGE_QUALITY_FASTER ); + + //vguEllipse(fontpath1, 5.0f,5.0f,5.0f,5.0f); + //vgImageSubData( fontimg1, image_data, window.width*4, VG_sRGBA_8888, 0, 0, window.width, window.height); + + //vgSetGlyphToPath(font, 'a',fontpath1, 1, origin, escapement); + //vgDestroyPath(fontpath1); + //vgSetGlyphToImage(font, 'b',fontimg1, origin, escapement); + + + //draw(window.width, window.height); + + //eglSwapBuffers(state->display, state->surface); + initFont(); + + Start(state->screen_width, state->screen_height); // Start the picture + Background( 0, 0, 0); // Black background + Fill(44, 77, 232, 1); // Big blue marble + Circle(state->screen_width / 2, 0, state->screen_width); // The "world" + Fill(255, 255, 255, 1); // White text + TextMid(state->screen_width / 2, state->screen_height / 2, "hello, world", SerifTypeface, state->screen_width/10); // Greetings + End(); + + +#endif + deinitFont(); + deinit(); + return(0); +} + +#endif + |