2 * Copyright (c) 2007 Ivan Leben
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library in the file COPYING;
16 * if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <vg/openvg.h>
22 #include "shContext.h"
26 /*-----------------------------------------------------
27 * Simple functions to create a VG context instance
28 * on top of an existing OpenGL context.
29 * TODO: There is no mechanics yet to asure the OpenGL
30 * context exists and to choose which context / window
32 *-----------------------------------------------------*/
34 static VGContext *g_context = NULL;
36 VG_API_CALL VGboolean vgCreateContextSH(VGint width, VGint height)
38 /* return if already created */
39 if (g_context) return VG_TRUE;
41 /* create new context */
42 SH_NEWOBJ(VGContext, g_context);
43 if (!g_context) return VG_FALSE;
45 /* init surface info */
46 g_context->surfaceWidth = width;
47 g_context->surfaceHeight = height;
49 /* setup GL projection */
50 /* We handle viewport and projection ourselves...
52 glViewport(0,0,width,height);
54 glMatrixMode(GL_PROJECTION);
56 glOrtho(0, width, 0, height, -1, 1);
58 glMatrixMode(GL_MODELVIEW);
64 VG_API_CALL VGboolean vgHasContextSH()
66 return g_context != NULL;
69 VG_API_CALL void vgResizeSurfaceSH(VGint width, VGint height)
71 VG_GETCONTEXT(VG_NO_RETVAL);
73 /* update surface info */
74 context->surfaceWidth = width;
75 context->surfaceHeight = height;
77 /* setup GL projection */
78 glViewport(0,0,width,height);
80 glMatrixMode(GL_PROJECTION);
82 glOrtho(0, width, 0, height, -1, 1);
84 glMatrixMode(GL_MODELVIEW);
87 VG_RETURN(VG_NO_RETVAL);
90 VG_API_CALL void vgDestroyContextSH()
92 /* return if already released */
93 if (!g_context) return;
95 /* delete context object */
96 SH_DELETEOBJ(VGContext, g_context);
100 VGContext* shGetContext()
102 SH_ASSERT(g_context);
106 /*-----------------------------------------------------
107 * VGContext constructor
108 *-----------------------------------------------------*/
110 void shLoadExtensions(VGContext *c);
112 void VGContext_ctor(VGContext *c)
116 c->surfaceHeight = 0;
119 strncpy(c->vendor, "Ivan Leben", sizeof(c->vendor));
120 strncpy(c->renderer, "ShivaVG 0.1.0", sizeof(c->renderer));
121 strncpy(c->version, "1.0", sizeof(c->version));
122 strncpy(c->extensions, "", sizeof(c->extensions));
125 c->matrixMode = VG_MATRIX_PATH_USER_TO_SURFACE;
126 c->fillRule = VG_EVEN_ODD;
127 c->imageQuality = VG_IMAGE_QUALITY_FASTER;
128 c->renderingQuality = VG_RENDERING_QUALITY_BETTER;
129 c->blendMode = VG_BLEND_SRC_OVER;
130 c->imageMode = VG_DRAW_IMAGE_NORMAL;
132 /* Scissor rectangles */
133 SH_INITOBJ(SHRectArray, c->scissor);
134 c->scissoring = VG_FALSE;
135 c->masking = VG_FALSE;
137 /* Stroke parameters */
138 c->strokeLineWidth = 1.0f;
139 c->strokeCapStyle = VG_CAP_BUTT;
140 c->strokeJoinStyle = VG_JOIN_MITER;
141 c->strokeMiterLimit = 4.0f;
142 c->strokeDashPhase = 0.0f;
143 c->strokeDashPhaseReset = VG_FALSE;
144 SH_INITOBJ(SHFloatArray, c->strokeDashPattern);
146 /* Edge fill color for vgConvolve and pattern paint */
147 CSET(c->tileFillColor, 0,0,0,0);
149 /* Color for vgClear */
150 CSET(c->clearColor, 0,0,0,0);
152 /* Color components layout inside pixel */
153 c->pixelLayout = VG_PIXEL_LAYOUT_UNKNOWN;
155 /* Source format for image filters */
156 c->filterFormatLinear = VG_FALSE;
157 c->filterFormatPremultiplied = VG_FALSE;
158 c->filterChannelMask = VG_RED|VG_GREEN|VG_BLUE|VG_ALPHA;
161 SH_INITOBJ(SHMatrix3x3, c->pathTransform);
162 SH_INITOBJ(SHMatrix3x3, c->imageTransform);
163 SH_INITOBJ(SHMatrix3x3, c->fillTransform);
164 SH_INITOBJ(SHMatrix3x3, c->strokeTransform);
168 c->strokePaint = NULL;
169 SH_INITOBJ(SHPaint, c->defaultPaint);
172 c->error = VG_NO_ERROR;
175 SH_INITOBJ(SHPathArray, c->paths);
176 SH_INITOBJ(SHPaintArray, c->paints);
177 SH_INITOBJ(SHImageArray, c->images);
182 /*-----------------------------------------------------
183 * VGContext constructor
184 *-----------------------------------------------------*/
186 void VGContext_dtor(VGContext *c)
190 SH_DEINITOBJ(SHRectArray, c->scissor);
191 SH_DEINITOBJ(SHFloatArray, c->strokeDashPattern);
193 /* Destroy resources */
194 for (i=0; i<c->paths.size; ++i)
195 SH_DELETEOBJ(SHPath, c->paths.items[i]);
197 for (i=0; i<c->paints.size; ++i)
198 SH_DELETEOBJ(SHPaint, c->paints.items[i]);
200 for (i=0; i<c->images.size; ++i)
201 SH_DELETEOBJ(SHImage, c->images.items[i]);
204 /*--------------------------------------------------
205 * Tries to find resources in this context
206 *--------------------------------------------------*/
208 SHint shIsValidPath(VGContext *c, VGHandle h)
210 int index = shPathArrayFind(&c->paths, (SHPath*)h);
211 return (index == -1) ? 0 : 1;
214 SHint shIsValidPaint(VGContext *c, VGHandle h)
216 int index = shPaintArrayFind(&c->paints, (SHPaint*)h);
217 return (index == -1) ? 0 : 1;
220 SHint shIsValidImage(VGContext *c, VGHandle h)
222 int index = shImageArrayFind(&c->images, (SHImage*)h);
223 return (index == -1) ? 0 : 1;
226 /*--------------------------------------------------
227 * Tries to find a resources in this context and
228 * return its type or invalid flag.
229 *--------------------------------------------------*/
231 SHResourceType shGetResourceType(VGContext *c, VGHandle h)
233 if (shIsValidPath(c, h))
234 return SH_RESOURCE_PATH;
236 else if (shIsValidPaint(c, h))
237 return SH_RESOURCE_PAINT;
239 else if (shIsValidImage(c, h))
240 return SH_RESOURCE_IMAGE;
243 return SH_RESOURCE_INVALID;
246 /*-----------------------------------------------------
247 * Sets the specified error on the given context if
248 * there is no pending error yet
249 *-----------------------------------------------------*/
251 void shSetError(VGContext *c, VGErrorCode e)
253 if (c->error == VG_NO_ERROR)
257 /*--------------------------------------------------
258 * Returns the oldest error pending on the current
259 * context and clears its error code
260 *--------------------------------------------------*/
262 VG_API_CALL VGErrorCode vgGetError(void)
265 VG_GETCONTEXT(VG_NO_CONTEXT_ERROR);
266 error = context->error;
267 context->error = VG_NO_ERROR;
271 VG_API_CALL void vgFlush(void)
273 VG_GETCONTEXT(VG_NO_RETVAL);
275 VG_RETURN(VG_NO_RETVAL);
278 VG_API_CALL void vgFinish(void)
280 VG_GETCONTEXT(VG_NO_RETVAL);
282 VG_RETURN(VG_NO_RETVAL);
285 VG_API_CALL void vgMask(VGImage mask, VGMaskOperation operation,
286 VGint x, VGint y, VGint width, VGint height)
290 VG_API_CALL void vgClear(VGint x, VGint y, VGint width, VGint height)
292 VG_GETCONTEXT(VG_NO_RETVAL);
297 if (width > context->surfaceWidth) width = context->surfaceWidth;
298 if (height > context->surfaceHeight) height = context->surfaceHeight;
300 /* Check if scissoring needed */
301 if (x > 0 || y > 0 ||
302 width < context->surfaceWidth ||
303 height < context->surfaceHeight) {
305 glScissor(x, y, width, height);
306 glEnable(GL_SCISSOR_TEST);
309 /* Clear GL color buffer */
310 /* TODO: what about stencil and depth? when do we clear that?
311 we would need some kind of special "begin" function at
312 beginning of each drawing or clear the planes prior to each
313 drawing where it takes places */
314 glClearColor(context->clearColor.r,
315 context->clearColor.g,
316 context->clearColor.b,
317 context->clearColor.a);
319 glClear(GL_COLOR_BUFFER_BIT |
320 GL_STENCIL_BUFFER_BIT |
321 GL_DEPTH_BUFFER_BIT);
323 glDisable(GL_SCISSOR_TEST);
325 VG_RETURN(VG_NO_RETVAL);
328 /*-----------------------------------------------------------
329 * Returns the matrix currently selected via VG_MATRIX_MODE
330 *-----------------------------------------------------------*/
332 SHMatrix3x3* shCurrentMatrix(VGContext *c)
334 switch(c->matrixMode) {
335 case VG_MATRIX_PATH_USER_TO_SURFACE:
336 return &c->pathTransform;
337 case VG_MATRIX_IMAGE_USER_TO_SURFACE:
338 return &c->imageTransform;
339 case VG_MATRIX_FILL_PAINT_TO_USER:
340 return &c->fillTransform;
342 return &c->strokeTransform;
346 /*--------------------------------------
347 * Sets the current matrix to identity
348 *--------------------------------------*/
350 VG_API_CALL void vgLoadIdentity(void)
353 VG_GETCONTEXT(VG_NO_RETVAL);
355 m = shCurrentMatrix(context);
358 VG_RETURN(VG_NO_RETVAL);
361 /*-------------------------------------------------------------
362 * Loads values into the current matrix from the given array.
363 * Matrix affinity is preserved if an affine matrix is loaded.
364 *-------------------------------------------------------------*/
366 VG_API_CALL void vgLoadMatrix(const VGfloat * mm)
369 VG_GETCONTEXT(VG_NO_RETVAL);
371 VG_RETURN_ERR_IF(!mm, VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
372 /* TODO: check matrix array alignment */
374 m = shCurrentMatrix(context);
376 if (context->matrixMode == VG_MATRIX_IMAGE_USER_TO_SURFACE) {
381 mm[2], mm[5], mm[8]);
390 VG_RETURN(VG_NO_RETVAL);
393 /*---------------------------------------------------------------
394 * Outputs the values of the current matrix into the given array
395 *---------------------------------------------------------------*/
397 VG_API_CALL void vgGetMatrix(VGfloat * mm)
399 SHMatrix3x3 *m; int i,j,k=0;
400 VG_GETCONTEXT(VG_NO_RETVAL);
402 VG_RETURN_ERR_IF(!mm, VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
403 /* TODO: check matrix array alignment */
405 m = shCurrentMatrix(context);
409 mm[k++] = m->m[j][i];
411 VG_RETURN(VG_NO_RETVAL);
414 /*-------------------------------------------------------------
415 * Right-multiplies the current matrix with the one specified
416 * in the given array. Matrix affinity is preserved if an
417 * affine matrix is begin multiplied.
418 *-------------------------------------------------------------*/
420 VG_API_CALL void vgMultMatrix(const VGfloat * mm)
422 SHMatrix3x3 *m, mul, temp;
423 VG_GETCONTEXT(VG_NO_RETVAL);
425 VG_RETURN_ERR_IF(!mm, VG_ILLEGAL_ARGUMENT_ERROR, VG_NO_RETVAL);
426 /* TODO: check matrix array alignment */
428 m = shCurrentMatrix(context);
430 if (context->matrixMode == VG_MATRIX_IMAGE_USER_TO_SURFACE) {
435 mm[2], mm[5], mm[8]);
444 MULMATMAT((*m), mul, temp);
445 SETMATMAT((*m), temp);
447 VG_RETURN(VG_NO_RETVAL);
450 VG_API_CALL void vgTranslate(VGfloat tx, VGfloat ty)
453 VG_GETCONTEXT(VG_NO_RETVAL);
455 m = shCurrentMatrix(context);
456 TRANSLATEMATR((*m), tx, ty);
458 VG_RETURN(VG_NO_RETVAL);
461 VG_API_CALL void vgScale(VGfloat sx, VGfloat sy)
464 VG_GETCONTEXT(VG_NO_RETVAL);
466 m = shCurrentMatrix(context);
467 SCALEMATR((*m), sx, sy);
469 VG_RETURN(VG_NO_RETVAL);
472 VG_API_CALL void vgShear(VGfloat shx, VGfloat shy)
475 VG_GETCONTEXT(VG_NO_RETVAL);
477 m = shCurrentMatrix(context);
478 SHEARMATR((*m), shx, shy);
480 VG_RETURN(VG_NO_RETVAL);
483 VG_API_CALL void vgRotate(VGfloat angle)
487 VG_GETCONTEXT(VG_NO_RETVAL);
489 a = SH_DEG2RAD(angle);
490 m = shCurrentMatrix(context);
493 VG_RETURN(VG_NO_RETVAL);
496 VG_API_CALL VGHardwareQueryResult vgHardwareQuery(VGHardwareQueryType key,
499 return VG_HARDWARE_UNACCELERATED;