summaryrefslogtreecommitdiff
path: root/tiger.c
diff options
context:
space:
mode:
Diffstat (limited to 'tiger.c')
-rw-r--r--tiger.c417
1 files changed, 417 insertions, 0 deletions
diff --git a/tiger.c b/tiger.c
new file mode 100644
index 0000000..28c5f26
--- /dev/null
+++ b/tiger.c
@@ -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
+};