diff options
Diffstat (limited to 'tiger.c')
-rw-r--r-- | tiger.c | 417 |
1 files changed, 417 insertions, 0 deletions
@@ -0,0 +1,417 @@ +/**************************************************************************** +** Authors: Matteo Muratori, Michele Fabbri. +** +** Official website: http://www.amanithvg.com +** +** Copyright (C) 2004-2009 Mazatech S.r.l. All rights reserved. +** +** This file is part of AmanithVG library. +** Khronos and OpenVG are trademarks of The Khronos Group Inc. +** OpenGL is a registered trademark and OpenGL ES is a trademark of +** Silicon Graphics, Inc. +** +** This file is distributed under the terms of Mazatech End-User License +** Agreement for Evaluation Purposes only as defined by Mazatech S.r.l. of +** Italy and appearing in the file LICENSE.TXT included in the packaging +** of this file. +** +** This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE +** WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. +** +** For any informations, please contact info@mazatech.com +** +****************************************************************************/ +#include <VG/openvg.h> +#include <VG/vgu.h> +#include <VG/vgext.h> + +#include "tiger.h" +#include "tiger_data.h" +#include <stdlib.h> + +typedef struct { + VGFillRule m_fillRule; + VGPaintMode m_paintMode; + VGCapStyle m_capStyle; + VGJoinStyle m_joinStyle; + VGfloat m_miterLimit; + VGfloat m_strokeWidth; + VGPaint m_fillPaint; + VGPaint m_strokePaint; + VGPath m_path; +} PathData; + +typedef struct { + PathData* m_paths; + VGint m_numPaths; +} PS; + +static VGRenderingQuality quality; +static VGboolean animationActive; +static PS* tiger = NULL; +static VGfloat translation[2]; +static VGfloat zoomFactor, zoomSpeed; +static VGfloat rotation, rotationSpeed; +static VGint oldMouseX, oldMouseY; +static VGint mouseButtonState; + +static void resetParameters(void); + +static PS * +PS_construct(const char *commands, int commandCount, const float *points, int pointCount) { + + PS *ps = (PS*)malloc(sizeof(PS)); + int p = 0; + int c = 0; + int i = 0; + int paths = 0; + int maxElements = 0; + unsigned char *cmd; + + (void)pointCount; + + while (c < commandCount) { + + int elements, e; + + c += 4; + p += 8; + elements = (int)points[p++]; + if (elements > maxElements) + maxElements = elements; + for (e = 0; e < elements ; e++) { + switch (commands[c]) { + case 'M': + p += 2; + break; + case 'L': + p += 2; + break; + case 'C': + p += 6; + break; + case 'E': + break; + } + c++; + } + paths++; + } + + ps->m_numPaths = paths; + ps->m_paths = (PathData *)malloc(paths * sizeof(PathData)); + cmd = (unsigned char *)malloc(maxElements); + + i = 0; + p = 0; + c = 0; + while (c < commandCount) { + + int elements, startp, e; + float color[4]; + int paintMode = 0; + + // fill type + ps->m_paths[i].m_fillRule = VG_NON_ZERO; + switch (commands[c]) { + case 'N': + break; + case 'F': + ps->m_paths[i].m_fillRule = VG_NON_ZERO; + paintMode |= VG_FILL_PATH; + break; + case 'E': + ps->m_paths[i].m_fillRule = VG_EVEN_ODD; + paintMode |= VG_FILL_PATH; + break; + } + c++; + // stroke + switch (commands[c]) { + case 'N': + break; + case 'S': + paintMode |= VG_STROKE_PATH; + break; + } + ps->m_paths[i].m_paintMode = (VGPaintMode)paintMode; + c++; + // line cap + switch (commands[c]) { + case 'B': + ps->m_paths[i].m_capStyle = VG_CAP_BUTT; + break; + case 'R': + ps->m_paths[i].m_capStyle = VG_CAP_ROUND; + break; + case 'S': + ps->m_paths[i].m_capStyle = VG_CAP_SQUARE; + break; + } + c++; + // line join + switch (commands[c]) { + case 'M': + ps->m_paths[i].m_joinStyle = VG_JOIN_MITER; + break; + case 'R': + ps->m_paths[i].m_joinStyle = VG_JOIN_ROUND; + break; + case 'B': + ps->m_paths[i].m_joinStyle = VG_JOIN_BEVEL; + break; + } + c++; + // the rest of stroke attributes + ps->m_paths[i].m_miterLimit = points[p++]; + ps->m_paths[i].m_strokeWidth = points[p++]; + // paints + color[0] = points[p++]; + color[1] = points[p++]; + color[2] = points[p++]; + color[3] = 1.0f; + ps->m_paths[i].m_strokePaint = vgCreatePaint(); + vgSetParameteri(ps->m_paths[i].m_strokePaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + vgSetParameterfv(ps->m_paths[i].m_strokePaint, VG_PAINT_COLOR, 4, color); + + color[0] = points[p++]; + color[1] = points[p++]; + color[2] = points[p++]; + color[3] = 1.0f; + ps->m_paths[i].m_fillPaint = vgCreatePaint(); + vgSetParameteri(ps->m_paths[i].m_fillPaint, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR); + vgSetParameterfv(ps->m_paths[i].m_fillPaint, VG_PAINT_COLOR, 4, color); + // read number of elements + elements = (int)points[p++]; + startp = p; + for (e = 0 ; e < elements; e++) { + switch (commands[c]) { + case 'M': + cmd[e] = VG_MOVE_TO | VG_ABSOLUTE; + p += 2; + break; + case 'L': + cmd[e] = VG_LINE_TO | VG_ABSOLUTE; + p += 2; + break; + case 'C': + cmd[e] = VG_CUBIC_TO | VG_ABSOLUTE; + p += 6; + break; + case 'E': + cmd[e] = VG_CLOSE_PATH; + break; + } + c++; + } + ps->m_paths[i].m_path = vgCreatePath(VG_PATH_FORMAT_STANDARD, VG_PATH_DATATYPE_F, 1.0f, 0.0f, 0, 0, (unsigned int)VG_PATH_CAPABILITY_ALL); + vgAppendPathData(ps->m_paths[i].m_path, elements, cmd, points + startp); + vgRemovePathCapabilities(ps->m_paths[i].m_path, VG_PATH_CAPABILITY_ALL); + i++; + } + free(cmd); + return ps; +} + +static void +PS_destruct(PS* ps) { + + int i; + + for (i = 0; i < ps->m_numPaths; i++) { + vgDestroyPaint(ps->m_paths[i].m_fillPaint); + vgDestroyPaint(ps->m_paths[i].m_strokePaint); + vgDestroyPath(ps->m_paths[i].m_path); + } + free(ps->m_paths); + free(ps); +} + +static void +PS_render(PS* ps) { + + int i; + + for (i = 0; i < ps->m_numPaths; i++) { + vgSeti(VG_FILL_RULE, ps->m_paths[i].m_fillRule); + vgSetPaint(ps->m_paths[i].m_fillPaint, VG_FILL_PATH); + if (ps->m_paths[i].m_paintMode & VG_STROKE_PATH) { + vgSetf(VG_STROKE_LINE_WIDTH, ps->m_paths[i].m_strokeWidth); + vgSeti(VG_STROKE_CAP_STYLE, ps->m_paths[i].m_capStyle); + vgSeti(VG_STROKE_JOIN_STYLE, ps->m_paths[i].m_joinStyle); + vgSetf(VG_STROKE_MITER_LIMIT, ps->m_paths[i].m_miterLimit); + vgSetPaint(ps->m_paths[i].m_strokePaint, VG_STROKE_PATH); + } + vgDrawPath(ps->m_paths[i].m_path, ps->m_paths[i].m_paintMode); + } +} + +static void +initApp(int windowWidth, int windowHeight) { + + VGfloat clearColor[4] = { 0.8f, 0.8f, 0.8f, 1.0f }; + + (void)windowWidth; + (void)windowHeight; + resetParameters(); + tiger = PS_construct(tigerCommands, tigerCommandCount, tigerPoints, tigerPointCount); + + mouseButtonState = 0; + + vgSeti(VG_SCISSORING, VG_FALSE); + vgSeti(VG_MASKING, VG_FALSE); + vgSetfv(VG_CLEAR_COLOR, 4, clearColor); + vgSeti(VG_MATRIX_MODE, VG_MATRIX_IMAGE_USER_TO_SURFACE); + vgLoadIdentity(); +} + +static void +killApp(void) { + + if (tiger) + PS_destruct(tiger); +} + +static void +changeQuality(void) { + + if (quality == VG_RENDERING_QUALITY_FASTER) + quality = VG_RENDERING_QUALITY_BETTER; + else + if (quality == VG_RENDERING_QUALITY_BETTER) + quality = VG_RENDERING_QUALITY_NONANTIALIASED; + else + quality = VG_RENDERING_QUALITY_FASTER; +} + +static void +toggleAnimation(void) { + + if (animationActive == VG_TRUE) + animationActive = VG_FALSE; + else + animationActive = VG_TRUE; +} + +static void +resetParameters(void) { + + rotation = 0.0f; + rotationSpeed = 0.25f; + zoomFactor = 1.0f; + zoomSpeed = 0.1f; + translation[0] = 0.0f; + translation[1] = 0.0f; + animationActive = VG_FALSE; + quality = VG_RENDERING_QUALITY_BETTER; +} + +static void +deltaZoom(const VGfloat delta) { + + zoomFactor += delta * zoomFactor; + if (zoomFactor < 0.005f) + zoomFactor = 0.005f; + if (zoomFactor > 650.000f) + zoomFactor = 650.000f; +} + +static void +deltaTranslation(const VGfloat deltaX, const VGfloat deltaY) { + + translation[0] += deltaX; + translation[1] += deltaY; +} + +static void +mouseLeftButtonDown(int x, int y) { + + oldMouseX = x; + oldMouseY = y; + mouseButtonState = 1; +} + +static void +mouseLeftButtonUp(int x, int y) { + + (void)x; + (void)y; + + mouseButtonState = 0; +} + +static void +mouseRightButtonDown(int x, int y) { + + oldMouseX = x; + oldMouseY = y; + mouseButtonState = 2; +} + +static void +mouseRightButtonUp(int x, int y) { + + (void)x; + (void)y; + + mouseButtonState = 0; +} + +static void +mouseMove(int x, int y) { + + if (mouseButtonState == 1) { + + deltaTranslation((VGfloat)(x - oldMouseX), (VGfloat)(-(y - oldMouseY))); + oldMouseX = x; + oldMouseY = y; + } + else + if (mouseButtonState == 2) { + + VGint deltaX = x - oldMouseX; + VGint deltaY = y - oldMouseY; + VGint delta = (abs(deltaX) > abs(deltaY)) ? deltaX : -deltaY; + + oldMouseX = x; + oldMouseY = y; + deltaZoom(delta * 0.003f); + } +} + +static void +drawScene(int windowWidth, int windowHeight) { + + VGfloat scale = windowHeight / tigerMaxY; + + if (animationActive) + rotation += rotationSpeed; + + vgSeti(VG_RENDERING_QUALITY, quality); + vgSeti(VG_BLEND_MODE, VG_BLEND_SRC); + vgClear(0, 0, windowWidth, windowHeight); + vgSeti(VG_MATRIX_MODE, VG_MATRIX_PATH_USER_TO_SURFACE); + vgLoadIdentity(); + vgTranslate(translation[0], translation[1]); + vgTranslate(0.5f * (windowWidth - tigerMaxX * scale), -(VGfloat)windowHeight / 12.0f); + vgScale(scale, scale); + vgTranslate(tigerMaxX * 0.5f, tigerMaxY * 0.5f + 65.0f); + vgScale(zoomFactor, zoomFactor); + vgRotate(rotation); + vgTranslate(-tigerMaxX * 0.5f, (-tigerMaxY * 0.5f - 65.0f)); + PS_render(tiger); +} + +struct app vg_tiger_app = { + initApp, + killApp, + drawScene, + mouseLeftButtonDown, + mouseLeftButtonUp, + mouseRightButtonDown, + mouseRightButtonUp, + mouseMove, + changeQuality, + toggleAnimation, + resetParameters +}; |