]> git.mxchange.org Git - simgear.git/blob - simgear/canvas/ShivaVG/src/shParams.c
Update for OpenSceneGraph 3.3.2 API changes.
[simgear.git] / simgear / canvas / ShivaVG / src / shParams.c
1 /*
2  * Copyright (c) 2007 Ivan Leben
3  *
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.
8  * 
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.
13  * 
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
18  *
19  */
20
21 #include <stdio.h>
22 #include <vg/openvg.h>
23 #include "shContext.h"
24
25 /*----------------------------------------------------
26  * Returns true (1) if the specified parameter takes
27  * a vector of values (more than 1) or false (0)
28  * otherwise.
29  *----------------------------------------------------*/
30
31 int shIsParamVector(SHint type)
32 {
33   return
34     (type == VG_SCISSOR_RECTS ||
35      type == VG_STROKE_DASH_PATTERN ||
36      type == VG_TILE_FILL_COLOR ||
37      type == VG_CLEAR_COLOR ||
38      type == VG_PAINT_COLOR ||
39      type == VG_PAINT_COLOR_RAMP_STOPS ||
40      type == VG_PAINT_LINEAR_GRADIENT ||
41      type == VG_PAINT_RADIAL_GRADIENT);
42 }
43
44 /*----------------------------------------------------
45  * Returns true (1) if the given integer is a valid
46  * enumeration value for the specified parameter or
47  * false (0) otherwise.
48  *----------------------------------------------------*/
49   
50 int shIsEnumValid(SHint type, VGint val)
51 {
52   switch(type)
53   {
54   case VG_MATRIX_MODE:
55     return (val == VG_MATRIX_PATH_USER_TO_SURFACE ||
56             val == VG_MATRIX_IMAGE_USER_TO_SURFACE ||
57             val == VG_MATRIX_FILL_PAINT_TO_USER ||
58             val == VG_MATRIX_STROKE_PAINT_TO_USER);
59     
60   case VG_FILL_RULE:
61     return (val == VG_EVEN_ODD ||
62             val == VG_NON_ZERO)  ? VG_TRUE : VG_FALSE;
63     
64   case VG_IMAGE_QUALITY:
65     return (val == VG_IMAGE_QUALITY_NONANTIALIASED ||
66             val == VG_IMAGE_QUALITY_FASTER ||
67             val == VG_IMAGE_QUALITY_BETTER);
68     
69   case VG_RENDERING_QUALITY:
70     return (val == VG_RENDERING_QUALITY_NONANTIALIASED ||
71             val == VG_RENDERING_QUALITY_FASTER ||
72             val == VG_RENDERING_QUALITY_BETTER);
73     
74   case VG_BLEND_MODE:
75     return (val == VG_BLEND_SRC ||
76             val == VG_BLEND_SRC_OVER ||
77             val == VG_BLEND_DST_OVER ||
78             val == VG_BLEND_SRC_IN ||
79             val == VG_BLEND_DST_IN ||
80             val == VG_BLEND_MULTIPLY ||
81             val == VG_BLEND_SCREEN ||
82             val == VG_BLEND_DARKEN ||
83             val == VG_BLEND_LIGHTEN ||
84             val == VG_BLEND_ADDITIVE ||
85             val == VG_BLEND_SRC_OUT_SH ||
86             val == VG_BLEND_DST_OUT_SH ||
87             val == VG_BLEND_SRC_ATOP_SH ||
88             val == VG_BLEND_DST_ATOP_SH);
89     
90   case VG_IMAGE_MODE:
91     return (val == VG_DRAW_IMAGE_NORMAL ||
92             val == VG_DRAW_IMAGE_MULTIPLY ||
93             val == VG_DRAW_IMAGE_STENCIL);
94     
95   case VG_STROKE_CAP_STYLE:
96     return (val == VG_CAP_BUTT ||
97             val == VG_CAP_ROUND ||
98             val == VG_CAP_SQUARE);
99     
100   case VG_STROKE_JOIN_STYLE:
101     return (val == VG_JOIN_MITER ||
102             val == VG_JOIN_ROUND ||
103             val == VG_JOIN_BEVEL);
104     
105   case VG_STROKE_DASH_PHASE_RESET:
106   case VG_SCISSORING:
107   case VG_MASKING:
108     return (val == VG_TRUE ||
109             val == VG_FALSE);
110     
111   case VG_PIXEL_LAYOUT:
112     return (val == VG_PIXEL_LAYOUT_UNKNOWN ||
113             val == VG_PIXEL_LAYOUT_RGB_VERTICAL ||
114             val == VG_PIXEL_LAYOUT_BGR_VERTICAL ||
115             val == VG_PIXEL_LAYOUT_RGB_HORIZONTAL ||
116             val == VG_PIXEL_LAYOUT_BGR_HORIZONTAL);
117     
118   case VG_FILTER_FORMAT_LINEAR:
119   case VG_FILTER_FORMAT_PREMULTIPLIED:
120     return (val == VG_TRUE ||
121             val == VG_FALSE);
122     
123   case VG_PAINT_TYPE:
124     return (val == VG_PAINT_TYPE_COLOR ||
125             val == VG_PAINT_TYPE_LINEAR_GRADIENT ||
126             val == VG_PAINT_TYPE_RADIAL_GRADIENT ||
127             val == VG_PAINT_TYPE_PATTERN);
128     
129   case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
130     return (val == VG_COLOR_RAMP_SPREAD_PAD ||
131             val == VG_COLOR_RAMP_SPREAD_REPEAT ||
132             val == VG_COLOR_RAMP_SPREAD_REFLECT);
133     
134   case VG_PAINT_PATTERN_TILING_MODE:
135     return (val == VG_TILE_FILL ||
136             val == VG_TILE_PAD ||
137             val == VG_TILE_REPEAT ||
138             val == VG_TILE_REFLECT);
139     
140   case VG_IMAGE_FORMAT:
141     return (val >= VG_sRGBX_8888 &&
142             val <= VG_lABGR_8888_PRE);
143     
144   default:
145     return 1;
146   }
147 }
148
149 /*--------------------------------------------------------
150  * These two functions check for invalid (erroneus) float
151  * input and correct it to acceptable ranges.
152  *---------------------------------------------------*/
153
154 SHfloat getMaxFloat()
155 {
156   SHfloatint fi;
157   fi.i = SH_MAX_FLOAT_BITS;
158   return fi.f;
159 }
160
161 SHfloat shValidInputFloat(VGfloat f)
162 {
163   SHfloat max = getMaxFloat();
164   if (SH_ISNAN(f)) return 0.0f; /* convert NAN to zero */
165   SH_CLAMP(f, -max, max); /* clamp to valid range */
166   return (SHfloat)f;
167 }
168
169 static SHint shValidInputFloat2Int(VGfloat f)
170 {
171   double v = (double)SH_FLOOR(shValidInputFloat(f));
172   SH_CLAMP(v, (double)SH_MIN_INT, (double)SH_MAX_INT);
173   return (SHint)v;
174 }
175
176 /*---------------------------------------------------
177  * Interpretes the input value vector as an array of
178  * integers and returns the value at given index
179  *---------------------------------------------------*/
180
181 static SHint shParamToInt(const void *values, SHint floats, SHint index)
182 {
183   if (floats)
184     return shValidInputFloat2Int(((const VGfloat*)values)[index]);
185   else
186     return (SHint)((const VGint*)values)[index];
187 }
188
189 /*---------------------------------------------------
190  * Interpretes the input value vector as an array of
191  * floats and returns the value at given index
192  *---------------------------------------------------*/
193
194 static VGfloat shParamToFloat(const void *values, SHint floats, SHint index)
195 {
196   if (floats)
197     return shValidInputFloat(((const VGfloat*)values)[index]);
198   else
199     return (SHfloat)((const VGint*)values)[index];
200 }
201
202 /*---------------------------------------------------
203  * Interpretes the output value vector as an array of
204  * integers and sets the value at given index
205  *---------------------------------------------------*/
206
207 static void shIntToParam(SHint i, SHint count, void *output, SHint floats, SHint index)
208 {
209   if (index >= count)
210     return;
211   if (floats)
212     ((VGfloat*)output)[index] = (VGfloat)i;
213   else
214     ((VGint*)output)[index] = (VGint)i;
215 }
216
217 /*----------------------------------------------------
218  * Interpretes the output value vector as an array of
219  * floats and sets the value at given index
220  *----------------------------------------------------*/
221
222 static void shFloatToParam(SHfloat f, SHint count, void *output, SHint floats, SHint index)
223 {
224   if (index >= count)
225     return;
226   if (floats)
227     ((VGfloat*)output)[index] = (VGfloat)f;
228   else
229     ((VGint*)output)[index] = (VGint)shValidInputFloat2Int(f);
230 }
231
232 /*---------------------------------------------------------
233  * Sets a parameter by interpreting the input value vector
234  * according to the parameter type and input type.
235  *---------------------------------------------------------*/
236
237 static void shSet(VGContext *context, VGParamType type, SHint count,
238                   const void* values, SHint floats)
239 {
240   SHfloat fvalue = 0.0f;
241   SHint ivalue = 0;
242   VGboolean bvalue = VG_FALSE;
243   int i = 0;
244   
245   /* Check for negative count */
246   SH_RETURN_ERR_IF(count<0, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
247   
248   /* Check for empty vector */
249   SH_RETURN_ERR_IF(!values && count!=0, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
250   
251   /* Pre-convert first value for non-vector params */
252   if (count == 1) {
253     fvalue = shParamToFloat(values, floats, 0);
254     ivalue = shParamToInt(values, floats, 0);
255     bvalue = (ivalue ? VG_TRUE : VG_FALSE);
256   }
257   
258   switch (type)
259   {
260   case VG_MATRIX_MODE:
261     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
262     SH_RETURN_ERR_IF(!shIsEnumValid(type,ivalue), VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
263     context->matrixMode = (VGMatrixMode)ivalue;
264     break;
265     
266   case VG_FILL_RULE:
267     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
268     SH_RETURN_ERR_IF(!shIsEnumValid(type,ivalue), VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
269     context->fillRule = (VGFillRule)ivalue;
270     break;
271     
272   case VG_IMAGE_QUALITY:
273     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
274     SH_RETURN_ERR_IF(!shIsEnumValid(type,ivalue), VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
275     context->imageQuality = (VGImageQuality)ivalue;
276     break;
277     
278   case VG_RENDERING_QUALITY:
279     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
280     SH_RETURN_ERR_IF(!shIsEnumValid(type,ivalue), VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
281     context->renderingQuality = (VGRenderingQuality)ivalue;
282     break;
283     
284   case VG_BLEND_MODE:
285     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
286     SH_RETURN_ERR_IF(!shIsEnumValid(type,ivalue), VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
287     context->blendMode = (VGBlendMode)ivalue;
288     break;
289     
290   case VG_IMAGE_MODE:
291     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
292     SH_RETURN_ERR_IF(!shIsEnumValid(type,ivalue), VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
293     context->imageMode = (VGImageMode)ivalue;
294     break;
295     
296   case VG_STROKE_CAP_STYLE:
297     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
298     SH_RETURN_ERR_IF(!shIsEnumValid(type,ivalue), VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
299     context->strokeCapStyle = (VGCapStyle)ivalue;
300     break;
301     
302   case VG_STROKE_JOIN_STYLE:
303     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
304     SH_RETURN_ERR_IF(!shIsEnumValid(type,ivalue), VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
305     context->strokeJoinStyle = (VGJoinStyle)ivalue;
306     break;
307     
308   case VG_PIXEL_LAYOUT:
309     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
310     SH_RETURN_ERR_IF(!shIsEnumValid(type,ivalue), VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
311     context->pixelLayout = (VGPixelLayout)ivalue;
312     break;
313     
314   case VG_FILTER_CHANNEL_MASK:
315     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
316     context->filterChannelMask = (VGbitfield)ivalue;
317     break;
318     
319   case VG_FILTER_FORMAT_LINEAR:
320     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
321     context->filterFormatLinear = bvalue;
322     break;
323     
324   case VG_FILTER_FORMAT_PREMULTIPLIED:
325     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
326     context->filterFormatPremultiplied = bvalue;
327     break;
328     
329   case VG_STROKE_DASH_PHASE_RESET:
330     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
331     context->strokeDashPhaseReset = bvalue;
332     break;
333     
334   case VG_MASKING:
335     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
336     context->masking = bvalue;
337     break;
338     
339   case VG_SCISSORING:
340     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
341     context->scissoring = bvalue;
342     break;
343     
344   case VG_STROKE_LINE_WIDTH:
345     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
346     context->strokeLineWidth = fvalue;
347     break;
348     
349   case VG_STROKE_MITER_LIMIT:
350     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
351     context->strokeMiterLimit = SH_MAX(fvalue, 1.0f);
352     break;
353     
354   case VG_STROKE_DASH_PHASE:
355     SH_RETURN_ERR_IF(count!=1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
356     context->strokeDashPhase = fvalue;
357     break;
358     
359   case VG_STROKE_DASH_PATTERN:
360     
361     /* TODO: limit by the VG_MAX_DASH_COUNT value */
362     shFloatArrayClear(&context->strokeDashPattern);
363     for (i=0; i<count; ++i)
364       shFloatArrayPushBack(&context->strokeDashPattern,
365                            shParamToFloat(values, floats, i));
366     break;
367   case VG_TILE_FILL_COLOR:
368     
369     SH_RETURN_ERR_IF(count!=4, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
370     CSET(context->tileFillColor,
371          shParamToFloat(values, floats, 0),
372          shParamToFloat(values, floats, 1),
373          shParamToFloat(values, floats, 2),
374          shParamToFloat(values, floats, 3));
375     
376     break;
377   case VG_CLEAR_COLOR:
378     
379     SH_RETURN_ERR_IF(count!=4, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
380     CSET(context->clearColor,
381          shParamToFloat(values, floats, 0),
382          shParamToFloat(values, floats, 1),
383          shParamToFloat(values, floats, 2),
384          shParamToFloat(values, floats, 3));
385     
386     break;
387   case VG_SCISSOR_RECTS:
388     
389     SH_RETURN_ERR_IF(count % 4, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
390     shRectArrayClear(&context->scissor);
391     for (i=0; i<count && i<SH_MAX_SCISSOR_RECTS; i+=4) {
392       SHRectangle r;
393       r.x = shParamToFloat(values, floats, i+0);
394       r.y = shParamToFloat(values, floats, i+1);
395       r.w = shParamToFloat(values, floats, i+2);
396       r.h = shParamToFloat(values, floats, i+3);
397       shRectArrayPushBackP(&context->scissor, &r);
398     }
399     
400     break;
401     
402   case VG_MAX_SCISSOR_RECTS:
403   case VG_MAX_DASH_COUNT:
404   case VG_MAX_KERNEL_SIZE:
405   case VG_MAX_SEPARABLE_KERNEL_SIZE:
406   case VG_MAX_COLOR_RAMP_STOPS:
407   case VG_MAX_IMAGE_WIDTH:
408   case VG_MAX_IMAGE_HEIGHT:
409   case VG_MAX_IMAGE_PIXELS:
410   case VG_MAX_IMAGE_BYTES:
411   case VG_MAX_FLOAT:
412   case VG_MAX_GAUSSIAN_STD_DEVIATION:
413     /* Read-only */ break;
414     
415   default:
416     /* Invalid VGParamType */
417     SH_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
418   }
419   
420   SH_RETURN(SH_NO_RETVAL);
421 }
422
423 /*--------------------------------------------------
424  * Sets a parameter of a single integer value
425  *--------------------------------------------------*/
426
427 VG_API_CALL void vgSetf (VGParamType type, VGfloat value)
428 {
429   VG_GETCONTEXT(VG_NO_RETVAL);
430   
431   /* Check if target vector */
432   VG_RETURN_ERR_IF(shIsParamVector(type),
433                    VG_ILLEGAL_ARGUMENT_ERROR,
434                    VG_NO_RETVAL);
435   
436   /* Error code will be set by shSet */
437   shSet(context, type, 1, &value, 1);
438   VG_RETURN(VG_NO_RETVAL);
439 }
440
441 /*--------------------------------------------------
442  * Sets a parameter of a single float value
443  *--------------------------------------------------*/
444
445 VG_API_CALL void vgSeti (VGParamType type, VGint value)
446 {
447   VG_GETCONTEXT(VG_NO_RETVAL);
448   
449   /* Check if target vector */
450   VG_RETURN_ERR_IF(shIsParamVector(type),
451                    VG_ILLEGAL_ARGUMENT_ERROR,
452                    VG_NO_RETVAL);
453   
454   /* Error code will be set by shSet */
455   shSet(context, type, 1, &value, 0);
456   VG_RETURN(VG_NO_RETVAL);
457 }
458
459 /*-------------------------------------------------------
460  * Sets a parameter which takes a vector of float values
461  *-------------------------------------------------------*/
462
463 VG_API_CALL void vgSetfv(VGParamType type, VGint count,
464                          const VGfloat * values)
465 {
466   VG_GETCONTEXT(VG_NO_RETVAL);
467   
468   /* TODO: check input array alignment */
469   
470   /* Error code will be set by shSet */
471   shSet(context, type, count, values, 1);
472   VG_RETURN(VG_NO_RETVAL);
473 }
474
475 /*---------------------------------------------------------
476  * Sets a parameter which takes a vector of integer values
477  *---------------------------------------------------------*/
478
479 VG_API_CALL void vgSetiv(VGParamType type, VGint count,
480                          const VGint * values)
481 {
482   VG_GETCONTEXT(VG_NO_RETVAL);
483   
484   /* TODO: check input array alignment */
485   
486   /* Error code wil be set by shSet */
487   shSet(context, type, count, values, 0);
488   VG_RETURN(VG_NO_RETVAL);
489 }
490
491 /*---------------------------------------------------------
492  * Outputs a parameter by interpreting the output value
493  * vector according to the parameter type and input type.
494  *---------------------------------------------------------*/
495
496 static void shGet(VGContext *context, VGParamType type, SHint count, void *values, SHint floats)
497 {
498   int i;
499   
500   /* Check for invalid array / count */
501   SH_RETURN_ERR_IF(!values || count<=0, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
502   
503   switch (type)
504   {
505   case VG_MATRIX_MODE:
506     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
507     shIntToParam((SHint)context->matrixMode, count, values, floats, 0);
508     break;
509     
510   case VG_FILL_RULE:
511     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
512     shIntToParam((SHint)context->fillRule, count, values, floats, 0);
513     break;
514     
515   case VG_IMAGE_QUALITY:
516     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
517     shIntToParam((SHint)context->imageQuality, count, values, floats, 0);
518     break;
519     
520   case VG_RENDERING_QUALITY:
521     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
522     shIntToParam((SHint)context->renderingQuality, count, values, floats, 0);
523     break;
524     
525   case VG_BLEND_MODE:
526     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
527     shIntToParam((SHint)context->blendMode, count, values, floats, 0);
528     break;
529     
530   case VG_IMAGE_MODE:
531     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
532     shIntToParam((SHint)context->imageMode, count, values, floats, 0);
533     break;
534     
535   case VG_STROKE_CAP_STYLE:
536     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
537     shIntToParam((SHint)context->strokeCapStyle, count, values, floats, 0);
538     break;
539     
540   case VG_STROKE_JOIN_STYLE:
541     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
542     shIntToParam((SHint)context->strokeJoinStyle, count, values, floats, 0);
543     break;
544     
545   case VG_PIXEL_LAYOUT:
546     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
547     shIntToParam((SHint)context->pixelLayout, count, values, floats, 0);
548     break;
549     
550   case VG_FILTER_CHANNEL_MASK:
551     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
552     shIntToParam((SHint)context->filterChannelMask, count, values, floats, 0);
553     break;
554     
555   case VG_FILTER_FORMAT_LINEAR:
556     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
557     shIntToParam((SHint)context->filterFormatLinear, count, values, floats, 0);
558     break;
559     
560   case VG_FILTER_FORMAT_PREMULTIPLIED:
561     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
562     shIntToParam((SHint)context->filterFormatPremultiplied, count, values, floats, 0);
563     break;
564     
565   case VG_STROKE_DASH_PHASE_RESET:
566     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
567     shIntToParam((SHint)context->strokeDashPhaseReset, count, values, floats, 0);
568     break;
569     
570   case VG_MASKING:
571     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
572     shIntToParam((SHint)context->masking, count, values, floats, 0);
573     break;
574     
575   case VG_SCISSORING:
576     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
577     shIntToParam((SHint)context->scissoring, count, values, floats, 0);
578     break;
579     
580   case VG_STROKE_LINE_WIDTH:
581     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
582     shFloatToParam(context->strokeLineWidth, count, values, floats, 0);
583     break;
584     
585   case VG_STROKE_MITER_LIMIT:
586     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
587     shFloatToParam(context->strokeMiterLimit, count, values, floats, 0);
588     break;
589     
590   case VG_STROKE_DASH_PHASE:
591     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
592     shFloatToParam(context->strokeDashPhase, count, values, floats, 0);
593     break;
594     
595   case VG_STROKE_DASH_PATTERN:
596     
597     SH_RETURN_ERR_IF(count > context->strokeDashPattern.size,
598                      VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
599     
600     for (i=0; i<context->strokeDashPattern.size; ++i)
601       shFloatToParam(context->strokeDashPattern.items[i],
602                      count, values, floats, i);
603     
604     break;
605   case VG_TILE_FILL_COLOR:
606     
607     SH_RETURN_ERR_IF(count > 4, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
608     shFloatToParam(context->tileFillColor.r, count, values, floats, 0);
609     shFloatToParam(context->tileFillColor.g, count, values, floats, 1);
610     shFloatToParam(context->tileFillColor.b, count, values, floats, 2);
611     shFloatToParam(context->tileFillColor.a, count, values, floats, 3);
612     
613     break;
614   case VG_CLEAR_COLOR:
615     
616     SH_RETURN_ERR_IF(count > 4, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
617     shFloatToParam(context->clearColor.r, count, values, floats, 0);
618     shFloatToParam(context->clearColor.g, count, values, floats, 1);
619     shFloatToParam(context->clearColor.b, count, values, floats, 2);
620     shFloatToParam(context->clearColor.a, count, values, floats, 3);
621     
622     break;
623   case VG_SCISSOR_RECTS:
624     
625     SH_RETURN_ERR_IF(count > context->scissor.size * 4,
626                      VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
627     
628     for (i=0; i<context->scissor.size; ++i) {
629       shIntToParam((SHint)context->scissor.items[i].x, count, values, floats, i*4+0);
630       shIntToParam((SHint)context->scissor.items[i].y, count, values, floats, i*4+1);
631       shIntToParam((SHint)context->scissor.items[i].w, count, values, floats, i*4+2);
632       shIntToParam((SHint)context->scissor.items[i].h, count, values, floats, i*4+3);
633     }
634     
635     break;
636     
637   case VG_MAX_SCISSOR_RECTS:
638     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
639     shIntToParam(SH_MAX_SCISSOR_RECTS, count, values, floats, 0);
640     break;
641     
642   case VG_MAX_DASH_COUNT:
643     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
644     shIntToParam(SH_MAX_DASH_COUNT, count, values, floats, 0);
645     break;
646     
647   case VG_MAX_COLOR_RAMP_STOPS:
648     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
649     shIntToParam(SH_MAX_COLOR_RAMP_STOPS, count, values, floats, 0);
650     break;
651     
652   case VG_MAX_IMAGE_WIDTH:
653     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
654     shIntToParam(SH_MAX_IMAGE_WIDTH, count, values, floats, 0);
655     break;
656     
657   case VG_MAX_IMAGE_HEIGHT:
658     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
659     shIntToParam(SH_MAX_IMAGE_WIDTH, count, values, floats, 0);
660     break;
661     
662   case VG_MAX_IMAGE_PIXELS:
663     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
664     shIntToParam(SH_MAX_IMAGE_HEIGHT, count, values, floats, 0);
665     break;
666     
667   case VG_MAX_IMAGE_BYTES:
668     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
669     shIntToParam(SH_MAX_IMAGE_BYTES, count, values, floats, 0);
670     break;
671     
672   case VG_MAX_FLOAT:
673     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
674     shFloatToParam(getMaxFloat(), count, values, floats, 0);
675     break;
676     
677   case VG_MAX_KERNEL_SIZE: /* TODO: depends on convolution implementation */
678     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
679     shIntToParam(0, count, values, floats, 0);
680     break;
681     
682   case VG_MAX_SEPARABLE_KERNEL_SIZE: /* TODO: depends on convolution implementation */
683     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
684     shIntToParam(0, count, values, floats, 0);
685     break;
686     
687   case VG_MAX_GAUSSIAN_STD_DEVIATION: /* TODO: depends on gaussian blur implementation */
688     SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
689     shFloatToParam(0.0f, count, values, floats, 0);
690     break;
691     
692   default:
693     /* Invalid VGParamType */
694     SH_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
695   }
696   
697   SH_RETURN(SH_NO_RETVAL);
698 }
699
700 /*---------------------------------------------------------
701  * Returns a parameter of a single float value
702  *---------------------------------------------------------*/
703
704 VG_API_CALL VGfloat vgGetf(VGParamType type)
705 {
706   VGfloat retval = 0.0f;
707   VG_GETCONTEXT(retval);
708   
709   /* Check if target vector */
710   VG_RETURN_ERR_IF(shIsParamVector(type),
711                    VG_ILLEGAL_ARGUMENT_ERROR,
712                    retval);
713   
714   /* Error code will be set by shGet */
715   shGet(context, type, 1, &retval, 1);
716   VG_RETURN(retval);
717 }
718
719 /*---------------------------------------------------------
720  * Returns a parameter of a single integer value
721  *---------------------------------------------------------*/
722
723 VG_API_CALL VGint vgGeti(VGParamType type)
724 {
725   VGint retval = 0;
726   VG_GETCONTEXT(retval);
727   
728   /* Check if target vector */
729   VG_RETURN_ERR_IF(shIsParamVector(type),
730                    VG_ILLEGAL_ARGUMENT_ERROR,
731                    retval);
732   
733   /* Error code will be set by shGet */
734   shGet(context, type, 1, &retval, 0);
735   VG_RETURN(retval);
736 }
737
738 /*---------------------------------------------------------
739  * Outputs a parameter of a float vector value
740  *---------------------------------------------------------*/
741
742 VG_API_CALL void vgGetfv(VGParamType type, VGint count, VGfloat * values)
743 {
744   VG_GETCONTEXT(VG_NO_RETVAL);
745   
746   /* TODO: check output array alignment */
747   
748   /* Error code will be set by shGet */
749   shGet(context, type, count, values, 1);
750   VG_RETURN(VG_NO_RETVAL);
751 }
752
753 /*---------------------------------------------------------
754  * Outputs a parameter of an integer vector value
755  *---------------------------------------------------------*/
756
757 VG_API_CALL void vgGetiv(VGParamType type, VGint count, VGint * values)
758 {
759   VG_GETCONTEXT(VG_NO_RETVAL);
760   
761   /* TODO: check output array alignment */
762   
763   /* Error code will be set by shGet */
764   shGet(context, type, count, values, 0);
765   VG_RETURN(VG_NO_RETVAL);
766 }
767
768 /*---------------------------------------------------------
769  * Returns the size of the output array required to
770  * receive the whole vector of parameter values
771  *---------------------------------------------------------*/
772
773 VG_API_CALL VGint vgGetVectorSize(VGParamType type)
774 {
775   int retval = 0;
776   VG_GETCONTEXT(retval);
777   
778   switch(type)
779   {
780   case VG_MATRIX_MODE:
781   case VG_FILL_RULE:
782   case VG_IMAGE_QUALITY:
783   case VG_RENDERING_QUALITY:
784   case VG_BLEND_MODE:
785   case VG_IMAGE_MODE:
786   case VG_STROKE_CAP_STYLE:
787   case VG_STROKE_JOIN_STYLE:
788   case VG_PIXEL_LAYOUT:
789   case VG_FILTER_CHANNEL_MASK:
790   case VG_FILTER_FORMAT_LINEAR:
791   case VG_FILTER_FORMAT_PREMULTIPLIED:
792   case VG_STROKE_DASH_PHASE_RESET:
793   case VG_MASKING:
794   case VG_SCISSORING:
795   case VG_STROKE_LINE_WIDTH:
796   case VG_STROKE_MITER_LIMIT:
797   case VG_STROKE_DASH_PHASE:
798   case VG_MAX_SCISSOR_RECTS:
799   case VG_MAX_DASH_COUNT:
800   case VG_MAX_KERNEL_SIZE:
801   case VG_MAX_SEPARABLE_KERNEL_SIZE:
802   case VG_MAX_COLOR_RAMP_STOPS:
803   case VG_MAX_IMAGE_WIDTH:
804   case VG_MAX_IMAGE_HEIGHT:
805   case VG_MAX_IMAGE_PIXELS:
806   case VG_MAX_IMAGE_BYTES:
807   case VG_MAX_FLOAT:
808   case VG_MAX_GAUSSIAN_STD_DEVIATION:
809     retval = 1;
810     break;
811     
812   case VG_TILE_FILL_COLOR:
813   case VG_CLEAR_COLOR:
814     retval = 4;
815     break;
816     
817   case VG_STROKE_DASH_PATTERN:
818     retval = context->strokeDashPattern.size;
819     break;
820     
821   case VG_SCISSOR_RECTS:
822     retval = context->scissor.size * 4;
823     break;
824     
825   default:
826     /* Invalid VGParamType */
827     VG_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, retval);
828   }
829   
830   VG_RETURN(retval);
831 }
832
833 /*-----------------------------------------------------------
834  * Sets a resource parameter by interpreting the input value
835  * vector according to the parameter type and input type.
836  *-----------------------------------------------------------*/
837
838 static void shSetParameter(VGContext *context, VGHandle object,
839                            SHResourceType rtype, VGint ptype,
840                            SHint count, const void *values, SHint floats)
841 {
842 //  SHfloat fvalue = 0.0f;
843   SHint ivalue = 0;
844 //  VGboolean bvalue = VG_FALSE;
845   int i;
846   
847   /* Check for negative count */
848   SH_RETURN_ERR_IF(count<0, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
849   
850   /* Check for empty vector */
851   SH_RETURN_ERR_IF(!values && count!=0, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
852   
853   /* Pre-convert first value for non-vector params */
854   if (count == 1) {
855 //    fvalue = shParamToFloat(values, floats, 0);
856     ivalue = shParamToInt(values, floats, 0);
857 //    bvalue = (ivalue ? VG_TRUE : VG_FALSE);
858   }
859   
860   switch (rtype)
861   {
862   case SH_RESOURCE_PATH: switch (ptype) { /* Path parameters */
863       
864     case VG_PATH_FORMAT:
865     case VG_PATH_DATATYPE:
866     case VG_PATH_SCALE:
867     case VG_PATH_BIAS:
868     case VG_PATH_NUM_SEGMENTS:
869     case VG_PATH_NUM_COORDS:
870       /* Read-only */ break;
871       
872     default:
873       /* Invalid VGParamType */
874       SH_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
875       
876     } break;
877   case SH_RESOURCE_PAINT: switch (ptype) { /* Paint parameters */
878       
879     case VG_PAINT_TYPE:
880       SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
881       SH_RETURN_ERR_IF(!shIsEnumValid(ptype,ivalue), VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
882       ((SHPaint*)object)->type = (VGPaintType)ivalue;
883       break;
884       
885     case VG_PAINT_COLOR:
886       SH_RETURN_ERR_IF(count != 4, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
887       ((SHPaint*)object)->color.r = shParamToFloat(values, floats, 0);
888       ((SHPaint*)object)->color.g = shParamToFloat(values, floats, 1);
889       ((SHPaint*)object)->color.b = shParamToFloat(values, floats, 2);
890       ((SHPaint*)object)->color.a = shParamToFloat(values, floats, 3);
891       break;
892       
893     case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
894       SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
895       SH_RETURN_ERR_IF(!shIsEnumValid(ptype,ivalue), VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
896       ((SHPaint*)object)->spreadMode = (VGColorRampSpreadMode)ivalue;
897       break;
898       
899     case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
900       SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
901       SH_RETURN_ERR_IF(!shIsEnumValid(ptype,ivalue), VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
902       ((SHPaint*)object)->premultiplied = (VGboolean)ivalue;
903       break;
904       
905     case VG_PAINT_COLOR_RAMP_STOPS: {
906         
907         int max; SHPaint *paint; SHStop stop;
908         SH_RETURN_ERR_IF(count % 5, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
909         max  = SH_MIN(count, SH_MAX_COLOR_RAMP_STOPS * 5);
910         paint = (SHPaint*)object;
911         shStopArrayClear(&paint->instops);
912         
913         for (i=0; i<max; i+=5) {
914           stop.offset = shParamToFloat(values, floats, i+0);
915           CSET(stop.color,
916                shParamToFloat(values, floats, i+1),
917                shParamToFloat(values, floats, i+2),
918                shParamToFloat(values, floats, i+3),
919                shParamToFloat(values, floats, i+4));
920           shStopArrayPushBackP(&paint->instops, &stop); }
921         
922         shValidateInputStops(paint);
923         break;}
924       
925     case VG_PAINT_LINEAR_GRADIENT:
926       SH_RETURN_ERR_IF(count != 4, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
927       for (i=0; i<4; ++i)
928         ((SHPaint*)object)->linearGradient[i] = shParamToFloat(values, floats, i);
929       break;
930       
931     case VG_PAINT_RADIAL_GRADIENT:
932       SH_RETURN_ERR_IF(count != 5, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
933       for (i=0; i<5; ++i)
934         ((SHPaint*)object)->radialGradient[i] = shParamToFloat(values, floats, i);
935       break;
936       
937     case VG_PAINT_PATTERN_TILING_MODE:
938       SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
939       SH_RETURN_ERR_IF(!shIsEnumValid(ptype,ivalue), VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
940       ((SHPaint*)object)->tilingMode = (VGTilingMode)ivalue;
941       break;
942       
943     default:
944       /* Invalid VGParamType */
945       SH_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
946     
947     } break;
948   case SH_RESOURCE_IMAGE: switch (ptype) {/* Image parameters */
949       
950     case VG_IMAGE_FORMAT:
951     case VG_IMAGE_WIDTH:
952     case VG_IMAGE_HEIGHT:
953       /* Read-only */ break;
954       
955     default:
956       /* Invalid VGParamType */
957       SH_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
958       
959     } break;
960     
961   default:
962     /* Invalid resource handle */
963     SH_ASSERT(rtype!=SH_RESOURCE_INVALID);
964     break;
965   }
966   
967   SH_RETURN(SH_NO_RETVAL);
968 }
969
970 /*------------------------------------------------------------
971  * Sets a resource parameter which takes a single float value
972  *------------------------------------------------------------*/
973
974 VG_API_CALL void vgSetParameterf(VGHandle object, VGint paramType, VGfloat value)
975 {
976   SHResourceType resType;
977   VG_GETCONTEXT(VG_NO_RETVAL);
978   
979   /* Validate object */
980   resType = shGetResourceType(context, object);
981   VG_RETURN_ERR_IF(resType == SH_RESOURCE_INVALID,
982                    VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
983   
984   /* Check if param vector */
985   VG_RETURN_ERR_IF(shIsParamVector(paramType),
986                    VG_ILLEGAL_ARGUMENT_ERROR,
987                    VG_NO_RETVAL);
988   
989   /* Error code will be set by shSetParam() */
990   shSetParameter(context, object, resType, paramType, 1, &value, 1);
991   VG_RETURN(VG_NO_RETVAL);
992 }
993
994 /*--------------------------------------------------------------
995  * Sets a resource parameter which takes a single integer value
996  *--------------------------------------------------------------*/
997
998 VG_API_CALL void vgSetParameteri(VGHandle object, VGint paramType, VGint value)
999 {
1000   SHResourceType resType;
1001   VG_GETCONTEXT(VG_NO_RETVAL);
1002   
1003   /* Validate object */
1004   resType = shGetResourceType(context, object);
1005   VG_RETURN_ERR_IF(resType == SH_RESOURCE_INVALID,
1006                    VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
1007   
1008   /* Check if param vector */
1009   VG_RETURN_ERR_IF(shIsParamVector(paramType),
1010                    VG_ILLEGAL_ARGUMENT_ERROR,
1011                    VG_NO_RETVAL);
1012   
1013   /* Error code will be set by shSetParam() */
1014   shSetParameter(context, object, resType, paramType, 1, &value, 0);
1015   VG_RETURN(VG_NO_RETVAL);
1016 }
1017
1018 /*----------------------------------------------------------------
1019  * Sets a resource parameter which takes a vector of float values
1020  *----------------------------------------------------------------*/
1021
1022 VG_API_CALL void vgSetParameterfv(VGHandle object, VGint paramType,
1023                                   VGint count, const VGfloat * values)
1024 {
1025   SHResourceType resType;
1026   VG_GETCONTEXT(VG_NO_RETVAL);
1027   
1028   /* Validate object */
1029   resType = shGetResourceType(context, object);
1030   VG_RETURN_ERR_IF(resType == SH_RESOURCE_INVALID,
1031                    VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
1032   
1033   /* TODO: Check for input array alignment */
1034   
1035   /* Error code will be set by shSetParam() */
1036   shSetParameter(context, object, resType, paramType, count, values, 1);
1037   VG_RETURN(VG_NO_RETVAL);
1038 }
1039
1040 /*------------------------------------------------------------------
1041  * Sets a resource parameter which takes a vector of integer values
1042  *------------------------------------------------------------------*/
1043
1044 VG_API_CALL void vgSetParameteriv(VGHandle object, VGint paramType,
1045                                   VGint count, const VGint * values)
1046 {
1047   SHResourceType resType;
1048   VG_GETCONTEXT(VG_NO_RETVAL);
1049   
1050   /* Validate object */
1051   resType = shGetResourceType(context, object);
1052   VG_RETURN_ERR_IF(resType == SH_RESOURCE_INVALID,
1053                    VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
1054   
1055   /* TODO: Check for input array alignment */
1056   
1057   /* Error code will be set by shSetParam() */
1058   shSetParameter(context, object, resType, paramType, count, values, 0);
1059   VG_RETURN(VG_NO_RETVAL);
1060 }
1061
1062 /*---------------------------------------------------------------
1063  * Outputs a resource parameter by interpreting the output value
1064  * vector according to the parameter type and input type.
1065  *---------------------------------------------------------------*/
1066
1067 static void shGetParameter(VGContext *context, VGHandle object,
1068                            SHResourceType rtype, VGint ptype,
1069                            SHint count, void *values, SHint floats)
1070 {
1071   int i;
1072   
1073   /* Check for invalid array / count */
1074   SH_RETURN_ERR_IF(!values || count<=0, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1075   
1076   switch (rtype)
1077   {
1078   case SH_RESOURCE_PATH: switch (ptype) { /* Path parameters */
1079       
1080     case VG_PATH_FORMAT:
1081       SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1082       shIntToParam(((SHPath*)object)->format, count, values, floats, 0);
1083       break;
1084       
1085     case VG_PATH_DATATYPE:
1086       SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1087       shIntToParam(((SHPath*)object)->datatype, count, values, floats, 0);
1088       break;
1089       
1090     case VG_PATH_SCALE:
1091       SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1092       shFloatToParam(((SHPath*)object)->scale, count, values, floats, 0);
1093       break;
1094       
1095     case VG_PATH_BIAS:
1096       SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1097       shFloatToParam(((SHPath*)object)->bias, count, values, floats, 0);
1098       break;
1099       
1100     case VG_PATH_NUM_SEGMENTS:
1101       SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1102       shIntToParam(((SHPath*)object)->segCount, count, values, floats, 0);
1103       break;
1104       
1105     case VG_PATH_NUM_COORDS:
1106       SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1107       shIntToParam(((SHPath*)object)->dataCount, count, values, floats, 0);
1108       break;
1109       
1110     default:
1111       /* Invalid VGParamType */
1112       SH_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1113       
1114     } break;
1115   case SH_RESOURCE_PAINT: switch (ptype) { /* Paint parameters */
1116       
1117     case VG_PAINT_TYPE:
1118       SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1119       shIntToParam(((SHPaint*)object)->type, count, values, floats, 0);
1120       break;
1121       
1122     case VG_PAINT_COLOR:
1123       SH_RETURN_ERR_IF(count > 4, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1124       shFloatToParam(((SHPaint*)object)->color.r, count, values, floats, 0);
1125       shFloatToParam(((SHPaint*)object)->color.g, count, values, floats, 1);
1126       shFloatToParam(((SHPaint*)object)->color.b, count, values, floats, 2);
1127       shFloatToParam(((SHPaint*)object)->color.a, count, values, floats, 3);
1128       break;
1129       
1130     case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
1131       SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1132       shIntToParam(((SHPaint*)object)->spreadMode, count, values, floats, 0);
1133       break;
1134       
1135     case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
1136       SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1137       shIntToParam(((SHPaint*)object)->spreadMode, count, values, floats, 0);
1138       break;
1139       
1140     case VG_PAINT_COLOR_RAMP_STOPS:{
1141         
1142         int i; SHPaint* paint = (SHPaint*)object; SHStop *stop;
1143         SH_RETURN_ERR_IF(count > paint->stops.size * 5,
1144                          VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1145         
1146         for (i=0; i<paint->stops.size; ++i) {
1147           stop = &paint->stops.items[i];
1148           shFloatToParam(stop->offset, count, values, floats, i*5+0);
1149           shFloatToParam(stop->color.r, count, values, floats, i*5+1);
1150           shFloatToParam(stop->color.g, count, values, floats, i*5+2);
1151           shFloatToParam(stop->color.b, count, values, floats, i*5+3);
1152           shFloatToParam(stop->color.a, count, values, floats, i*5+4);
1153         }
1154         
1155         break;}
1156       
1157     case VG_PAINT_LINEAR_GRADIENT:
1158       SH_RETURN_ERR_IF(count > 4, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1159       for (i=0; i<4; ++i)
1160         shFloatToParam(((SHPaint*)object)->linearGradient[i],
1161                         count, values, floats, i);
1162       break;
1163       
1164     case VG_PAINT_RADIAL_GRADIENT:
1165       SH_RETURN_ERR_IF(count > 5, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1166       for (i=0; i<5; ++i)
1167         shFloatToParam(((SHPaint*)object)->radialGradient[i],
1168                        count, values, floats, i);
1169       break;
1170       
1171     case VG_PAINT_PATTERN_TILING_MODE:
1172       SH_RETURN_ERR_IF(count != 1, VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1173       shIntToParam(((SHPaint*)object)->tilingMode, count, values, floats, 0);
1174       break;
1175       
1176     default:
1177       /* Invalid VGParamType */
1178       SH_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1179       
1180     } break;
1181   case SH_RESOURCE_IMAGE: switch (ptype) { /* Image parameters */
1182       
1183       /* TODO: output image parameters when image implemented */
1184     case VG_IMAGE_FORMAT:
1185       break;
1186       
1187     case VG_IMAGE_WIDTH:
1188       break;
1189       
1190     case VG_IMAGE_HEIGHT:
1191       break;
1192       
1193     default:
1194       /* Invalid VGParamType */
1195       SH_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, SH_NO_RETVAL);
1196       
1197     } break;
1198     
1199   default:
1200     /* Invalid resource handle */
1201     SH_ASSERT(rtype!=SH_RESOURCE_INVALID);
1202     break;
1203   }
1204   
1205   SH_RETURN(SH_NO_RETVAL);
1206 }
1207
1208 /*----------------------------------------------------------
1209  * Returns a resource parameter of a single float value
1210  *----------------------------------------------------------*/
1211
1212 VG_API_CALL VGfloat vgGetParameterf(VGHandle object, VGint paramType)
1213 {
1214   VGfloat retval = 0.0f;
1215   SHResourceType resType;
1216   VG_GETCONTEXT(retval);
1217   
1218   /* Validate object */
1219   resType = shGetResourceType(context, object);
1220   VG_RETURN_ERR_IF(resType == SH_RESOURCE_INVALID,
1221                    VG_BAD_HANDLE_ERROR, retval);
1222   
1223   /* Check if param vector */
1224   VG_RETURN_ERR_IF(shIsParamVector(paramType),
1225                    VG_ILLEGAL_ARGUMENT_ERROR, retval);
1226   
1227   /* Error code will be set by shGetParameter() */
1228   shGetParameter(context, object, resType, paramType, 1, &retval, 1);
1229   VG_RETURN(retval);
1230 }
1231
1232 /*----------------------------------------------------------
1233  * Returns a resource parameter of a single integer value
1234  *----------------------------------------------------------*/
1235
1236 VG_API_CALL VGint vgGetParameteri(VGHandle object, VGint paramType)
1237 {
1238   VGint retval = 0;
1239   SHResourceType resType;
1240   VG_GETCONTEXT(retval);
1241   
1242   /* Validate object */
1243   resType = shGetResourceType(context, object);
1244   VG_RETURN_ERR_IF(resType == SH_RESOURCE_INVALID,
1245                    VG_BAD_HANDLE_ERROR, retval);
1246   
1247   /* Check if param vector */
1248   VG_RETURN_ERR_IF(shIsParamVector(paramType),
1249                    VG_ILLEGAL_ARGUMENT_ERROR, retval);
1250   
1251   /* Error code will be set by shGetParameter() */
1252   shGetParameter(context, object, resType, paramType, 1, &retval, 0);
1253   VG_RETURN(retval);
1254 }
1255
1256 /*----------------------------------------------------------
1257  * Outputs a resource parameter of a float vector value
1258  *----------------------------------------------------------*/
1259
1260 VG_API_CALL void vgGetParameterfv(VGHandle object, VGint paramType,
1261                                   VGint count, VGfloat * values)
1262 {
1263   SHResourceType resType;
1264   VG_GETCONTEXT(VG_NO_RETVAL);
1265   
1266   /* Validate object */
1267   resType = shGetResourceType(context, object);
1268   VG_RETURN_ERR_IF(resType == SH_RESOURCE_INVALID,
1269                    VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
1270   
1271   /* TODO: Check output array alignment */
1272   
1273   /* Error code will be set by shGetParameter() */
1274   shGetParameter(context, object, resType, paramType, count, values, 1);
1275   VG_RETURN(VG_NO_RETVAL);
1276 }
1277
1278 /*----------------------------------------------------------
1279  * Outputs a resource parameter of an integer vector value
1280  *----------------------------------------------------------*/
1281
1282 VG_API_CALL void vgGetParameteriv(VGHandle object, VGint paramType,
1283                                   VGint count, VGint * values)
1284 {
1285   SHResourceType resType;
1286   VG_GETCONTEXT(VG_NO_RETVAL);
1287   
1288   /* Validate object */
1289   resType = shGetResourceType(context, object);
1290   VG_RETURN_ERR_IF(resType == SH_RESOURCE_INVALID,
1291                    VG_BAD_HANDLE_ERROR, VG_NO_RETVAL);
1292   
1293   /* TODO: Check output array alignment */
1294   
1295   /* Error code will be set by shGetParameter() */
1296   shGetParameter(context, object, resType, paramType, count, values, 0);
1297   VG_RETURN(VG_NO_RETVAL);
1298 }
1299
1300 /*---------------------------------------------------------
1301  * Returns the size of the output array required to
1302  * receive the whole vector of resource parameter values
1303  *---------------------------------------------------------*/
1304   
1305 VG_API_CALL VGint vgGetParameterVectorSize(VGHandle object, VGint ptype)
1306 {
1307   int retval = 0;
1308   SHResourceType rtype;
1309   VG_GETCONTEXT(retval);
1310   
1311   /* Validate object */
1312   rtype = shGetResourceType(context, object);
1313   VG_RETURN_ERR_IF(rtype == SH_RESOURCE_INVALID,
1314                    VG_BAD_HANDLE_ERROR, retval);
1315   
1316   switch (rtype)
1317   {
1318   case SH_RESOURCE_PATH: switch (ptype) { /* Path parameters */
1319       
1320     case VG_PATH_FORMAT:
1321     case VG_PATH_DATATYPE:
1322     case VG_PATH_SCALE:
1323     case VG_PATH_BIAS:
1324     case VG_PATH_NUM_SEGMENTS:
1325     case VG_PATH_NUM_COORDS:
1326       retval = 1; break;
1327       
1328     default:
1329       /* Invalid VGParamType */
1330       VG_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, retval);
1331       
1332     } break;
1333   case SH_RESOURCE_PAINT: switch (ptype) { /* Paint parameters */
1334       
1335     case VG_PAINT_TYPE:
1336       retval = 1; break;
1337       
1338     case VG_PAINT_COLOR:
1339       retval = 4; break;
1340       
1341     case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
1342       retval = 1; break;
1343       
1344     case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
1345       retval = 1; break;
1346       
1347     case VG_PAINT_COLOR_RAMP_STOPS:
1348       retval = ((SHPaint*)object)->stops.size*5; break;
1349       
1350     case VG_PAINT_LINEAR_GRADIENT:
1351       retval = 4; break;
1352       
1353     case VG_PAINT_RADIAL_GRADIENT:
1354       retval = 5; break;
1355       
1356     case VG_PAINT_PATTERN_TILING_MODE:
1357       retval = 1; break;
1358       
1359     default:
1360       /* Invalid VGParamType */
1361       VG_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, retval);
1362       
1363     } break;
1364   case SH_RESOURCE_IMAGE: switch (ptype) { /* Image parameters */
1365       
1366     case VG_IMAGE_FORMAT:
1367     case VG_IMAGE_WIDTH:
1368     case VG_IMAGE_HEIGHT:
1369       retval = 1; break;
1370       
1371     default:
1372       /* Invalid VGParamType */
1373       VG_RETURN_ERR(VG_ILLEGAL_ARGUMENT_ERROR, retval);
1374       
1375     } break;
1376     
1377   default:
1378     /* Invalid resource handle */
1379     SH_ASSERT(rtype!=SH_RESOURCE_INVALID);
1380     break;
1381   }
1382   
1383   VG_RETURN(retval);
1384 }
1385
1386 VG_API_CALL const VGubyte * vgGetString(VGStringID name)
1387 {
1388   VG_GETCONTEXT(NULL);
1389   
1390   switch(name) {
1391   case VG_VENDOR:
1392     VG_RETURN((const VGubyte*)context->vendor);
1393   case VG_RENDERER:
1394     VG_RETURN((const VGubyte*)context->renderer);
1395   case VG_VERSION:
1396     VG_RETURN((const VGubyte*)context->version);
1397   case VG_EXTENSIONS:
1398     VG_RETURN((const VGubyte*)context->extensions);
1399   default:
1400     VG_RETURN(NULL);
1401   }
1402 }