1/**************************************************************************
2 *
3 * Copyright 2009 VMware, Inc.  All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a
6 * copy of this software and associated documentation files (the
7 * "Software"), to deal in the Software without restriction, including
8 * without limitation the rights to use, copy, modify, merge, publish,
9 * distribute, sub license, and/or sell copies of the Software, and to
10 * permit persons to whom the Software is furnished to do so, subject to
11 * the following conditions:
12 *
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
15 * of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24 *
25 **************************************************************************/
26
27#include "VG/openvg.h"
28
29#include "vg_context.h"
30#include "paint.h"
31#include "path.h"
32#include "handle.h"
33#include "image.h"
34#include "text.h"
35#include "matrix.h"
36#include "api_consts.h"
37#include "api.h"
38
39#include "pipe/p_compiler.h"
40#include "util/u_pointer.h"
41#include "util/u_math.h"
42
43#include <math.h>
44
45static INLINE struct vg_state *current_state()
46{
47   struct vg_context *ctx = vg_current_context();
48   if (!ctx)
49      return 0;
50   else
51      return &ctx->state.vg;
52}
53
54static INLINE VGboolean count_in_bounds(VGParamType type, VGint count)
55{
56   if (count < 0)
57      return VG_FALSE;
58
59   if (type == VG_SCISSOR_RECTS)
60      return (!(count % 4) && (count >= 0 || count <= VEGA_MAX_SCISSOR_RECTS * 4));
61   else if (type == VG_STROKE_DASH_PATTERN) {
62      return count <= VEGA_MAX_DASH_COUNT;
63   } else {
64      VGint real_count = vegaGetVectorSize(type);
65      return count == real_count;
66   }
67}
68
69void vegaSetf (VGParamType type, VGfloat value)
70{
71   struct vg_context *ctx = vg_current_context();
72   struct vg_state *state = current_state();
73   VGErrorCode error = VG_NO_ERROR;
74
75   switch(type) {
76   case VG_MATRIX_MODE:
77   case VG_FILL_RULE:
78   case VG_IMAGE_QUALITY:
79   case VG_RENDERING_QUALITY:
80   case VG_BLEND_MODE:
81   case VG_IMAGE_MODE:
82#ifdef OPENVG_VERSION_1_1
83   case VG_COLOR_TRANSFORM:
84#endif
85   case VG_STROKE_CAP_STYLE:
86   case VG_STROKE_JOIN_STYLE:
87   case VG_STROKE_DASH_PHASE_RESET:
88   case VG_MASKING:
89   case VG_SCISSORING:
90   case VG_PIXEL_LAYOUT:
91   case VG_SCREEN_LAYOUT:
92   case VG_FILTER_FORMAT_LINEAR:
93   case VG_FILTER_FORMAT_PREMULTIPLIED:
94   case VG_FILTER_CHANNEL_MASK:
95
96   case VG_MAX_SCISSOR_RECTS:
97   case VG_MAX_DASH_COUNT:
98   case VG_MAX_KERNEL_SIZE:
99   case VG_MAX_SEPARABLE_KERNEL_SIZE:
100   case VG_MAX_COLOR_RAMP_STOPS:
101   case VG_MAX_IMAGE_WIDTH:
102   case VG_MAX_IMAGE_HEIGHT:
103   case VG_MAX_IMAGE_PIXELS:
104   case VG_MAX_IMAGE_BYTES:
105   case VG_MAX_GAUSSIAN_STD_DEVIATION:
106   case VG_MAX_FLOAT:
107      vegaSeti(type, floor(value));
108      return;
109      break;
110   case VG_STROKE_LINE_WIDTH:
111      state->stroke.line_width.f = value;
112      state->stroke.line_width.i = float_to_int_floor(*((VGuint*)(&value)));
113      break;
114   case VG_STROKE_MITER_LIMIT:
115      state->stroke.miter_limit.f = value;
116      state->stroke.miter_limit.i = float_to_int_floor(*((VGuint*)(&value)));
117      break;
118   case VG_STROKE_DASH_PHASE:
119      state->stroke.dash_phase.f = value;
120      state->stroke.dash_phase.i = float_to_int_floor(*((VGuint*)(&value)));
121      break;
122   default:
123      error = VG_ILLEGAL_ARGUMENT_ERROR;
124      break;
125   }
126   vg_set_error(ctx, error);
127}
128
129void vegaSeti (VGParamType type, VGint value)
130{
131   struct vg_context *ctx = vg_current_context();
132   struct vg_state *state = current_state();
133   VGErrorCode error = VG_NO_ERROR;
134
135   switch(type) {
136   case VG_MATRIX_MODE:
137      if (value < VG_MATRIX_PATH_USER_TO_SURFACE ||
138#ifdef OPENVG_VERSION_1_1
139          value > VG_MATRIX_GLYPH_USER_TO_SURFACE)
140#else
141          value > VG_MATRIX_STROKE_PAINT_TO_USER)
142#endif
143         error = VG_ILLEGAL_ARGUMENT_ERROR;
144      else
145         state->matrix_mode = value;
146      break;
147   case VG_FILL_RULE:
148      if (value < VG_EVEN_ODD ||
149          value > VG_NON_ZERO)
150         error = VG_ILLEGAL_ARGUMENT_ERROR;
151      else
152         state->fill_rule = value;
153      break;
154   case VG_IMAGE_QUALITY:
155      state->image_quality = value;
156      break;
157   case VG_RENDERING_QUALITY:
158      if (value < VG_RENDERING_QUALITY_NONANTIALIASED ||
159          value > VG_RENDERING_QUALITY_BETTER)
160         error = VG_ILLEGAL_ARGUMENT_ERROR;
161      else
162         state->rendering_quality = value;
163      break;
164   case VG_BLEND_MODE:
165      if (value < VG_BLEND_SRC ||
166          value > VG_BLEND_ADDITIVE)
167         error = VG_ILLEGAL_ARGUMENT_ERROR;
168      else {
169         ctx->state.dirty |= BLEND_DIRTY;
170         state->blend_mode = value;
171      }
172      break;
173   case VG_IMAGE_MODE:
174      if (value < VG_DRAW_IMAGE_NORMAL ||
175          value > VG_DRAW_IMAGE_STENCIL)
176         error = VG_ILLEGAL_ARGUMENT_ERROR;
177      else
178         state->image_mode = value;
179      break;
180#ifdef OPENVG_VERSION_1_1
181   case VG_COLOR_TRANSFORM:
182      state->color_transform = value;
183#endif
184      break;
185   case VG_STROKE_LINE_WIDTH:
186      state->stroke.line_width.f = value;
187      state->stroke.line_width.i = value;
188      break;
189   case VG_STROKE_CAP_STYLE:
190      if (value < VG_CAP_BUTT ||
191          value > VG_CAP_SQUARE)
192         error = VG_ILLEGAL_ARGUMENT_ERROR;
193      else
194         state->stroke.cap_style = value;
195      break;
196   case VG_STROKE_JOIN_STYLE:
197      if (value < VG_JOIN_MITER ||
198          value > VG_JOIN_BEVEL)
199         error = VG_ILLEGAL_ARGUMENT_ERROR;
200      else
201         state->stroke.join_style = value;
202      break;
203   case VG_STROKE_MITER_LIMIT:
204      state->stroke.miter_limit.f = value;
205      state->stroke.miter_limit.i = value;
206      break;
207   case VG_STROKE_DASH_PHASE:
208      state->stroke.dash_phase.f = value;
209      state->stroke.dash_phase.i = value;
210      break;
211   case VG_STROKE_DASH_PHASE_RESET:
212      state->stroke.dash_phase_reset = value;
213      break;
214   case VG_MASKING:
215      state->masking = value;
216      break;
217   case VG_SCISSORING:
218      state->scissoring = value;
219      ctx->state.dirty |= DEPTH_STENCIL_DIRTY;
220      break;
221   case VG_PIXEL_LAYOUT:
222      if (value < VG_PIXEL_LAYOUT_UNKNOWN ||
223          value > VG_PIXEL_LAYOUT_BGR_HORIZONTAL)
224         error = VG_ILLEGAL_ARGUMENT_ERROR;
225      else
226         state->pixel_layout = value;
227      break;
228   case VG_SCREEN_LAYOUT:
229      /* read only ignore */
230      break;
231   case VG_FILTER_FORMAT_LINEAR:
232      state->filter_format_linear = value;
233      break;
234   case VG_FILTER_FORMAT_PREMULTIPLIED:
235      state->filter_format_premultiplied = value;
236      break;
237   case VG_FILTER_CHANNEL_MASK:
238      state->filter_channel_mask = value;
239      break;
240
241   case VG_MAX_SCISSOR_RECTS:
242   case VG_MAX_DASH_COUNT:
243   case VG_MAX_KERNEL_SIZE:
244   case VG_MAX_SEPARABLE_KERNEL_SIZE:
245   case VG_MAX_COLOR_RAMP_STOPS:
246   case VG_MAX_IMAGE_WIDTH:
247   case VG_MAX_IMAGE_HEIGHT:
248   case VG_MAX_IMAGE_PIXELS:
249   case VG_MAX_IMAGE_BYTES:
250   case VG_MAX_GAUSSIAN_STD_DEVIATION:
251   case VG_MAX_FLOAT:
252      /* read only ignore */
253      break;
254   default:
255      error = VG_ILLEGAL_ARGUMENT_ERROR;
256      break;
257   }
258   vg_set_error(ctx, error);
259}
260
261void vegaSetfv(VGParamType type, VGint count,
262               const VGfloat * values)
263{
264   struct vg_context *ctx = vg_current_context();
265   struct vg_state *state = current_state();
266   VGErrorCode error = VG_NO_ERROR;
267
268   if ((count && !values) || !count_in_bounds(type, count) || !is_aligned(values)) {
269      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
270      return;
271   }
272
273   switch(type) {
274   case VG_MATRIX_MODE:
275   case VG_FILL_RULE:
276   case VG_IMAGE_QUALITY:
277   case VG_RENDERING_QUALITY:
278   case VG_BLEND_MODE:
279   case VG_IMAGE_MODE:
280#ifdef OPENVG_VERSION_1_1
281   case VG_COLOR_TRANSFORM:
282#endif
283   case VG_STROKE_CAP_STYLE:
284   case VG_STROKE_JOIN_STYLE:
285   case VG_STROKE_DASH_PHASE_RESET:
286   case VG_MASKING:
287   case VG_SCISSORING:
288   case VG_PIXEL_LAYOUT:
289   case VG_SCREEN_LAYOUT:
290   case VG_FILTER_FORMAT_LINEAR:
291   case VG_FILTER_FORMAT_PREMULTIPLIED:
292   case VG_FILTER_CHANNEL_MASK:
293      vegaSeti(type, floor(values[0]));
294      return;
295      break;
296   case VG_SCISSOR_RECTS: {
297      VGint i;
298      VGuint *x = (VGuint*)values;
299      for (i = 0; i < count; ++i) {
300         state->scissor_rects[i].f =  values[i];
301         state->scissor_rects[i].i =  float_to_int_floor(x[i]);
302      }
303      state->scissor_rects_num = count / 4;
304      ctx->state.dirty |= DEPTH_STENCIL_DIRTY;
305   }
306      break;
307#ifdef OPENVG_VERSION_1_1
308   case VG_COLOR_TRANSFORM_VALUES: {
309      VGint i;
310      for (i = 0; i < count; ++i) {
311         state->color_transform_values[i] =  values[i];
312      }
313   }
314      break;
315#endif
316   case VG_STROKE_LINE_WIDTH:
317      state->stroke.line_width.f = values[0];
318      state->stroke.line_width.i = float_to_int_floor(*((VGuint*)(values)));
319      break;
320   case VG_STROKE_MITER_LIMIT:
321      state->stroke.miter_limit.f = values[0];
322      state->stroke.miter_limit.i = float_to_int_floor(*((VGuint*)(values)));
323      break;
324   case VG_STROKE_DASH_PATTERN: {
325      int i;
326      for (i = 0; i < count; ++i) {
327         state->stroke.dash_pattern[i].f = values[i];
328         state->stroke.dash_pattern[i].i =
329            float_to_int_floor(*((VGuint*)(values + i)));
330      }
331      state->stroke.dash_pattern_num = count;
332   }
333      break;
334   case VG_STROKE_DASH_PHASE:
335      state->stroke.dash_phase.f = values[0];
336      state->stroke.dash_phase.i = float_to_int_floor(*((VGuint*)(values)));
337      break;
338   case VG_TILE_FILL_COLOR:
339      state->tile_fill_color[0] = values[0];
340      state->tile_fill_color[1] = values[1];
341      state->tile_fill_color[2] = values[2];
342      state->tile_fill_color[3] = values[3];
343
344      state->tile_fill_colori[0] = float_to_int_floor(*((VGuint*)(values + 0)));
345      state->tile_fill_colori[1] = float_to_int_floor(*((VGuint*)(values + 1)));
346      state->tile_fill_colori[2] = float_to_int_floor(*((VGuint*)(values + 2)));
347      state->tile_fill_colori[3] = float_to_int_floor(*((VGuint*)(values + 3)));
348      break;
349   case VG_CLEAR_COLOR:
350      state->clear_color[0] = values[0];
351      state->clear_color[1] = values[1];
352      state->clear_color[2] = values[2];
353      state->clear_color[3] = values[3];
354
355      state->clear_colori[0] = float_to_int_floor(*((VGuint*)(values + 0)));
356      state->clear_colori[1] = float_to_int_floor(*((VGuint*)(values + 1)));
357      state->clear_colori[2] = float_to_int_floor(*((VGuint*)(values + 2)));
358      state->clear_colori[3] = float_to_int_floor(*((VGuint*)(values + 3)));
359      break;
360#ifdef OPENVG_VERSION_1_1
361   case VG_GLYPH_ORIGIN:
362      state->glyph_origin[0].f = values[0];
363      state->glyph_origin[1].f = values[1];
364
365      state->glyph_origin[0].i = float_to_int_floor(*((VGuint*)(values + 0)));
366      state->glyph_origin[1].i = float_to_int_floor(*((VGuint*)(values + 1)));
367      break;
368#endif
369
370   case VG_MAX_SCISSOR_RECTS:
371   case VG_MAX_DASH_COUNT:
372   case VG_MAX_KERNEL_SIZE:
373   case VG_MAX_SEPARABLE_KERNEL_SIZE:
374   case VG_MAX_COLOR_RAMP_STOPS:
375   case VG_MAX_IMAGE_WIDTH:
376   case VG_MAX_IMAGE_HEIGHT:
377   case VG_MAX_IMAGE_PIXELS:
378   case VG_MAX_IMAGE_BYTES:
379   case VG_MAX_GAUSSIAN_STD_DEVIATION:
380   case VG_MAX_FLOAT:
381      break;
382   default:
383      error = VG_ILLEGAL_ARGUMENT_ERROR;
384      break;
385   }
386   vg_set_error(ctx, error);
387}
388
389void vegaSetiv(VGParamType type, VGint count,
390               const VGint * values)
391{
392   struct vg_context *ctx = vg_current_context();
393   struct vg_state *state = current_state();
394
395   if ((count && !values) || !count_in_bounds(type, count) || !is_aligned(values)) {
396      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
397      return;
398   }
399
400   switch(type) {
401   case VG_MATRIX_MODE:
402   case VG_FILL_RULE:
403   case VG_IMAGE_QUALITY:
404   case VG_RENDERING_QUALITY:
405   case VG_BLEND_MODE:
406   case VG_IMAGE_MODE:
407#ifdef OPENVG_VERSION_1_1
408   case VG_COLOR_TRANSFORM:
409#endif
410   case VG_STROKE_CAP_STYLE:
411   case VG_STROKE_JOIN_STYLE:
412   case VG_STROKE_DASH_PHASE_RESET:
413   case VG_MASKING:
414   case VG_SCISSORING:
415   case VG_PIXEL_LAYOUT:
416   case VG_SCREEN_LAYOUT:
417   case VG_FILTER_FORMAT_LINEAR:
418   case VG_FILTER_FORMAT_PREMULTIPLIED:
419   case VG_FILTER_CHANNEL_MASK:
420      vegaSeti(type, values[0]);
421      return;
422      break;
423   case VG_SCISSOR_RECTS: {
424      VGint i;
425      for (i = 0; i < count; ++i) {
426         state->scissor_rects[i].i =  values[i];
427         state->scissor_rects[i].f =  values[i];
428      }
429      state->scissor_rects_num = count / 4;
430      ctx->state.dirty |= DEPTH_STENCIL_DIRTY;
431   }
432      break;
433#ifdef OPENVG_VERSION_1_1
434   case VG_COLOR_TRANSFORM_VALUES: {
435      VGint i;
436      for (i = 0; i < count; ++i) {
437         state->color_transform_values[i] =  values[i];
438      }
439   }
440      break;
441#endif
442   case VG_STROKE_LINE_WIDTH:
443      state->stroke.line_width.f = values[0];
444      state->stroke.line_width.i = values[0];
445      break;
446   case VG_STROKE_MITER_LIMIT:
447      state->stroke.miter_limit.f = values[0];
448      state->stroke.miter_limit.i = values[0];
449      break;
450   case VG_STROKE_DASH_PATTERN: {
451      int i;
452      for (i = 0; i < count; ++i) {
453         state->stroke.dash_pattern[i].f = values[i];
454         state->stroke.dash_pattern[i].i = values[i];
455      }
456      state->stroke.dash_pattern_num = count;
457   }
458      break;
459   case VG_STROKE_DASH_PHASE:
460      state->stroke.dash_phase.f = values[0];
461      state->stroke.dash_phase.i = values[0];
462      break;
463   case VG_TILE_FILL_COLOR:
464      state->tile_fill_color[0] = values[0];
465      state->tile_fill_color[1] = values[1];
466      state->tile_fill_color[2] = values[2];
467      state->tile_fill_color[3] = values[3];
468
469      state->tile_fill_colori[0] = values[0];
470      state->tile_fill_colori[1] = values[1];
471      state->tile_fill_colori[2] = values[2];
472      state->tile_fill_colori[3] = values[3];
473      break;
474   case VG_CLEAR_COLOR:
475      state->clear_color[0] = values[0];
476      state->clear_color[1] = values[1];
477      state->clear_color[2] = values[2];
478      state->clear_color[3] = values[3];
479
480      state->clear_colori[0] = values[0];
481      state->clear_colori[1] = values[1];
482      state->clear_colori[2] = values[2];
483      state->clear_colori[3] = values[3];
484      break;
485#ifdef OPENVG_VERSION_1_1
486   case VG_GLYPH_ORIGIN:
487      state->glyph_origin[0].f = values[0];
488      state->glyph_origin[1].f = values[1];
489      state->glyph_origin[0].i = values[0];
490      state->glyph_origin[1].i = values[1];
491      break;
492#endif
493
494   case VG_MAX_SCISSOR_RECTS:
495   case VG_MAX_DASH_COUNT:
496   case VG_MAX_KERNEL_SIZE:
497   case VG_MAX_SEPARABLE_KERNEL_SIZE:
498   case VG_MAX_COLOR_RAMP_STOPS:
499   case VG_MAX_IMAGE_WIDTH:
500   case VG_MAX_IMAGE_HEIGHT:
501   case VG_MAX_IMAGE_PIXELS:
502   case VG_MAX_IMAGE_BYTES:
503   case VG_MAX_GAUSSIAN_STD_DEVIATION:
504   case VG_MAX_FLOAT:
505      break;
506
507   default:
508      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
509      break;
510   }
511}
512
513VGfloat vegaGetf(VGParamType type)
514{
515   struct vg_context *ctx = vg_current_context();
516   const struct vg_state *state = current_state();
517   VGErrorCode error = VG_NO_ERROR;
518   VGfloat value = 0.0f;
519
520   switch(type) {
521   case VG_MATRIX_MODE:
522   case VG_FILL_RULE:
523   case VG_IMAGE_QUALITY:
524   case VG_RENDERING_QUALITY:
525   case VG_BLEND_MODE:
526   case VG_IMAGE_MODE:
527#ifdef OPENVG_VERSION_1_1
528   case VG_COLOR_TRANSFORM:
529#endif
530   case VG_STROKE_CAP_STYLE:
531   case VG_STROKE_JOIN_STYLE:
532   case VG_STROKE_DASH_PHASE_RESET:
533   case VG_MASKING:
534   case VG_SCISSORING:
535   case VG_PIXEL_LAYOUT:
536   case VG_SCREEN_LAYOUT:
537   case VG_FILTER_FORMAT_LINEAR:
538   case VG_FILTER_FORMAT_PREMULTIPLIED:
539   case VG_FILTER_CHANNEL_MASK:
540      return vegaGeti(type);
541      break;
542   case VG_STROKE_LINE_WIDTH:
543      value = state->stroke.line_width.f;
544      break;
545   case VG_STROKE_MITER_LIMIT:
546      value = state->stroke.miter_limit.f;
547      break;
548   case VG_STROKE_DASH_PHASE:
549      value = state->stroke.dash_phase.f;
550      break;
551
552   case VG_MAX_SCISSOR_RECTS:
553   case VG_MAX_DASH_COUNT:
554   case VG_MAX_KERNEL_SIZE:
555   case VG_MAX_SEPARABLE_KERNEL_SIZE:
556   case VG_MAX_COLOR_RAMP_STOPS:
557   case VG_MAX_IMAGE_WIDTH:
558   case VG_MAX_IMAGE_HEIGHT:
559   case VG_MAX_IMAGE_PIXELS:
560   case VG_MAX_IMAGE_BYTES:
561   case VG_MAX_GAUSSIAN_STD_DEVIATION:
562      return vegaGeti(type);
563      break;
564   case VG_MAX_FLOAT:
565      value = 1e+10;/*must be at least 1e+10*/
566      break;
567   default:
568      error = VG_ILLEGAL_ARGUMENT_ERROR;
569      break;
570   }
571   vg_set_error(ctx, error);
572   return value;
573}
574
575VGint vegaGeti(VGParamType type)
576{
577   const struct vg_state *state = current_state();
578   struct vg_context *ctx = vg_current_context();
579   VGErrorCode error = VG_NO_ERROR;
580   VGint value = 0;
581
582   switch(type) {
583   case VG_MATRIX_MODE:
584      value = state->matrix_mode;
585      break;
586   case VG_FILL_RULE:
587      value = state->fill_rule;
588      break;
589   case VG_IMAGE_QUALITY:
590      value = state->image_quality;
591      break;
592   case VG_RENDERING_QUALITY:
593      value = state->rendering_quality;
594      break;
595   case VG_BLEND_MODE:
596      value = state->blend_mode;
597      break;
598   case VG_IMAGE_MODE:
599      value = state->image_mode;
600      break;
601#ifdef OPENVG_VERSION_1_1
602   case VG_COLOR_TRANSFORM:
603      value = state->color_transform;
604      break;
605#endif
606   case VG_STROKE_LINE_WIDTH:
607      value = state->stroke.line_width.i;
608      break;
609   case VG_STROKE_CAP_STYLE:
610      value = state->stroke.cap_style;
611      break;
612   case VG_STROKE_JOIN_STYLE:
613      value = state->stroke.join_style;
614      break;
615   case VG_STROKE_MITER_LIMIT:
616      value = state->stroke.miter_limit.i;
617      break;
618   case VG_STROKE_DASH_PHASE:
619      value = state->stroke.dash_phase.i;
620      break;
621   case VG_STROKE_DASH_PHASE_RESET:
622      value = state->stroke.dash_phase_reset;
623      break;
624   case VG_MASKING:
625      value = state->masking;
626      break;
627   case VG_SCISSORING:
628      value = state->scissoring;
629      break;
630   case VG_PIXEL_LAYOUT:
631      value = state->pixel_layout;
632      break;
633   case VG_SCREEN_LAYOUT:
634      value = state->screen_layout;
635      break;
636   case VG_FILTER_FORMAT_LINEAR:
637      value = state->filter_format_linear;
638      break;
639   case VG_FILTER_FORMAT_PREMULTIPLIED:
640      value = state->filter_format_premultiplied;
641      break;
642   case VG_FILTER_CHANNEL_MASK:
643      value = state->filter_channel_mask;
644      break;
645
646   case VG_MAX_SCISSOR_RECTS:
647      value = 32; /*must be at least 32*/
648      break;
649   case VG_MAX_DASH_COUNT:
650      value = 16; /*must be at least 16*/
651      break;
652   case VG_MAX_KERNEL_SIZE:
653      value = 7; /*must be at least 7*/
654      break;
655   case VG_MAX_SEPARABLE_KERNEL_SIZE:
656      value = 15; /*must be at least 15*/
657      break;
658   case VG_MAX_COLOR_RAMP_STOPS:
659      value = 256; /*must be at least 32*/
660      break;
661   case VG_MAX_IMAGE_WIDTH:
662      value = 2048;
663      break;
664   case VG_MAX_IMAGE_HEIGHT:
665      value = 2048;
666      break;
667   case VG_MAX_IMAGE_PIXELS:
668      value = 2048*2048;
669      break;
670   case VG_MAX_IMAGE_BYTES:
671      value = 2048*2048 * 4;
672      break;
673   case VG_MAX_GAUSSIAN_STD_DEVIATION:
674      value = 128; /*must be at least 128*/
675      break;
676
677   case VG_MAX_FLOAT: {
678      VGfloat val = vegaGetf(type);
679      value = float_to_int_floor(*((VGuint*)&val));
680   }
681      break;
682   default:
683      error = VG_ILLEGAL_ARGUMENT_ERROR;
684      break;
685   }
686   vg_set_error(ctx, error);
687   return value;
688}
689
690VGint vegaGetVectorSize(VGParamType type)
691{
692   struct vg_context *ctx = vg_current_context();
693   const struct vg_state *state = current_state();
694   switch(type) {
695   case VG_MATRIX_MODE:
696   case VG_FILL_RULE:
697   case VG_IMAGE_QUALITY:
698   case VG_RENDERING_QUALITY:
699   case VG_BLEND_MODE:
700   case VG_IMAGE_MODE:
701      return 1;
702   case VG_SCISSOR_RECTS:
703      return state->scissor_rects_num * 4;
704#ifdef OPENVG_VERSION_1_1
705   case VG_COLOR_TRANSFORM:
706      return 1;
707   case VG_COLOR_TRANSFORM_VALUES:
708      return 8;
709#endif
710   case VG_STROKE_LINE_WIDTH:
711   case VG_STROKE_CAP_STYLE:
712   case VG_STROKE_JOIN_STYLE:
713   case VG_STROKE_MITER_LIMIT:
714      return 1;
715   case VG_STROKE_DASH_PATTERN:
716      return state->stroke.dash_pattern_num;
717   case VG_STROKE_DASH_PHASE:
718      return 1;
719   case VG_STROKE_DASH_PHASE_RESET:
720      return 1;
721   case VG_TILE_FILL_COLOR:
722      return 4;
723   case VG_CLEAR_COLOR:
724      return 4;
725#ifdef OPENVG_VERSION_1_1
726   case VG_GLYPH_ORIGIN:
727      return 2;
728#endif
729   case VG_MASKING:
730      return 1;
731   case VG_SCISSORING:
732      return 1;
733   case VG_PIXEL_LAYOUT:
734      return 1;
735   case VG_SCREEN_LAYOUT:
736      return 1;
737   case VG_FILTER_FORMAT_LINEAR:
738      return 1;
739   case VG_FILTER_FORMAT_PREMULTIPLIED:
740      return 1;
741   case VG_FILTER_CHANNEL_MASK:
742      return 1;
743
744   case VG_MAX_COLOR_RAMP_STOPS:
745      return 1;
746   case VG_MAX_SCISSOR_RECTS:
747   case VG_MAX_DASH_COUNT:
748   case VG_MAX_KERNEL_SIZE:
749   case VG_MAX_SEPARABLE_KERNEL_SIZE:
750   case VG_MAX_IMAGE_WIDTH:
751   case VG_MAX_IMAGE_HEIGHT:
752   case VG_MAX_IMAGE_PIXELS:
753   case VG_MAX_IMAGE_BYTES:
754   case VG_MAX_FLOAT:
755   case VG_MAX_GAUSSIAN_STD_DEVIATION:
756      return 1;
757   default:
758      if (ctx)
759         vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
760      return 0;
761   }
762}
763
764void vegaGetfv(VGParamType type, VGint count,
765               VGfloat * values)
766{
767   const struct vg_state *state = current_state();
768   struct vg_context *ctx = vg_current_context();
769   VGint real_count = vegaGetVectorSize(type);
770
771   if (!values || count <= 0 || count > real_count || !is_aligned(values)) {
772      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
773      return;
774   }
775
776   switch(type) {
777   case VG_MATRIX_MODE:
778   case VG_FILL_RULE:
779   case VG_IMAGE_QUALITY:
780   case VG_RENDERING_QUALITY:
781   case VG_BLEND_MODE:
782   case VG_IMAGE_MODE:
783#ifdef OPENVG_VERSION_1_1
784   case VG_COLOR_TRANSFORM:
785#endif
786   case VG_STROKE_CAP_STYLE:
787   case VG_STROKE_JOIN_STYLE:
788   case VG_STROKE_DASH_PHASE_RESET:
789   case VG_MASKING:
790   case VG_SCISSORING:
791   case VG_PIXEL_LAYOUT:
792   case VG_SCREEN_LAYOUT:
793   case VG_FILTER_FORMAT_LINEAR:
794   case VG_FILTER_FORMAT_PREMULTIPLIED:
795   case VG_FILTER_CHANNEL_MASK:
796   case VG_MAX_SCISSOR_RECTS:
797   case VG_MAX_DASH_COUNT:
798   case VG_MAX_KERNEL_SIZE:
799   case VG_MAX_SEPARABLE_KERNEL_SIZE:
800   case VG_MAX_COLOR_RAMP_STOPS:
801   case VG_MAX_IMAGE_WIDTH:
802   case VG_MAX_IMAGE_HEIGHT:
803   case VG_MAX_IMAGE_PIXELS:
804   case VG_MAX_IMAGE_BYTES:
805   case VG_MAX_GAUSSIAN_STD_DEVIATION:
806      values[0] = vegaGeti(type);
807      break;
808   case VG_MAX_FLOAT:
809      values[0] = vegaGetf(type);
810      break;
811   case VG_SCISSOR_RECTS: {
812      VGint i;
813      for (i = 0; i < count; ++i) {
814         values[i] = state->scissor_rects[i].f;
815      }
816   }
817      break;
818#ifdef OPENVG_VERSION_1_1
819   case VG_COLOR_TRANSFORM_VALUES: {
820      memcpy(values, state->color_transform_values,
821             sizeof(VGfloat) * count);
822   }
823      break;
824#endif
825   case VG_STROKE_LINE_WIDTH:
826      values[0] = state->stroke.line_width.f;
827      break;
828   case VG_STROKE_MITER_LIMIT:
829      values[0] = state->stroke.miter_limit.f;
830      break;
831   case VG_STROKE_DASH_PATTERN: {
832      VGint i;
833      for (i = 0; i < count; ++i) {
834         values[i] = state->stroke.dash_pattern[i].f;
835      }
836   }
837      break;
838   case VG_STROKE_DASH_PHASE:
839      values[0] = state->stroke.dash_phase.f;
840      break;
841   case VG_TILE_FILL_COLOR:
842      values[0] = state->tile_fill_color[0];
843      values[1] = state->tile_fill_color[1];
844      values[2] = state->tile_fill_color[2];
845      values[3] = state->tile_fill_color[3];
846      break;
847   case VG_CLEAR_COLOR:
848      values[0] = state->clear_color[0];
849      values[1] = state->clear_color[1];
850      values[2] = state->clear_color[2];
851      values[3] = state->clear_color[3];
852      break;
853#ifdef OPENVG_VERSION_1_1
854   case VG_GLYPH_ORIGIN:
855      values[0] = state->glyph_origin[0].f;
856      values[1] = state->glyph_origin[1].f;
857      break;
858#endif
859   default:
860      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
861      break;
862   }
863}
864
865void vegaGetiv(VGParamType type, VGint count,
866               VGint * values)
867{
868   const struct vg_state *state = current_state();
869   struct vg_context *ctx = vg_current_context();
870   VGint real_count = vegaGetVectorSize(type);
871
872   if (!values || count <= 0 || count > real_count || !is_aligned(values)) {
873      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
874      return;
875   }
876
877   switch(type) {
878   case VG_MATRIX_MODE:
879   case VG_FILL_RULE:
880   case VG_IMAGE_QUALITY:
881   case VG_RENDERING_QUALITY:
882   case VG_BLEND_MODE:
883   case VG_IMAGE_MODE:
884#ifdef OPENVG_VERSION_1_1
885   case VG_COLOR_TRANSFORM:
886#endif
887   case VG_STROKE_CAP_STYLE:
888   case VG_STROKE_JOIN_STYLE:
889   case VG_STROKE_DASH_PHASE_RESET:
890   case VG_MASKING:
891   case VG_SCISSORING:
892   case VG_PIXEL_LAYOUT:
893   case VG_SCREEN_LAYOUT:
894   case VG_FILTER_FORMAT_LINEAR:
895   case VG_FILTER_FORMAT_PREMULTIPLIED:
896   case VG_FILTER_CHANNEL_MASK:
897   case VG_MAX_SCISSOR_RECTS:
898   case VG_MAX_DASH_COUNT:
899   case VG_MAX_KERNEL_SIZE:
900   case VG_MAX_SEPARABLE_KERNEL_SIZE:
901   case VG_MAX_COLOR_RAMP_STOPS:
902   case VG_MAX_IMAGE_WIDTH:
903   case VG_MAX_IMAGE_HEIGHT:
904   case VG_MAX_IMAGE_PIXELS:
905   case VG_MAX_IMAGE_BYTES:
906   case VG_MAX_GAUSSIAN_STD_DEVIATION:
907      values[0] = vegaGeti(type);
908      break;
909   case VG_MAX_FLOAT: {
910      VGfloat val = vegaGetf(type);
911      values[0] = float_to_int_floor(*((VGuint*)&val));
912   }
913      break;
914   case VG_SCISSOR_RECTS: {
915      VGint i;
916      for (i = 0; i < count; ++i) {
917         values[i] = state->scissor_rects[i].i;
918      }
919   }
920      break;
921#ifdef OPENVG_VERSION_1_1
922   case VG_COLOR_TRANSFORM_VALUES: {
923      VGint i;
924      VGuint *x = (VGuint*)state->color_transform_values;
925      for (i = 0; i < count; ++i) {
926         values[i] = float_to_int_floor(x[i]);
927      }
928   }
929      break;
930#endif
931   case VG_STROKE_LINE_WIDTH:
932      values[0] = state->stroke.line_width.i;
933      break;
934   case VG_STROKE_MITER_LIMIT:
935      values[0] = state->stroke.miter_limit.i;
936      break;
937   case VG_STROKE_DASH_PATTERN: {
938      VGint i;
939      for (i = 0; i < count; ++i) {
940         values[i] = state->stroke.dash_pattern[i].i;
941      }
942   }
943      break;
944   case VG_STROKE_DASH_PHASE:
945      values[0] = state->stroke.dash_phase.i;
946      break;
947   case VG_TILE_FILL_COLOR:
948      values[0] = state->tile_fill_colori[0];
949      values[1] = state->tile_fill_colori[1];
950      values[2] = state->tile_fill_colori[2];
951      values[3] = state->tile_fill_colori[3];
952      break;
953   case VG_CLEAR_COLOR:
954      values[0] = state->clear_colori[0];
955      values[1] = state->clear_colori[1];
956      values[2] = state->clear_colori[2];
957      values[3] = state->clear_colori[3];
958      break;
959#ifdef OPENVG_VERSION_1_1
960   case VG_GLYPH_ORIGIN:
961      values[0] = state->glyph_origin[0].i;
962      values[1] = state->glyph_origin[1].i;
963      break;
964#endif
965   default:
966      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
967      break;
968   }
969}
970
971void vegaSetParameterf(VGHandle object,
972                       VGint paramType,
973                       VGfloat value)
974{
975   struct vg_context *ctx = vg_current_context();
976   void *ptr = handle_to_pointer(object);
977
978   if (object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
979      vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
980      return;
981   }
982
983   switch(paramType) {
984   case VG_PAINT_TYPE:
985   case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
986   case VG_PAINT_PATTERN_TILING_MODE:
987      vegaSetParameteri(object, paramType, floor(value));
988      return;
989      break;
990   case VG_PAINT_COLOR:
991   case VG_PAINT_COLOR_RAMP_STOPS:
992   case VG_PAINT_LINEAR_GRADIENT:
993   case VG_PAINT_RADIAL_GRADIENT:
994      /* it's an error if paramType refers to a vector parameter */
995      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
996      break;
997   case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: {
998      struct vg_paint *p = handle_to_paint(object);
999      paint_set_color_ramp_premultiplied(p, value);
1000   }
1001      break;
1002
1003   case VG_PATH_DATATYPE:
1004   case VG_PATH_FORMAT:
1005   case VG_PATH_SCALE:
1006   case VG_PATH_BIAS:
1007   case VG_PATH_NUM_SEGMENTS:
1008   case VG_PATH_NUM_COORDS:
1009
1010   case VG_IMAGE_FORMAT:
1011   case VG_IMAGE_WIDTH:
1012   case VG_IMAGE_HEIGHT:
1013
1014#ifdef OPENVG_VERSION_1_1
1015   case VG_FONT_NUM_GLYPHS:
1016      /* read only don't produce an error */
1017      break;
1018#endif
1019   default:
1020      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1021      break;
1022   }
1023}
1024
1025void vegaSetParameteri(VGHandle object,
1026                       VGint paramType,
1027                       VGint value)
1028{
1029   struct vg_context *ctx = vg_current_context();
1030   void *ptr = handle_to_pointer(object);
1031
1032   if (object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
1033      vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
1034      return;
1035   }
1036
1037   switch(paramType) {
1038   case VG_PAINT_TYPE:
1039      if (value < VG_PAINT_TYPE_COLOR ||
1040          value > VG_PAINT_TYPE_PATTERN)
1041         vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1042      else {
1043         struct vg_paint *paint = handle_to_paint(object);
1044         paint_set_type(paint, value);
1045      }
1046      break;
1047   case VG_PAINT_COLOR:
1048   case VG_PAINT_COLOR_RAMP_STOPS:
1049   case VG_PAINT_LINEAR_GRADIENT:
1050   case VG_PAINT_RADIAL_GRADIENT:
1051      /* it's an error if paramType refers to a vector parameter */
1052      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1053      break;
1054   case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
1055      if (value < VG_COLOR_RAMP_SPREAD_PAD ||
1056          value > VG_COLOR_RAMP_SPREAD_REFLECT)
1057         vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1058      else {
1059         struct vg_paint *paint = handle_to_paint(object);
1060         paint_set_spread_mode(paint, value);
1061      }
1062      break;
1063   case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: {
1064      struct vg_paint *p = handle_to_paint(object);
1065      paint_set_color_ramp_premultiplied(p, value);
1066   }
1067      break;
1068   case VG_PAINT_PATTERN_TILING_MODE:
1069      if (value < VG_TILE_FILL ||
1070          value > VG_TILE_REFLECT)
1071         vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1072      else {
1073         struct vg_paint *paint = handle_to_paint(object);
1074         paint_set_pattern_tiling(paint, value);
1075      }
1076      break;
1077
1078   case VG_PATH_DATATYPE:
1079   case VG_PATH_FORMAT:
1080   case VG_PATH_SCALE:
1081   case VG_PATH_BIAS:
1082   case VG_PATH_NUM_SEGMENTS:
1083   case VG_PATH_NUM_COORDS:
1084
1085   case VG_IMAGE_FORMAT:
1086   case VG_IMAGE_WIDTH:
1087   case VG_IMAGE_HEIGHT:
1088
1089#ifdef OPENVG_VERSION_1_1
1090   case VG_FONT_NUM_GLYPHS:
1091      /* read only don't produce an error */
1092      break;
1093#endif
1094   default:
1095      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1096      return;
1097   }
1098}
1099
1100void vegaSetParameterfv(VGHandle object,
1101                        VGint paramType,
1102                        VGint count,
1103                        const VGfloat * values)
1104{
1105   struct vg_context *ctx = vg_current_context();
1106   void *ptr = handle_to_pointer(object);
1107   VGint real_count = vegaGetParameterVectorSize(object, paramType);
1108
1109   if (object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
1110      vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
1111      return;
1112   }
1113
1114   if (count < 0 || count < real_count ||
1115       (values == NULL && count != 0) ||
1116       !is_aligned(values)) {
1117      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1118      return;
1119   }
1120
1121   switch(paramType) {
1122   case VG_PAINT_TYPE:
1123   case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
1124   case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
1125   case VG_PAINT_PATTERN_TILING_MODE:
1126      if (count != 1)
1127         vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1128      else
1129         vegaSetParameterf(object, paramType, values[0]);
1130      return;
1131      break;
1132   case VG_PAINT_COLOR: {
1133      if (count != 4)
1134         vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1135      else {
1136         struct vg_paint *paint = handle_to_paint(object);
1137         paint_set_color(paint, values);
1138         if (ctx->state.vg.fill_paint == paint ||
1139             ctx->state.vg.stroke_paint == paint)
1140            ctx->state.dirty |= PAINT_DIRTY;
1141      }
1142   }
1143      break;
1144   case VG_PAINT_COLOR_RAMP_STOPS: {
1145      if (count && count < 4)
1146         vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1147      else {
1148         struct vg_paint *paint = handle_to_paint(object);
1149         count = MIN2(count, VEGA_MAX_COLOR_RAMP_STOPS);
1150         paint_set_ramp_stops(paint, values, count);
1151         {
1152            VGint stopsi[VEGA_MAX_COLOR_RAMP_STOPS];
1153            int i = 0;
1154            for (i = 0; i < count; ++i) {
1155               stopsi[i] = float_to_int_floor(*((VGuint*)(values + i)));
1156            }
1157            paint_set_ramp_stopsi(paint, stopsi, count);
1158         }
1159      }
1160   }
1161      break;
1162   case VG_PAINT_LINEAR_GRADIENT: {
1163      if (count != 4)
1164         vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1165      else {
1166         struct vg_paint *paint = handle_to_paint(object);
1167         paint_set_linear_gradient(paint, values);
1168         {
1169            VGint vals[4];
1170            vals[0] = FLT_TO_INT(values[0]);
1171            vals[1] = FLT_TO_INT(values[1]);
1172            vals[2] = FLT_TO_INT(values[2]);
1173            vals[3] = FLT_TO_INT(values[3]);
1174            paint_set_linear_gradienti(paint, vals);
1175         }
1176      }
1177   }
1178      break;
1179   case VG_PAINT_RADIAL_GRADIENT: {
1180      if (count != 5)
1181         vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1182      else {
1183         struct vg_paint *paint = handle_to_paint(object);
1184         paint_set_radial_gradient(paint, values);
1185         {
1186            VGint vals[5];
1187            vals[0] = FLT_TO_INT(values[0]);
1188            vals[1] = FLT_TO_INT(values[1]);
1189            vals[2] = FLT_TO_INT(values[2]);
1190            vals[3] = FLT_TO_INT(values[3]);
1191            vals[4] = FLT_TO_INT(values[4]);
1192            paint_set_radial_gradienti(paint, vals);
1193         }
1194      }
1195   }
1196      break;
1197
1198   case VG_PATH_DATATYPE:
1199   case VG_PATH_FORMAT:
1200   case VG_PATH_SCALE:
1201   case VG_PATH_BIAS:
1202   case VG_PATH_NUM_SEGMENTS:
1203   case VG_PATH_NUM_COORDS:
1204
1205#ifdef OPENVG_VERSION_1_1
1206   case VG_FONT_NUM_GLYPHS:
1207      /* read only don't produce an error */
1208      break;
1209#endif
1210   default:
1211      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1212      return;
1213   }
1214}
1215
1216void vegaSetParameteriv(VGHandle object,
1217                        VGint paramType,
1218                        VGint count,
1219                        const VGint * values)
1220{
1221   struct vg_context *ctx = vg_current_context();
1222   void *ptr = handle_to_pointer(object);
1223   VGint real_count = vegaGetParameterVectorSize(object, paramType);
1224
1225   if (object == VG_INVALID_HANDLE || !is_aligned(ptr)) {
1226      vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
1227      return;
1228   }
1229
1230   if (count < 0 || count < real_count ||
1231       (values == NULL && count != 0) ||
1232       !is_aligned(values)) {
1233      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1234      return;
1235   }
1236
1237   switch(paramType) {
1238   case VG_PAINT_TYPE:
1239   case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
1240   case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
1241   case VG_PAINT_PATTERN_TILING_MODE:
1242      if (count != 1)
1243         vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1244      else
1245         vegaSetParameteri(object, paramType, values[0]);
1246      return;
1247      break;
1248   case VG_PAINT_COLOR: {
1249      if (count != 4)
1250         vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1251      else {
1252         struct vg_paint *paint = handle_to_paint(object);
1253         paint_set_coloriv(paint, values);
1254         if (ctx->state.vg.fill_paint == paint ||
1255             ctx->state.vg.stroke_paint == paint)
1256            ctx->state.dirty |= PAINT_DIRTY;
1257      }
1258   }
1259      break;
1260   case VG_PAINT_COLOR_RAMP_STOPS: {
1261      if ((count % 5))
1262         vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1263      else {
1264         VGfloat *vals = 0;
1265         int i;
1266         struct vg_paint *paint = handle_to_paint(object);
1267         if (count) {
1268            vals = malloc(sizeof(VGfloat)*count);
1269            for (i = 0; i < count; ++i)
1270               vals[i] = values[i];
1271         }
1272
1273         paint_set_ramp_stopsi(paint, values, count);
1274         paint_set_ramp_stops(paint, vals, count);
1275         free(vals);
1276      }
1277   }
1278      break;
1279   case VG_PAINT_LINEAR_GRADIENT: {
1280      if (count != 4)
1281         vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1282      else {
1283         VGfloat vals[4];
1284         struct vg_paint *paint = handle_to_paint(object);
1285         vals[0] = values[0];
1286         vals[1] = values[1];
1287         vals[2] = values[2];
1288         vals[3] = values[3];
1289         paint_set_linear_gradient(paint, vals);
1290         paint_set_linear_gradienti(paint, values);
1291      }
1292   }
1293      break;
1294   case VG_PAINT_RADIAL_GRADIENT: {
1295      if (count != 5)
1296         vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1297      else {
1298         VGfloat vals[5];
1299         struct vg_paint *paint = handle_to_paint(object);
1300         vals[0] = values[0];
1301         vals[1] = values[1];
1302         vals[2] = values[2];
1303         vals[3] = values[3];
1304         vals[4] = values[4];
1305         paint_set_radial_gradient(paint, vals);
1306         paint_set_radial_gradienti(paint, values);
1307      }
1308   }
1309      break;
1310   case VG_PATH_DATATYPE:
1311   case VG_PATH_FORMAT:
1312   case VG_PATH_SCALE:
1313   case VG_PATH_BIAS:
1314   case VG_PATH_NUM_SEGMENTS:
1315   case VG_PATH_NUM_COORDS:
1316      /* read only don't produce an error */
1317      break;
1318   default:
1319      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1320      return;
1321   }
1322}
1323
1324VGint vegaGetParameterVectorSize(VGHandle object,
1325                                 VGint paramType)
1326{
1327   struct vg_context *ctx = vg_current_context();
1328
1329   if (object == VG_INVALID_HANDLE) {
1330      vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
1331      return 0;
1332   }
1333
1334   switch(paramType) {
1335   case VG_PAINT_TYPE:
1336   case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
1337   case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
1338   case VG_PAINT_PATTERN_TILING_MODE:
1339      return 1;
1340   case VG_PAINT_COLOR:
1341      return 4;
1342   case VG_PAINT_COLOR_RAMP_STOPS: {
1343      struct vg_paint *p = handle_to_paint(object);
1344      return paint_num_ramp_stops(p);
1345   }
1346      break;
1347   case VG_PAINT_LINEAR_GRADIENT:
1348      return 4;
1349   case VG_PAINT_RADIAL_GRADIENT:
1350      return 5;
1351
1352
1353   case VG_PATH_FORMAT:
1354   case VG_PATH_DATATYPE:
1355   case VG_PATH_SCALE:
1356   case VG_PATH_BIAS:
1357   case VG_PATH_NUM_SEGMENTS:
1358   case VG_PATH_NUM_COORDS:
1359      return 1;
1360
1361   case VG_IMAGE_FORMAT:
1362   case VG_IMAGE_WIDTH:
1363   case VG_IMAGE_HEIGHT:
1364      return 1;
1365
1366#ifdef OPENVG_VERSION_1_1
1367   case VG_FONT_NUM_GLYPHS:
1368      return 1;
1369#endif
1370
1371   default:
1372      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1373      break;
1374   }
1375   return 0;
1376}
1377
1378
1379VGfloat vegaGetParameterf(VGHandle object,
1380                          VGint paramType)
1381{
1382   struct vg_context *ctx = vg_current_context();
1383
1384   if (object == VG_INVALID_HANDLE) {
1385      vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
1386      return 0;
1387   }
1388
1389   switch(paramType) {
1390   case VG_PAINT_TYPE:
1391   case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
1392   case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
1393   case VG_PAINT_PATTERN_TILING_MODE:
1394      return vegaGetParameteri(object, paramType);
1395      break;
1396   case VG_PAINT_COLOR:
1397   case VG_PAINT_COLOR_RAMP_STOPS:
1398   case VG_PAINT_LINEAR_GRADIENT:
1399   case VG_PAINT_RADIAL_GRADIENT:
1400      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1401      break;
1402
1403   case VG_PATH_FORMAT:
1404      return VG_PATH_FORMAT_STANDARD;
1405   case VG_PATH_SCALE: {
1406      struct path *p = handle_to_path(object);
1407      return path_scale(p);
1408   }
1409   case VG_PATH_BIAS: {
1410      struct path *p = handle_to_path(object);
1411      return path_bias(p);
1412   }
1413   case VG_PATH_DATATYPE:
1414   case VG_PATH_NUM_SEGMENTS:
1415   case VG_PATH_NUM_COORDS:
1416      return vegaGetParameteri(object, paramType);
1417      break;
1418
1419   case VG_IMAGE_FORMAT:
1420   case VG_IMAGE_WIDTH:
1421   case VG_IMAGE_HEIGHT:
1422#ifdef OPENVG_VERSION_1_1
1423   case VG_FONT_NUM_GLYPHS:
1424      return vegaGetParameteri(object, paramType);
1425      break;
1426#endif
1427
1428   default:
1429      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1430      break;
1431   }
1432   return 0;
1433}
1434
1435VGint vegaGetParameteri(VGHandle object,
1436                        VGint paramType)
1437{
1438   struct vg_context *ctx = vg_current_context();
1439
1440   if (object == VG_INVALID_HANDLE) {
1441      vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
1442      return 0;
1443   }
1444
1445   switch(paramType) {
1446   case VG_PAINT_TYPE: {
1447         struct vg_paint *paint = handle_to_paint(object);
1448         return paint_type(paint);
1449   }
1450      break;
1451   case VG_PAINT_COLOR_RAMP_SPREAD_MODE: {
1452      struct vg_paint *p = handle_to_paint(object);
1453      return paint_spread_mode(p);
1454   }
1455   case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: {
1456      struct vg_paint *p = handle_to_paint(object);
1457      return paint_color_ramp_premultiplied(p);
1458   }
1459      break;
1460   case VG_PAINT_PATTERN_TILING_MODE: {
1461      struct vg_paint *p = handle_to_paint(object);
1462      return paint_pattern_tiling(p);
1463   }
1464      break;
1465   case VG_PAINT_COLOR:
1466   case VG_PAINT_COLOR_RAMP_STOPS:
1467   case VG_PAINT_LINEAR_GRADIENT:
1468   case VG_PAINT_RADIAL_GRADIENT:
1469      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1470      break;
1471
1472   case VG_PATH_FORMAT:
1473      return VG_PATH_FORMAT_STANDARD;
1474   case VG_PATH_SCALE:
1475   case VG_PATH_BIAS:
1476      return vegaGetParameterf(object, paramType);
1477   case VG_PATH_DATATYPE: {
1478      struct path *p = handle_to_path(object);
1479      return path_datatype(p);
1480   }
1481   case VG_PATH_NUM_SEGMENTS: {
1482      struct path *p = handle_to_path(object);
1483      return path_num_segments(p);
1484   }
1485   case VG_PATH_NUM_COORDS: {
1486      struct path *p = handle_to_path(object);
1487      return path_num_coords(p);
1488   }
1489      break;
1490
1491   case VG_IMAGE_FORMAT: {
1492      struct vg_image *img = handle_to_image(object);
1493      return img->format;
1494   }
1495      break;
1496   case VG_IMAGE_WIDTH: {
1497      struct vg_image *img = handle_to_image(object);
1498      return img->width;
1499   }
1500      break;
1501   case VG_IMAGE_HEIGHT: {
1502      struct vg_image *img = handle_to_image(object);
1503      return img->height;
1504   }
1505      break;
1506
1507#ifdef OPENVG_VERSION_1_1
1508   case VG_FONT_NUM_GLYPHS: {
1509      struct vg_font *font = handle_to_font(object);
1510      return font_num_glyphs(font);
1511   }
1512      break;
1513#endif
1514
1515   default:
1516      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1517      break;
1518   }
1519   return 0;
1520}
1521
1522void vegaGetParameterfv(VGHandle object,
1523                        VGint paramType,
1524                        VGint count,
1525                        VGfloat * values)
1526{
1527   struct vg_context *ctx = vg_current_context();
1528   VGint real_count = vegaGetParameterVectorSize(object, paramType);
1529
1530   if (object == VG_INVALID_HANDLE) {
1531      vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
1532      return;
1533   }
1534
1535   if (!values || count <= 0 || count > real_count ||
1536       !is_aligned(values)) {
1537      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1538      return;
1539   }
1540
1541   switch(paramType) {
1542   case VG_PAINT_TYPE: {
1543      struct vg_paint *p = handle_to_paint(object);
1544      values[0] = paint_type(p);
1545   }
1546      break;
1547   case VG_PAINT_COLOR_RAMP_SPREAD_MODE: {
1548      struct vg_paint *p = handle_to_paint(object);
1549      values[0] = paint_spread_mode(p);
1550   }
1551      break;
1552   case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: {
1553      struct vg_paint *p = handle_to_paint(object);
1554      values[0] = paint_color_ramp_premultiplied(p);
1555   }
1556      break;
1557   case VG_PAINT_PATTERN_TILING_MODE: {
1558      values[0] = vegaGetParameterf(object, paramType);
1559   }
1560      break;
1561   case VG_PAINT_COLOR: {
1562      struct vg_paint *paint = handle_to_paint(object);
1563      paint_get_color(paint, values);
1564   }
1565      break;
1566   case VG_PAINT_COLOR_RAMP_STOPS: {
1567      struct vg_paint *paint = handle_to_paint(object);
1568      paint_ramp_stops(paint, values, count);
1569   }
1570      break;
1571   case VG_PAINT_LINEAR_GRADIENT: {
1572      struct vg_paint *paint = handle_to_paint(object);
1573      paint_linear_gradient(paint, values);
1574   }
1575      break;
1576   case VG_PAINT_RADIAL_GRADIENT: {
1577      struct vg_paint *paint = handle_to_paint(object);
1578      paint_radial_gradient(paint, values);
1579   }
1580      break;
1581
1582   case VG_PATH_FORMAT:
1583   case VG_PATH_DATATYPE:
1584   case VG_PATH_NUM_SEGMENTS:
1585   case VG_PATH_NUM_COORDS:
1586      values[0] = vegaGetParameteri(object, paramType);
1587      break;
1588   case VG_PATH_SCALE:
1589   case VG_PATH_BIAS:
1590      values[0] = vegaGetParameterf(object, paramType);
1591      break;
1592
1593   case VG_IMAGE_FORMAT:
1594   case VG_IMAGE_WIDTH:
1595   case VG_IMAGE_HEIGHT:
1596#ifdef OPENVG_VERSION_1_1
1597   case VG_FONT_NUM_GLYPHS:
1598      values[0] = vegaGetParameteri(object, paramType);
1599      break;
1600#endif
1601
1602   default:
1603      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1604      break;
1605   }
1606}
1607
1608void vegaGetParameteriv(VGHandle object,
1609                        VGint paramType,
1610                        VGint count,
1611                        VGint * values)
1612{
1613   struct vg_context *ctx = vg_current_context();
1614   VGint real_count = vegaGetParameterVectorSize(object, paramType);
1615
1616   if (object || object == VG_INVALID_HANDLE) {
1617      vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
1618      return;
1619   }
1620
1621   if (!values || count <= 0 || count > real_count ||
1622       !is_aligned(values)) {
1623      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1624      return;
1625   }
1626
1627   switch(paramType) {
1628   case VG_PAINT_TYPE:
1629   case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
1630   case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
1631   case VG_PAINT_PATTERN_TILING_MODE:
1632#ifdef OPENVG_VERSION_1_1
1633   case VG_FONT_NUM_GLYPHS:
1634      values[0] = vegaGetParameteri(object, paramType);
1635      break;
1636#endif
1637   case VG_PAINT_COLOR: {
1638      struct vg_paint *paint = handle_to_paint(object);
1639      paint_get_coloriv(paint, values);
1640   }
1641      break;
1642   case VG_PAINT_COLOR_RAMP_STOPS: {
1643      struct vg_paint *paint = handle_to_paint(object);
1644      paint_ramp_stopsi(paint, values, count);
1645   }
1646      break;
1647   case VG_PAINT_LINEAR_GRADIENT: {
1648      struct vg_paint *paint = handle_to_paint(object);
1649      paint_linear_gradienti(paint, values);
1650   }
1651      break;
1652   case VG_PAINT_RADIAL_GRADIENT: {
1653      struct vg_paint *paint = handle_to_paint(object);
1654      paint_radial_gradienti(paint, values);
1655   }
1656      break;
1657
1658   case VG_PATH_SCALE:
1659   case VG_PATH_BIAS:
1660      values[0] = vegaGetParameterf(object, paramType);
1661      break;
1662   case VG_PATH_FORMAT:
1663   case VG_PATH_DATATYPE:
1664   case VG_PATH_NUM_SEGMENTS:
1665   case VG_PATH_NUM_COORDS:
1666      values[0] = vegaGetParameteri(object, paramType);
1667      break;
1668
1669   case VG_IMAGE_FORMAT:
1670   case VG_IMAGE_WIDTH:
1671   case VG_IMAGE_HEIGHT:
1672      values[0] = vegaGetParameteri(object, paramType);
1673      break;
1674
1675   default:
1676      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
1677      break;
1678   }
1679}
1680