/**************************************************************************** ** 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 #include #include #include "tiger.h" #include "tiger_data.h" #include 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 };