Home | History | Annotate | Download | only in vega
      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 
     45 static 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 
     54 static 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 
     69 void 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 
    129 void 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 
    261 void 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 
    389 void 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 
    513 VGfloat 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 
    575 VGint 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 
    690 VGint 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 
    764 void 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 
    865 void 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 
    971 void 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 
   1025 void 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 
   1100 void 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 
   1216 void 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 
   1324 VGint 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 
   1379 VGfloat 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 
   1435 VGint 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 
   1522 void 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 
   1608 void 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