hostsupport/hostopenvg/src/src/riApi.cpp
branchbug235_bringup_0
changeset 53 c2ef9095503a
parent 24 a3f46bb01be2
equal deleted inserted replaced
52:39e5f73667ba 53:c2ef9095503a
       
     1 /*------------------------------------------------------------------------
       
     2  *
       
     3  * OpenVG 1.1 Reference Implementation
       
     4  * -----------------------------------
       
     5  *
       
     6  * Copyright (c) 2007 The Khronos Group Inc.
       
     7  * Portions copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     8  *
       
     9  * Permission is hereby granted, free of charge, to any person obtaining a
       
    10  * copy of this software and /or associated documentation files
       
    11  * (the "Materials "), to deal in the Materials without restriction,
       
    12  * including without limitation the rights to use, copy, modify, merge,
       
    13  * publish, distribute, sublicense, and/or sell copies of the Materials,
       
    14  * and to permit persons to whom the Materials are furnished to do so,
       
    15  * subject to the following conditions:
       
    16  *
       
    17  * The above copyright notice and this permission notice shall be included
       
    18  * in all copies or substantial portions of the Materials.
       
    19  *
       
    20  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
       
    21  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
       
    22  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
       
    23  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
       
    24  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
       
    25  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR
       
    26  * THE USE OR OTHER DEALINGS IN THE MATERIALS.
       
    27  *
       
    28  *//**
       
    29  * \file
       
    30  * \brief	Implementations of OpenVG API functions.
       
    31  * \note	The actual processing is done in Path, Image, Rasterizer and PixelPipe classes.
       
    32  *//*-------------------------------------------------------------------*/
       
    33 
       
    34 #include "openvg.h"
       
    35 #include "vgext.h"
       
    36 #include "riContext.h"
       
    37 #include "riRasterizer.h"
       
    38 #include "riPixelPipe.h"
       
    39 #include "riPath.h"
       
    40 #include <stdio.h>
       
    41 
       
    42 //==============================================================================================
       
    43 
       
    44 namespace OpenVGRI
       
    45 {
       
    46 
       
    47 /* EGL&OS functions for use in an OpenVG implementation */
       
    48 // \note To ensure that different EGLs work in parallel, these functions must be implemented.
       
    49 // They may be wrappers if the underlying EGL is more complicated that miniEGL.
       
    50 void* eglvgGetCurrentVGContext(void);
       
    51 bool  eglvgIsInUse(void* image);
       
    52 bool  eglvgLockSurface(bool read, bool write);
       
    53 bool  eglvgUnlockSurface();
       
    54 void  OSAcquireMutex(void);
       
    55 void  OSReleaseMutex(void);
       
    56 void  eglvgGetImageDescriptor( void* image, Color::Descriptor &desc, int &width, int &height, int &stride );
       
    57 void*  eglvgGetImageData( void* image );
       
    58 
       
    59 #define RI_NO_RETVAL
       
    60 
       
    61 //this must be the first line in an API function
       
    62 #define RI_GET_CONTEXT(RETVAL) \
       
    63     OSAcquireMutex(); \
       
    64     VGContext* context = (VGContext*)eglvgGetCurrentVGContext(); \
       
    65     if(!context) \
       
    66     { \
       
    67         OSReleaseMutex(); \
       
    68         return RETVAL;\
       
    69     }
       
    70 
       
    71 #define RI_IF_ERROR(COND, ERRORCODE, RETVAL) \
       
    72     if(COND) { context->setError(ERRORCODE); OSReleaseMutex(); return RETVAL; }
       
    73 
       
    74 //all API functions must call this as their last operation (also functions that don't return values)
       
    75 //NOTE: don't evaluate anything or read state in RETVAL (it'll be executed after the mutex has been released)
       
    76 #define RI_RETURN(RETVAL) \
       
    77     { OSReleaseMutex(); \
       
    78     return RETVAL; }
       
    79 
       
    80 static bool isAligned(const void* ptr, int alignment)
       
    81 {
       
    82     RI_ASSERT(alignment == 1 || alignment == 2 || alignment == 4);
       
    83     if(((RIuintptr)ptr) & (alignment-1))
       
    84         return false;
       
    85     return true;
       
    86 }
       
    87 
       
    88 static bool isAligned(const void* ptr, VGImageFormat format)
       
    89 {
       
    90     RI_ASSERT(isValidImageFormat(format));
       
    91     int alignment = Color::formatToDescriptor(format).bitsPerPixel >> 3;
       
    92     if(alignment <= 1)
       
    93         return true;	//one bit or byte per pixel
       
    94     return isAligned(ptr, alignment);
       
    95 }
       
    96 
       
    97 bool isValidImageFormat(int f)
       
    98 {
       
    99     if(f < VG_sRGBX_8888 || f > VG_lABGR_8888_PRE)
       
   100         return false;
       
   101     return true;
       
   102 }
       
   103 
       
   104 }	//namespace OpenVGRI
       
   105 
       
   106 using namespace OpenVGRI;
       
   107 
       
   108 /*-------------------------------------------------------------------*//*!
       
   109 * \brief
       
   110 * \param
       
   111 * \return
       
   112 * \note
       
   113 *//*-------------------------------------------------------------------*/
       
   114 
       
   115 void RI_APIENTRY vgFlush(void)
       
   116 {
       
   117     RI_GET_CONTEXT(RI_NO_RETVAL);
       
   118     //the RI doesn't cache anything, so this is a no-op
       
   119     RI_RETURN(RI_NO_RETVAL);
       
   120 }
       
   121 
       
   122 /*-------------------------------------------------------------------*//*!
       
   123 * \brief
       
   124 * \param
       
   125 * \return
       
   126 * \note
       
   127 *//*-------------------------------------------------------------------*/
       
   128 
       
   129 void RI_APIENTRY vgFinish(void)
       
   130 {
       
   131     RI_GET_CONTEXT(RI_NO_RETVAL);
       
   132     //the RI doesn't cache anything, so this is a no-op
       
   133     RI_RETURN(RI_NO_RETVAL);
       
   134 }
       
   135 
       
   136 /*-------------------------------------------------------------------*//*!
       
   137 * \brief
       
   138 * \param
       
   139 * \return
       
   140 * \note
       
   141 *//*-------------------------------------------------------------------*/
       
   142 
       
   143 VGErrorCode RI_APIENTRY vgGetError(void)
       
   144 {
       
   145     RI_GET_CONTEXT(VG_NO_CONTEXT_ERROR);
       
   146     VGErrorCode error = context->m_error;
       
   147     context->m_error = VG_NO_ERROR;
       
   148     RI_RETURN(error);
       
   149 }
       
   150 
       
   151 VGErrorCode RI_APIENTRY vgPlatsimGetError(void)
       
   152 {
       
   153     RI_GET_CONTEXT(VG_NO_CONTEXT_ERROR);
       
   154     VGErrorCode error = context->m_error;
       
   155     RI_RETURN(error);
       
   156 }
       
   157 
       
   158 
       
   159 /*-------------------------------------------------------------------*//*!
       
   160 * \brief
       
   161 * \param
       
   162 * \return
       
   163 * \note
       
   164 *//*-------------------------------------------------------------------*/
       
   165 
       
   166 namespace OpenVGRI
       
   167 {
       
   168 
       
   169 RIfloat inputFloat(VGfloat f)
       
   170 {
       
   171     //this function is used for all floating point input values
       
   172     if(RI_ISNAN(f)) return 0.0f;	//convert NaN to zero
       
   173     return RI_CLAMP(f, -RI_FLOAT_MAX, RI_FLOAT_MAX);	//clamp +-inf to +-RIfloat max
       
   174 }
       
   175 
       
   176 Vector2 inputVector2(const Vector2& v)
       
   177 {
       
   178     return Vector2(inputFloat(v.x), inputFloat(v.y));
       
   179 }
       
   180 
       
   181 Color inputColor(const Color& c)
       
   182 {
       
   183     Color r = c;
       
   184     r.r = inputFloat(r.r);
       
   185     r.g = inputFloat(r.g);
       
   186     r.b = inputFloat(r.b);
       
   187     r.a = inputFloat(r.a);
       
   188     return r;
       
   189 }
       
   190 
       
   191 static int inputFloatToInt(VGfloat value)
       
   192 {
       
   193     double v = (double)floor(value);
       
   194     v = v > (double)RI_INT32_MAX ? (double)RI_INT32_MAX : v;
       
   195     v = v < (double)RI_INT32_MIN ? (double)RI_INT32_MIN : v;
       
   196     return (int)v;
       
   197 }
       
   198 
       
   199 static int paramToInt(const void* values, bool floats, int count, int i)
       
   200 {
       
   201     RI_ASSERT(i >= 0);
       
   202     if(i >= count || !values)
       
   203         return 0;
       
   204     if(floats)
       
   205         return inputFloatToInt(((const VGfloat*)values)[i]);
       
   206     return (int)((const VGint*)values)[i];
       
   207 }
       
   208 
       
   209 static RIfloat paramToFloat(const void* values, bool floats, int count, int i)
       
   210 {
       
   211     RI_ASSERT(i >= 0);
       
   212     if(i >= count || !values)
       
   213         return 0.0f;
       
   214     if(floats)
       
   215         return ((const VGfloat*)values)[i];
       
   216     return (RIfloat)((const VGint*)values)[i];
       
   217 }
       
   218 
       
   219 static void floatToParam(void* output, bool outputFloats, int count, int i, VGfloat value)
       
   220 {
       
   221     RI_ASSERT(i >= 0);
       
   222     RI_ASSERT(output);
       
   223     if(i >= count)
       
   224         return;
       
   225     if(outputFloats)
       
   226         ((VGfloat*)output)[i] = value;
       
   227     else
       
   228         ((VGint*)output)[i] = (VGint)inputFloatToInt(value);
       
   229 }
       
   230 
       
   231 static void intToParam(void* output, bool outputFloats, int count, int i, VGint value)
       
   232 {
       
   233     RI_ASSERT(i >= 0);
       
   234     RI_ASSERT(output);
       
   235     if(i >= count)
       
   236         return;
       
   237     if(outputFloats)
       
   238         ((VGfloat*)output)[i] = (VGfloat)value;
       
   239     else
       
   240         ((VGint*)output)[i] = value;
       
   241 }
       
   242 
       
   243 }	//namespace OpenVGRI
       
   244 
       
   245 /*-------------------------------------------------------------------*//*!
       
   246 * \brief
       
   247 * \param
       
   248 * \return
       
   249 * \note
       
   250 *//*-------------------------------------------------------------------*/
       
   251 
       
   252 static void setifv(VGContext* context, VGParamType type, VGint count, const void* values, bool floats)
       
   253 {
       
   254     RI_ASSERT(context);
       
   255     RI_ASSERT(!count || (count && values));
       
   256 
       
   257     int ivalue = paramToInt(values, floats, count, 0);
       
   258     RIfloat fvalue = paramToFloat(values, floats, count, 0);
       
   259 
       
   260     switch(type)
       
   261     {
       
   262     case VG_MATRIX_MODE:
       
   263         if(count != 1 || ivalue < VG_MATRIX_PATH_USER_TO_SURFACE || ivalue > VG_MATRIX_GLYPH_USER_TO_SURFACE)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   264         context->m_matrixMode = (VGMatrixMode)ivalue;
       
   265         break;
       
   266 
       
   267     case VG_FILL_RULE:
       
   268         if(count != 1 || ivalue < VG_EVEN_ODD || ivalue > VG_NON_ZERO)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   269         context->m_fillRule = (VGFillRule)ivalue;
       
   270         break;
       
   271 
       
   272     case VG_IMAGE_QUALITY:
       
   273         if(count != 1 || !(ivalue == VG_IMAGE_QUALITY_NONANTIALIASED || ivalue == VG_IMAGE_QUALITY_FASTER || ivalue == VG_IMAGE_QUALITY_BETTER))	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   274         context->m_imageQuality = (VGImageQuality)ivalue;
       
   275         break;
       
   276 
       
   277     case VG_RENDERING_QUALITY:
       
   278         if(count != 1 || !(ivalue == VG_RENDERING_QUALITY_NONANTIALIASED || ivalue == VG_RENDERING_QUALITY_FASTER || ivalue == VG_RENDERING_QUALITY_BETTER))	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   279         context->m_renderingQuality = (VGRenderingQuality)ivalue;
       
   280         break;
       
   281 
       
   282     case VG_BLEND_MODE:
       
   283         if(count != 1 || ivalue < VG_BLEND_SRC || ivalue > VG_BLEND_ADDITIVE)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   284         context->m_blendMode = (VGBlendMode)ivalue;
       
   285         break;
       
   286 
       
   287     case VG_IMAGE_MODE:
       
   288         if(count != 1 || ivalue < VG_DRAW_IMAGE_NORMAL || ivalue > VG_DRAW_IMAGE_STENCIL)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   289         context->m_imageMode = (VGImageMode)ivalue;
       
   290         break;
       
   291 
       
   292     case VG_SCISSOR_RECTS:
       
   293     {
       
   294         if(count & 3)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }	//count must be a multiple of four
       
   295         try
       
   296         {
       
   297             Array<OpenVGRI::Rectangle> scissor;
       
   298             for(int i=0;i<RI_INT_MIN(count, RI_MAX_SCISSOR_RECTANGLES*4);i+=4)
       
   299             {
       
   300                 OpenVGRI::Rectangle s;
       
   301                 s.x = paramToInt(values, floats, count, i+0);
       
   302                 s.y = paramToInt(values, floats, count, i+1);
       
   303                 s.width = paramToInt(values, floats, count, i+2);
       
   304                 s.height = paramToInt(values, floats, count, i+3);
       
   305                 scissor.push_back(s);	//throws bad_alloc
       
   306             }
       
   307             context->m_scissor.swap(scissor);	//replace context data
       
   308         }
       
   309         catch(std::bad_alloc)
       
   310         {
       
   311             context->setError(VG_OUT_OF_MEMORY_ERROR);
       
   312         }
       
   313         break;
       
   314     }
       
   315 
       
   316     case VG_COLOR_TRANSFORM:
       
   317         if(count != 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   318         context->m_colorTransform = ivalue ? VG_TRUE : VG_FALSE;
       
   319         break;
       
   320 
       
   321     case VG_COLOR_TRANSFORM_VALUES:
       
   322         if(count != 8 || !values) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   323         {
       
   324             for(int i=0;i<8;i++)
       
   325             {
       
   326                 context->m_inputColorTransformValues[i] = paramToFloat(values, floats, count, i);
       
   327                 context->m_colorTransformValues[i] = inputFloat(context->m_inputColorTransformValues[i]);
       
   328             }
       
   329         }
       
   330         break;
       
   331 
       
   332     case VG_STROKE_LINE_WIDTH:
       
   333         if(count != 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   334         context->m_inputStrokeLineWidth = fvalue;
       
   335         context->m_strokeLineWidth = inputFloat(fvalue);
       
   336         break;
       
   337 
       
   338     case VG_STROKE_CAP_STYLE:
       
   339         if(count != 1 || ivalue < VG_CAP_BUTT || ivalue > VG_CAP_SQUARE)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   340         context->m_strokeCapStyle = (VGCapStyle)ivalue;
       
   341         break;
       
   342 
       
   343     case VG_STROKE_JOIN_STYLE:
       
   344         if(count != 1 || ivalue < VG_JOIN_MITER || ivalue > VG_JOIN_BEVEL)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   345         context->m_strokeJoinStyle = (VGJoinStyle)ivalue;
       
   346         break;
       
   347 
       
   348     case VG_STROKE_MITER_LIMIT:
       
   349         if(count != 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   350         context->m_inputStrokeMiterLimit = fvalue;
       
   351         context->m_strokeMiterLimit = inputFloat(fvalue);
       
   352         break;
       
   353 
       
   354     case VG_STROKE_DASH_PATTERN:
       
   355     {
       
   356         try
       
   357         {
       
   358             Array<RIfloat> inputStrokeDashPattern;
       
   359             Array<RIfloat> strokeDashPattern;
       
   360             for(int i=0;i<RI_INT_MIN(count, RI_MAX_DASH_COUNT);i++)
       
   361             {
       
   362                 RIfloat v = paramToFloat(values, floats, count, i);
       
   363                 inputStrokeDashPattern.push_back(v);	//throws bad_alloc
       
   364                 strokeDashPattern.push_back(inputFloat(v));	//throws bad_alloc
       
   365             }
       
   366             context->m_inputStrokeDashPattern.swap(inputStrokeDashPattern);	//replace context data
       
   367             context->m_strokeDashPattern.swap(strokeDashPattern);	//replace context data
       
   368         }
       
   369         catch(std::bad_alloc)
       
   370         {
       
   371             context->setError(VG_OUT_OF_MEMORY_ERROR);
       
   372         }
       
   373         break;
       
   374     }
       
   375 
       
   376     case VG_STROKE_DASH_PHASE:
       
   377         if(count != 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   378         context->m_inputStrokeDashPhase = fvalue;
       
   379         context->m_strokeDashPhase = inputFloat(fvalue);
       
   380         break;
       
   381 
       
   382     case VG_STROKE_DASH_PHASE_RESET:
       
   383         if(count != 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   384         context->m_strokeDashPhaseReset = ivalue ? VG_TRUE : VG_FALSE;
       
   385         break;
       
   386 
       
   387     case VG_TILE_FILL_COLOR:
       
   388         if(count != 4 || !values) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   389         context->m_inputTileFillColor.set(paramToFloat(values, floats, count, 0),
       
   390                                      paramToFloat(values, floats, count, 1),
       
   391                                      paramToFloat(values, floats, count, 2),
       
   392                                      paramToFloat(values, floats, count, 3),
       
   393                                      Color::sRGBA);
       
   394         context->m_tileFillColor = inputColor(context->m_inputTileFillColor);
       
   395         break;
       
   396 
       
   397     case VG_GLYPH_ORIGIN:
       
   398         if(count != 2 || !values) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   399         context->m_inputGlyphOrigin.x = paramToFloat(values, floats, count, 0);
       
   400         context->m_inputGlyphOrigin.y = paramToFloat(values, floats, count, 1);
       
   401         context->m_glyphOrigin = inputVector2(context->m_inputGlyphOrigin);
       
   402         break;
       
   403 
       
   404     case VG_CLEAR_COLOR:
       
   405         if(count != 4 || !values) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   406         context->m_inputClearColor.set(paramToFloat(values, floats, count, 0),
       
   407                                   paramToFloat(values, floats, count, 1),
       
   408                                   paramToFloat(values, floats, count, 2),
       
   409                                   paramToFloat(values, floats, count, 3),
       
   410                                   Color::sRGBA);
       
   411         context->m_clearColor = inputColor(context->m_inputClearColor);
       
   412         break;
       
   413 
       
   414     case VG_MASKING:
       
   415         if(count != 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   416         context->m_masking = ivalue ? VG_TRUE : VG_FALSE;
       
   417         break;
       
   418 
       
   419     case VG_SCISSORING:
       
   420         if(count != 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   421         context->m_scissoring = ivalue ? VG_TRUE : VG_FALSE;
       
   422         break;
       
   423 
       
   424     case VG_PIXEL_LAYOUT:
       
   425         if(count != 1 || ivalue < VG_PIXEL_LAYOUT_UNKNOWN || ivalue > VG_PIXEL_LAYOUT_BGR_HORIZONTAL)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   426         context->m_pixelLayout = (VGPixelLayout)ivalue;
       
   427         break;
       
   428 
       
   429     case VG_SCREEN_LAYOUT:
       
   430         if(count != 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   431         break;	//setting read-only values has no effect
       
   432 
       
   433     case VG_FILTER_FORMAT_LINEAR:
       
   434         if(count != 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   435         context->m_filterFormatLinear = ivalue ? VG_TRUE : VG_FALSE;
       
   436         break;
       
   437 
       
   438     case VG_FILTER_FORMAT_PREMULTIPLIED:
       
   439         if(count != 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   440         context->m_filterFormatPremultiplied = ivalue ? VG_TRUE : VG_FALSE;
       
   441         break;
       
   442 
       
   443     case VG_FILTER_CHANNEL_MASK:
       
   444         if(count != 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   445         //undefined bits are ignored
       
   446         context->m_filterChannelMask = (VGbitfield)ivalue;
       
   447         break;
       
   448 
       
   449     case VG_MAX_SCISSOR_RECTS:
       
   450     case VG_MAX_DASH_COUNT:
       
   451     case VG_MAX_KERNEL_SIZE:
       
   452     case VG_MAX_SEPARABLE_KERNEL_SIZE:
       
   453     case VG_MAX_COLOR_RAMP_STOPS:
       
   454     case VG_MAX_IMAGE_WIDTH:
       
   455     case VG_MAX_IMAGE_HEIGHT:
       
   456     case VG_MAX_IMAGE_PIXELS:
       
   457     case VG_MAX_IMAGE_BYTES:
       
   458     case VG_MAX_FLOAT:
       
   459     case VG_MAX_GAUSSIAN_STD_DEVIATION:
       
   460         if(count != 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   461         break;	//setting read-only values has no effect
       
   462 
       
   463     default:
       
   464         context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
   465         break;
       
   466     }
       
   467 }
       
   468 
       
   469 /*-------------------------------------------------------------------*//*!
       
   470 * \brief
       
   471 * \param
       
   472 * \return
       
   473 * \note
       
   474 *//*-------------------------------------------------------------------*/
       
   475 
       
   476 void RI_APIENTRY vgSetf(VGParamType type, VGfloat value)
       
   477 {
       
   478     RI_GET_CONTEXT(RI_NO_RETVAL);
       
   479     RI_IF_ERROR(type == VG_SCISSOR_RECTS || type == VG_STROKE_DASH_PATTERN || type == VG_TILE_FILL_COLOR ||
       
   480                 type == VG_CLEAR_COLOR, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);	//vector type value
       
   481     VGfloat values[1] = {value};
       
   482     setifv(context, type, 1, values, true);
       
   483     RI_RETURN(RI_NO_RETVAL);
       
   484 }
       
   485 
       
   486 /*-------------------------------------------------------------------*//*!
       
   487 * \brief
       
   488 * \param
       
   489 * \return
       
   490 * \note
       
   491 *//*-------------------------------------------------------------------*/
       
   492 
       
   493 void RI_APIENTRY vgSeti(VGParamType type, VGint value)
       
   494 {
       
   495     RI_GET_CONTEXT(RI_NO_RETVAL);
       
   496     RI_IF_ERROR(type == VG_SCISSOR_RECTS || type == VG_STROKE_DASH_PATTERN || type == VG_TILE_FILL_COLOR ||
       
   497                 type == VG_CLEAR_COLOR, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);	//vector type value
       
   498     VGint values[1] = {value};
       
   499     setifv(context, type, 1, values, false);
       
   500     RI_RETURN(RI_NO_RETVAL);
       
   501 }
       
   502 
       
   503 /*-------------------------------------------------------------------*//*!
       
   504 * \brief
       
   505 * \param
       
   506 * \return
       
   507 * \note
       
   508 *//*-------------------------------------------------------------------*/
       
   509 
       
   510 void RI_APIENTRY vgSetiv(VGParamType type, VGint count, const VGint * values)
       
   511 {
       
   512     RI_GET_CONTEXT(RI_NO_RETVAL);
       
   513     RI_IF_ERROR(count < 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
   514     RI_IF_ERROR((!values && count > 0) || (values && !isAligned(values,4)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
   515     setifv(context, type, count, values, false);
       
   516     RI_RETURN(RI_NO_RETVAL);
       
   517 }
       
   518 
       
   519 /*-------------------------------------------------------------------*//*!
       
   520 * \brief
       
   521 * \param
       
   522 * \return
       
   523 * \note
       
   524 *//*-------------------------------------------------------------------*/
       
   525 
       
   526 void RI_APIENTRY vgSetfv(VGParamType type, VGint count, const VGfloat * values)
       
   527 {
       
   528     RI_GET_CONTEXT(RI_NO_RETVAL);
       
   529     RI_IF_ERROR(count < 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
   530     RI_IF_ERROR((!values && count > 0) || (values && !isAligned(values,4)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
   531     setifv(context, type, count, values, true);
       
   532     RI_RETURN(RI_NO_RETVAL);
       
   533 }
       
   534 
       
   535 /*-------------------------------------------------------------------*//*!
       
   536 * \brief
       
   537 * \param
       
   538 * \return
       
   539 * \note
       
   540 *//*-------------------------------------------------------------------*/
       
   541 
       
   542 static void getifv(VGContext* context, VGParamType type, VGint count, void* values, bool floats)
       
   543 {
       
   544     switch(type)
       
   545     {
       
   546     case VG_MATRIX_MODE:
       
   547         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   548         intToParam(values, floats, count, 0, context->m_matrixMode);
       
   549         break;
       
   550 
       
   551     case VG_FILL_RULE:
       
   552         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   553         intToParam(values, floats, count, 0, context->m_fillRule);
       
   554         break;
       
   555 
       
   556     case VG_IMAGE_QUALITY:
       
   557         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   558         intToParam(values, floats, count, 0, context->m_imageQuality);
       
   559         break;
       
   560 
       
   561     case VG_RENDERING_QUALITY:
       
   562         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   563         intToParam(values, floats, count, 0, context->m_renderingQuality);
       
   564         break;
       
   565 
       
   566     case VG_BLEND_MODE:
       
   567         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   568         intToParam(values, floats, count, 0, context->m_blendMode);
       
   569         break;
       
   570 
       
   571     case VG_IMAGE_MODE:
       
   572         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   573         intToParam(values, floats, count, 0, context->m_imageMode);
       
   574         break;
       
   575 
       
   576     case VG_SCISSOR_RECTS:
       
   577     {
       
   578         if(count > context->m_scissor.size()*4)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   579         for(int i=0;i<context->m_scissor.size();i++)
       
   580         {
       
   581             intToParam(values, floats, count, i*4+0, context->m_scissor[i].x);
       
   582             intToParam(values, floats, count, i*4+1, context->m_scissor[i].y);
       
   583             intToParam(values, floats, count, i*4+2, context->m_scissor[i].width);
       
   584             intToParam(values, floats, count, i*4+3, context->m_scissor[i].height);
       
   585         }
       
   586         break;
       
   587     }
       
   588 
       
   589     case VG_COLOR_TRANSFORM:
       
   590         if(count != 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   591         intToParam(values, floats, count, 0, context->m_colorTransform);
       
   592         break;
       
   593 
       
   594     case VG_COLOR_TRANSFORM_VALUES:
       
   595         if(count > 8) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   596         {
       
   597             for(int i=0;i<count;i++)
       
   598             {
       
   599                 floatToParam(values, floats, count, i, context->m_inputColorTransformValues[i]);
       
   600             }
       
   601         }
       
   602         break;
       
   603 
       
   604     case VG_STROKE_LINE_WIDTH:
       
   605         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   606         floatToParam(values, floats, count, 0, context->m_inputStrokeLineWidth);
       
   607         break;
       
   608 
       
   609     case VG_STROKE_CAP_STYLE:
       
   610         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   611         intToParam(values, floats, count, 0, context->m_strokeCapStyle);
       
   612         break;
       
   613 
       
   614     case VG_STROKE_JOIN_STYLE:
       
   615         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   616         intToParam(values, floats, count, 0, context->m_strokeJoinStyle);
       
   617         break;
       
   618 
       
   619     case VG_STROKE_MITER_LIMIT:
       
   620         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   621         floatToParam(values, floats, count, 0, context->m_inputStrokeMiterLimit);
       
   622         break;
       
   623 
       
   624     case VG_STROKE_DASH_PATTERN:
       
   625     {
       
   626         if(count > context->m_inputStrokeDashPattern.size())	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   627         for(int i=0;i<context->m_inputStrokeDashPattern.size();i++)
       
   628             floatToParam(values, floats, count, i, context->m_inputStrokeDashPattern[i]);
       
   629         break;
       
   630     }
       
   631 
       
   632     case VG_STROKE_DASH_PHASE:
       
   633         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   634         floatToParam(values, floats, count, 0, context->m_inputStrokeDashPhase);
       
   635         break;
       
   636 
       
   637     case VG_STROKE_DASH_PHASE_RESET:
       
   638         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   639         intToParam(values, floats, count, 0, context->m_strokeDashPhaseReset);
       
   640         break;
       
   641 
       
   642     case VG_TILE_FILL_COLOR:
       
   643         if(count > 4)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   644         floatToParam(values, floats, count, 0, context->m_inputTileFillColor.r);
       
   645         floatToParam(values, floats, count, 1, context->m_inputTileFillColor.g);
       
   646         floatToParam(values, floats, count, 2, context->m_inputTileFillColor.b);
       
   647         floatToParam(values, floats, count, 3, context->m_inputTileFillColor.a);
       
   648         break;
       
   649 
       
   650     case VG_CLEAR_COLOR:
       
   651         if(count > 4)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   652         floatToParam(values, floats, count, 0, context->m_inputClearColor.r);
       
   653         floatToParam(values, floats, count, 1, context->m_inputClearColor.g);
       
   654         floatToParam(values, floats, count, 2, context->m_inputClearColor.b);
       
   655         floatToParam(values, floats, count, 3, context->m_inputClearColor.a);
       
   656         break;
       
   657 
       
   658     case VG_GLYPH_ORIGIN:
       
   659         if(count > 2)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   660         floatToParam(values, floats, count, 0, context->m_inputGlyphOrigin.x);
       
   661         floatToParam(values, floats, count, 1, context->m_inputGlyphOrigin.y);
       
   662         break;
       
   663 
       
   664     case VG_MASKING:
       
   665         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   666         intToParam(values, floats, count, 0, context->m_masking);
       
   667         break;
       
   668 
       
   669     case VG_SCISSORING:
       
   670         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   671         intToParam(values, floats, count, 0, context->m_scissoring);
       
   672         break;
       
   673 
       
   674     case VG_PIXEL_LAYOUT:
       
   675         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   676         intToParam(values, floats, count, 0, context->m_pixelLayout);
       
   677         break;
       
   678 
       
   679     case VG_SCREEN_LAYOUT:
       
   680         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   681         intToParam(values, floats, count, 0, VG_PIXEL_LAYOUT_UNKNOWN);
       
   682         break;
       
   683 
       
   684     case VG_FILTER_FORMAT_LINEAR:
       
   685         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   686         intToParam(values, floats, count, 0, context->m_filterFormatLinear);
       
   687         break;
       
   688 
       
   689     case VG_FILTER_FORMAT_PREMULTIPLIED:
       
   690         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   691         intToParam(values, floats, count, 0, context->m_filterFormatPremultiplied);
       
   692         break;
       
   693 
       
   694     case VG_FILTER_CHANNEL_MASK:
       
   695         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   696         intToParam(values, floats, count, 0, context->m_filterChannelMask);
       
   697         break;
       
   698 
       
   699     case VG_MAX_SCISSOR_RECTS:
       
   700         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   701         intToParam(values, floats, count, 0, RI_MAX_SCISSOR_RECTANGLES);
       
   702         break;
       
   703 
       
   704     case VG_MAX_DASH_COUNT:
       
   705         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   706         intToParam(values, floats, count, 0, RI_MAX_DASH_COUNT);
       
   707         break;
       
   708 
       
   709     case VG_MAX_KERNEL_SIZE:
       
   710         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   711         intToParam(values, floats, count, 0, RI_MAX_KERNEL_SIZE);
       
   712         break;
       
   713 
       
   714     case VG_MAX_SEPARABLE_KERNEL_SIZE:
       
   715         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   716         intToParam(values, floats, count, 0, RI_MAX_SEPARABLE_KERNEL_SIZE);
       
   717         break;
       
   718 
       
   719     case VG_MAX_COLOR_RAMP_STOPS:
       
   720         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   721         intToParam(values, floats, count, 0, RI_MAX_COLOR_RAMP_STOPS);
       
   722         break;
       
   723 
       
   724     case VG_MAX_IMAGE_WIDTH:
       
   725         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   726         intToParam(values, floats, count, 0, RI_MAX_IMAGE_WIDTH);
       
   727         break;
       
   728 
       
   729     case VG_MAX_IMAGE_HEIGHT:
       
   730         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   731         intToParam(values, floats, count, 0, RI_MAX_IMAGE_HEIGHT);
       
   732         break;
       
   733 
       
   734     case VG_MAX_IMAGE_PIXELS:
       
   735         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   736         intToParam(values, floats, count, 0, RI_MAX_IMAGE_PIXELS);
       
   737         break;
       
   738 
       
   739     case VG_MAX_IMAGE_BYTES:
       
   740         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   741         intToParam(values, floats, count, 0, RI_MAX_IMAGE_BYTES);
       
   742         break;
       
   743 
       
   744     case VG_MAX_FLOAT:
       
   745         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   746         floatToParam(values, floats, count, 0, RI_FLOAT_MAX);
       
   747         break;
       
   748 
       
   749     case VG_MAX_GAUSSIAN_STD_DEVIATION:
       
   750         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   751         floatToParam(values, floats, count, 0, RI_MAX_GAUSSIAN_STD_DEVIATION);
       
   752         break;
       
   753 
       
   754     default:
       
   755         context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
   756         break;
       
   757     }
       
   758 }
       
   759 
       
   760 /*-------------------------------------------------------------------*//*!
       
   761 * \brief
       
   762 * \param
       
   763 * \return
       
   764 * \note
       
   765 *//*-------------------------------------------------------------------*/
       
   766 
       
   767 VGfloat RI_APIENTRY vgGetf(VGParamType type)
       
   768 {
       
   769     RI_GET_CONTEXT(0.0f);
       
   770     RI_IF_ERROR(type == VG_SCISSOR_RECTS || type == VG_STROKE_DASH_PATTERN || type == VG_TILE_FILL_COLOR ||
       
   771                 type == VG_CLEAR_COLOR, VG_ILLEGAL_ARGUMENT_ERROR, 0.0f);	//vector type value
       
   772     RIfloat ret = 0.0f;
       
   773     getifv(context, type, 1, &ret, true);
       
   774     RI_RETURN(ret);
       
   775 }
       
   776 
       
   777 /*-------------------------------------------------------------------*//*!
       
   778 * \brief
       
   779 * \param
       
   780 * \return
       
   781 * \note
       
   782 *//*-------------------------------------------------------------------*/
       
   783 
       
   784 VGint RI_APIENTRY vgGeti(VGParamType type)
       
   785 {
       
   786     RI_GET_CONTEXT(0);
       
   787     RI_IF_ERROR(type == VG_SCISSOR_RECTS || type == VG_STROKE_DASH_PATTERN || type == VG_TILE_FILL_COLOR ||
       
   788                 type == VG_CLEAR_COLOR, VG_ILLEGAL_ARGUMENT_ERROR, 0);	//vector type value
       
   789     VGint ret = 0;
       
   790     getifv(context, type, 1, &ret, false);
       
   791     RI_RETURN(ret);
       
   792 }
       
   793 
       
   794 /*-------------------------------------------------------------------*//*!
       
   795 * \brief
       
   796 * \param
       
   797 * \return
       
   798 * \note
       
   799 *//*-------------------------------------------------------------------*/
       
   800 
       
   801 void RI_APIENTRY vgGetiv(VGParamType type, VGint count, VGint * values)
       
   802 {
       
   803     RI_GET_CONTEXT(RI_NO_RETVAL);
       
   804     RI_IF_ERROR(count <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
   805     RI_IF_ERROR(!values || !isAligned(values,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
   806     getifv(context, type, count, values, false);
       
   807     RI_RETURN(RI_NO_RETVAL);
       
   808 }
       
   809 
       
   810 /*-------------------------------------------------------------------*//*!
       
   811 * \brief
       
   812 * \param
       
   813 * \return
       
   814 * \note
       
   815 *//*-------------------------------------------------------------------*/
       
   816 
       
   817 void RI_APIENTRY vgGetfv(VGParamType type, VGint count, VGfloat * values)
       
   818 {
       
   819     RI_GET_CONTEXT(RI_NO_RETVAL);
       
   820     RI_IF_ERROR(count <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
   821     RI_IF_ERROR(!values || !isAligned(values,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
   822     getifv(context, type, count, values, true);
       
   823     RI_RETURN(RI_NO_RETVAL);
       
   824 }
       
   825 
       
   826 /*-------------------------------------------------------------------*//*!
       
   827 * \brief
       
   828 * \param
       
   829 * \return
       
   830 * \note
       
   831 *//*-------------------------------------------------------------------*/
       
   832 
       
   833 VGint RI_APIENTRY vgGetVectorSize(VGParamType type)
       
   834 {
       
   835     RI_GET_CONTEXT(0);
       
   836     VGint ret = 0;
       
   837     switch(type)
       
   838     {
       
   839     case VG_MATRIX_MODE:
       
   840     case VG_FILL_RULE:
       
   841     case VG_IMAGE_QUALITY:
       
   842     case VG_RENDERING_QUALITY:
       
   843     case VG_BLEND_MODE:
       
   844     case VG_IMAGE_MODE:
       
   845         ret = 1;
       
   846         break;
       
   847 
       
   848     case VG_SCISSOR_RECTS:
       
   849         ret = 4*context->m_scissor.size();
       
   850         break;
       
   851 
       
   852     case VG_COLOR_TRANSFORM:
       
   853         ret = 1;
       
   854         break;
       
   855 
       
   856     case VG_COLOR_TRANSFORM_VALUES:
       
   857         ret = 8;
       
   858         break;
       
   859 
       
   860     case VG_STROKE_LINE_WIDTH:
       
   861     case VG_STROKE_CAP_STYLE:
       
   862     case VG_STROKE_JOIN_STYLE:
       
   863     case VG_STROKE_MITER_LIMIT:
       
   864         ret = 1;
       
   865         break;
       
   866 
       
   867     case VG_STROKE_DASH_PATTERN:
       
   868         ret = context->m_inputStrokeDashPattern.size();
       
   869         break;
       
   870 
       
   871     case VG_STROKE_DASH_PHASE:
       
   872     case VG_STROKE_DASH_PHASE_RESET:
       
   873         ret = 1;
       
   874         break;
       
   875 
       
   876     case VG_TILE_FILL_COLOR:
       
   877     case VG_CLEAR_COLOR:
       
   878         ret = 4;
       
   879         break;
       
   880 
       
   881     case VG_GLYPH_ORIGIN:
       
   882         ret = 2;
       
   883         break;
       
   884 
       
   885     case VG_MASKING:
       
   886     case VG_SCISSORING:
       
   887     case VG_PIXEL_LAYOUT:
       
   888     case VG_SCREEN_LAYOUT:
       
   889     case VG_FILTER_FORMAT_LINEAR:
       
   890     case VG_FILTER_FORMAT_PREMULTIPLIED:
       
   891     case VG_FILTER_CHANNEL_MASK:
       
   892     case VG_MAX_SCISSOR_RECTS:
       
   893     case VG_MAX_DASH_COUNT:
       
   894     case VG_MAX_KERNEL_SIZE:
       
   895     case VG_MAX_SEPARABLE_KERNEL_SIZE:
       
   896     case VG_MAX_COLOR_RAMP_STOPS:
       
   897     case VG_MAX_IMAGE_WIDTH:
       
   898     case VG_MAX_IMAGE_HEIGHT:
       
   899     case VG_MAX_IMAGE_PIXELS:
       
   900     case VG_MAX_IMAGE_BYTES:
       
   901     case VG_MAX_FLOAT:
       
   902     case VG_MAX_GAUSSIAN_STD_DEVIATION:
       
   903         ret = 1;
       
   904         break;
       
   905 
       
   906     default:
       
   907         context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
   908         break;
       
   909     }
       
   910     RI_RETURN(ret);
       
   911 }
       
   912 
       
   913 /*-------------------------------------------------------------------*//*!
       
   914 * \brief
       
   915 * \param
       
   916 * \return
       
   917 * \note
       
   918 *//*-------------------------------------------------------------------*/
       
   919 
       
   920 static void setPaintParameterifv(VGContext* context, Paint* paint, VGPaintParamType paramType, VGint count, const void* values, bool floats)
       
   921 {
       
   922     RI_ASSERT(context);
       
   923     RI_ASSERT(paint);
       
   924 
       
   925     int ivalue = paramToInt(values, floats, count, 0);
       
   926 
       
   927     switch(paramType)
       
   928     {
       
   929     case VG_PAINT_TYPE:
       
   930         if(count != 1 || ivalue < VG_PAINT_TYPE_COLOR || ivalue > VG_PAINT_TYPE_PATTERN)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   931         paint->m_paintType = (VGPaintType)ivalue;
       
   932         break;
       
   933 
       
   934     case VG_PAINT_COLOR:
       
   935         RI_TRACE("\n***** Setting solid color to paint.\n");
       
   936         RI_TRACE("** ptr: %x\n", (int)paint);
       
   937         if(count != 4)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   938         paint->m_inputPaintColor.set(paramToFloat(values, floats, count, 0),
       
   939                                      paramToFloat(values, floats, count, 1),
       
   940                                      paramToFloat(values, floats, count, 2),
       
   941                                      paramToFloat(values, floats, count, 3),
       
   942                                      Color::sRGBA);
       
   943         RI_TRACE("** input solid color: [%.3f %.3f %.3f %.4f]\n", paint->m_inputPaintColor.r, paint->m_inputPaintColor.g, paint->m_inputPaintColor.b, paint->m_inputPaintColor.a);
       
   944         paint->setColor(inputColor(paint->m_inputPaintColor));
       
   945         RI_TRACE("** -> [%.3f %.3f %.3f %.3f]\n", paint->m_paintColor.r, paint->m_paintColor.g, paint->m_paintColor.b, paint->m_paintColor.a);
       
   946         break;
       
   947 
       
   948     case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
       
   949         if(count != 1 || ivalue < VG_COLOR_RAMP_SPREAD_PAD || ivalue > VG_COLOR_RAMP_SPREAD_REFLECT)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
   950         paint->m_colorRampSpreadMode = (VGColorRampSpreadMode)ivalue;
       
   951         break;
       
   952 
       
   953     case VG_PAINT_COLOR_RAMP_STOPS:
       
   954     {
       
   955         int numStops = count/5;
       
   956         if(count != numStops*5)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }	//count must be a multiple of five
       
   957         try
       
   958         {
       
   959             Array<Paint::GradientStop> colorRampStops;
       
   960             Array<Paint::GradientStop> inputColorRampStops;
       
   961             RIfloat prevOffset = -RI_FLOAT_MAX;
       
   962             bool valid = true;
       
   963             for(int i=0;i<RI_INT_MIN(numStops, RI_MAX_COLOR_RAMP_STOPS);i++)	//NOTE: ignores the final stop if there is not enough parameters
       
   964             {
       
   965                 Paint::GradientStop gs;
       
   966                 gs.offset = paramToFloat(values, floats, count, i*5);
       
   967                 gs.color.set(paramToFloat(values, floats, count, i*5+1),
       
   968                              paramToFloat(values, floats, count, i*5+2),
       
   969                              paramToFloat(values, floats, count, i*5+3),
       
   970                              paramToFloat(values, floats, count, i*5+4),
       
   971                              Color::sRGBA);
       
   972                 inputColorRampStops.push_back(gs);
       
   973 
       
   974                 if(gs.offset < prevOffset)
       
   975                     valid = false;	//decreasing sequence, ignore it
       
   976 
       
   977                 if(gs.offset >= 0.0f && gs.offset <= 1.0f)
       
   978                 {
       
   979                     gs.color.clamp();
       
   980 
       
   981                     if(!colorRampStops.size() && gs.offset > 0.0f)
       
   982                     {	//the first valid stop is not at 0, replicate the first one
       
   983                         RIfloat tmp = gs.offset;
       
   984                         gs.offset = 0.0f;
       
   985                         colorRampStops.push_back(gs);	//throws bad_alloc
       
   986                         gs.offset = tmp;
       
   987                     }
       
   988                     colorRampStops.push_back(gs);	//throws bad_alloc
       
   989                 }
       
   990                 prevOffset = gs.offset;
       
   991             }
       
   992             if(valid && colorRampStops.size() && colorRampStops[colorRampStops.size()-1].offset < 1.0f)
       
   993             {	//there is at least one stop, but the last one is not at 1, replicate the last one
       
   994                 Paint::GradientStop gs = colorRampStops[colorRampStops.size()-1];
       
   995                 gs.offset = 1.0f;
       
   996                 colorRampStops.push_back(gs);	//throws bad_alloc
       
   997             }
       
   998             if(!valid || !colorRampStops.size())
       
   999             {	//there are no valid stops, add implicit stops
       
  1000                 colorRampStops.clear();
       
  1001                 Paint::GradientStop gs;
       
  1002                 gs.offset = 0.0f;
       
  1003                 gs.color.set(0,0,0,1,Color::sRGBA);
       
  1004                 colorRampStops.push_back(gs);	//throws bad_alloc
       
  1005                 gs.offset = 1.0f;
       
  1006                 gs.color.set(1,1,1,1,Color::sRGBA);
       
  1007                 colorRampStops.push_back(gs);	//throws bad_alloc
       
  1008             }
       
  1009             RI_ASSERT(colorRampStops.size() >= 2 && colorRampStops.size() <= RI_MAX_COLOR_RAMP_STOPS);
       
  1010             //paint->m_colorRampStops.swap(colorRampStops);	//set paint array
       
  1011             //paint->m_inputColorRampStops.swap(inputColorRampStops);	//set paint array
       
  1012             paint->setGradientStops(inputColorRampStops, colorRampStops);
       
  1013             //paint->generateLUT();
       
  1014         }
       
  1015         catch(std::bad_alloc)
       
  1016         {
       
  1017             context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  1018         }
       
  1019         break;
       
  1020     }
       
  1021 
       
  1022     case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
       
  1023         if(count != 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1024         paint->m_colorRampPremultiplied = ivalue ? VG_TRUE : VG_FALSE;
       
  1025         break;
       
  1026 
       
  1027     case VG_PAINT_LINEAR_GRADIENT:
       
  1028         if(count != 4)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1029         paint->m_inputLinearGradientPoint0.set(paramToFloat(values, floats, count, 0),
       
  1030                                           paramToFloat(values, floats, count, 1));
       
  1031         paint->m_inputLinearGradientPoint1.set(paramToFloat(values, floats, count, 2),
       
  1032                                           paramToFloat(values, floats, count, 3));
       
  1033         paint->setLinearGradient(
       
  1034             inputVector2(paint->m_inputLinearGradientPoint0),
       
  1035             inputVector2(paint->m_inputLinearGradientPoint1));
       
  1036 
       
  1037         break;
       
  1038 
       
  1039     case VG_PAINT_RADIAL_GRADIENT:
       
  1040         if(count != 5)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1041         paint->m_inputRadialGradientCenter.set(paramToFloat(values, floats, count, 0),
       
  1042                                           paramToFloat(values, floats, count, 1));
       
  1043         paint->m_inputRadialGradientFocalPoint.set(paramToFloat(values, floats, count, 2),
       
  1044                                               paramToFloat(values, floats, count, 3));
       
  1045         paint->m_inputRadialGradientRadius = paramToFloat(values, floats, count, 4);
       
  1046         paint->setRadialGradient(
       
  1047             inputVector2(paint->m_inputRadialGradientCenter),
       
  1048             inputVector2(paint->m_inputRadialGradientFocalPoint),
       
  1049             inputFloat(paint->m_inputRadialGradientRadius));
       
  1050         //paint->m_radialGradientCenter = inputVector2(paint->m_inputRadialGradientCenter);
       
  1051         //paint->m_radialGradientFocalPoint = inputVector2(paint->m_inputRadialGradientFocalPoint);
       
  1052         //paint->m_radialGradientRadius = inputFloat(paint->m_inputRadialGradientRadius);
       
  1053         break;
       
  1054 
       
  1055     case VG_PAINT_PATTERN_TILING_MODE:
       
  1056         if(count != 1 || ivalue < VG_TILE_FILL || ivalue > VG_TILE_REFLECT)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1057         paint->m_patternTilingMode = (VGTilingMode)ivalue;
       
  1058         break;
       
  1059 
       
  1060     default:
       
  1061         context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1062         break;
       
  1063     }
       
  1064 }
       
  1065 
       
  1066 /*-------------------------------------------------------------------*//*!
       
  1067 * \brief
       
  1068 * \param
       
  1069 * \return
       
  1070 * \note
       
  1071 *//*-------------------------------------------------------------------*/
       
  1072 
       
  1073 void RI_APIENTRY vgSetParameterf(VGHandle object, VGint paramType, VGfloat value)
       
  1074 {
       
  1075     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1076     bool isImage = context->isValidImage(object);
       
  1077     bool isPath = context->isValidPath(object);
       
  1078     bool isPaint = context->isValidPaint(object);
       
  1079     bool isMaskLayer = context->isValidMaskLayer(object);
       
  1080     bool isFont = context->isValidFont(object);
       
  1081     RI_IF_ERROR(!isImage && !isPath && !isPaint && !isMaskLayer && !isFont, VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid object handle
       
  1082     RI_IF_ERROR(paramType == VG_PAINT_COLOR || paramType == VG_PAINT_COLOR_RAMP_STOPS || paramType == VG_PAINT_LINEAR_GRADIENT ||
       
  1083                 paramType == VG_PAINT_RADIAL_GRADIENT, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //vector valued parameter
       
  1084     VGfloat values[1] = {value};
       
  1085     if(isImage)
       
  1086     {	//read only, the function does nothing
       
  1087         RI_ASSERT(!isPath && !isPaint && !isMaskLayer && !isFont);
       
  1088         if(paramType < VG_IMAGE_FORMAT || paramType > VG_IMAGE_HEIGHT)
       
  1089             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1090     }
       
  1091     else if(isPath)
       
  1092     {	//read only, the function does nothing
       
  1093         RI_ASSERT(!isImage && !isPaint && !isMaskLayer && !isFont);
       
  1094         if(paramType < VG_PATH_FORMAT || paramType > VG_PATH_NUM_COORDS)
       
  1095             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1096     }
       
  1097     else if(isPaint)
       
  1098     {
       
  1099         RI_ASSERT(!isImage && !isPath && !isMaskLayer && !isFont);
       
  1100         setPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, 1, values, true);
       
  1101     }
       
  1102     else if(isMaskLayer)
       
  1103     {
       
  1104         RI_ASSERT(!isImage && !isPath && !isPaint && !isFont);
       
  1105         context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1106     }
       
  1107     else
       
  1108     {	//read only, the function does nothing
       
  1109         RI_ASSERT(!isImage && !isPath && !isPaint && !isMaskLayer && isFont);
       
  1110         if (paramType != VG_FONT_NUM_GLYPHS)
       
  1111             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1112     }
       
  1113     RI_RETURN(RI_NO_RETVAL);
       
  1114 }
       
  1115 
       
  1116 /*-------------------------------------------------------------------*//*!
       
  1117 * \brief
       
  1118 * \param
       
  1119 * \return
       
  1120 * \note
       
  1121 *//*-------------------------------------------------------------------*/
       
  1122 
       
  1123 void RI_APIENTRY vgSetParameteri(VGHandle object, VGint paramType, VGint value)
       
  1124 {
       
  1125     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1126     bool isImage = context->isValidImage(object);
       
  1127     bool isPath = context->isValidPath(object);
       
  1128     bool isPaint = context->isValidPaint(object);
       
  1129     bool isMaskLayer = context->isValidMaskLayer(object);
       
  1130     bool isFont = context->isValidFont(object);
       
  1131     RI_IF_ERROR(!isImage && !isPath && !isPaint && !isMaskLayer && !isFont, VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid object handle
       
  1132     RI_IF_ERROR(paramType == VG_PAINT_COLOR || paramType == VG_PAINT_COLOR_RAMP_STOPS || paramType == VG_PAINT_LINEAR_GRADIENT ||
       
  1133                 paramType == VG_PAINT_RADIAL_GRADIENT, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);	//vector valued parameter
       
  1134     VGint values[1] = {value};
       
  1135     if(isImage)
       
  1136     {	//read only, the function does nothing
       
  1137         RI_ASSERT(!isPath && !isPaint && !isMaskLayer && !isFont);
       
  1138         if(paramType < VG_IMAGE_FORMAT || paramType > VG_IMAGE_HEIGHT)
       
  1139             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1140     }
       
  1141     else if(isPath)
       
  1142     {	//read only, the function does nothing
       
  1143         RI_ASSERT(!isImage && !isPaint && !isMaskLayer && !isFont);
       
  1144         if(paramType < VG_PATH_FORMAT || paramType > VG_PATH_NUM_COORDS)
       
  1145             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1146     }
       
  1147     else if(isPaint)
       
  1148     {
       
  1149         RI_ASSERT(!isImage && !isPath && !isMaskLayer && !isFont);
       
  1150         setPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, 1, values, false);
       
  1151     }
       
  1152     else if(isMaskLayer)
       
  1153     {
       
  1154         RI_ASSERT(!isImage && !isPath && !isPaint && !isFont);
       
  1155         context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1156     }
       
  1157     else
       
  1158     {	//read only, the function does nothing
       
  1159         RI_ASSERT(!isImage && !isPath && !isPaint && !isMaskLayer && isFont);
       
  1160         if (paramType != VG_FONT_NUM_GLYPHS)
       
  1161             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1162     }
       
  1163     RI_RETURN(RI_NO_RETVAL);
       
  1164 }
       
  1165 
       
  1166 /*-------------------------------------------------------------------*//*!
       
  1167 * \brief
       
  1168 * \param
       
  1169 * \return
       
  1170 * \note
       
  1171 *//*-------------------------------------------------------------------*/
       
  1172 
       
  1173 void RI_APIENTRY vgSetParameterfv(VGHandle object, VGint paramType, VGint count, const VGfloat * values)
       
  1174 {
       
  1175     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1176     RI_IF_ERROR(count < 0 || (!values && count > 0) || (values && !isAligned(values,4)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  1177     bool isImage = context->isValidImage(object);
       
  1178     bool isPath = context->isValidPath(object);
       
  1179     bool isPaint = context->isValidPaint(object);
       
  1180     bool isMaskLayer = context->isValidMaskLayer(object);
       
  1181     bool isFont = context->isValidFont(object);
       
  1182     RI_IF_ERROR(!isImage && !isPath && !isPaint && !isMaskLayer && !isFont, VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid object handle
       
  1183     if(isImage)
       
  1184     {	//read only, the function does nothing
       
  1185         RI_ASSERT(!isPath && !isPaint && !isMaskLayer && !isFont);
       
  1186         if(paramType < VG_IMAGE_FORMAT || paramType > VG_IMAGE_HEIGHT)
       
  1187             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1188     }
       
  1189     else if(isPath)
       
  1190     {	//read only, the function does nothing
       
  1191         RI_ASSERT(!isImage && !isPaint && !isMaskLayer && !isFont);
       
  1192         if(paramType < VG_PATH_FORMAT || paramType > VG_PATH_NUM_COORDS)
       
  1193             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1194     }
       
  1195     else if(isPaint)
       
  1196     {
       
  1197         RI_ASSERT(!isImage && !isPath && !isMaskLayer && !isFont);
       
  1198         setPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, count, values, true);
       
  1199     }
       
  1200     else if(isMaskLayer)
       
  1201     {
       
  1202         RI_ASSERT(!isImage && !isPath && !isPaint && !isFont);
       
  1203         context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1204     }
       
  1205     else
       
  1206     {	//read only, the function does nothing
       
  1207         RI_ASSERT(!isImage && !isPath && !isPaint && !isMaskLayer && isFont);
       
  1208         if (paramType != VG_FONT_NUM_GLYPHS)
       
  1209             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1210     }
       
  1211     RI_RETURN(RI_NO_RETVAL);
       
  1212 }
       
  1213 
       
  1214 /*-------------------------------------------------------------------*//*!
       
  1215 * \brief
       
  1216 * \param
       
  1217 * \return
       
  1218 * \note
       
  1219 *//*-------------------------------------------------------------------*/
       
  1220 
       
  1221 void RI_APIENTRY vgSetParameteriv(VGHandle object, VGint paramType, VGint count, const VGint * values)
       
  1222 {
       
  1223     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1224     RI_IF_ERROR(count < 0 || (!values && count > 0) || (values && !isAligned(values,4)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  1225     bool isImage = context->isValidImage(object);
       
  1226     bool isPath = context->isValidPath(object);
       
  1227     bool isPaint = context->isValidPaint(object);
       
  1228     bool isMaskLayer = context->isValidMaskLayer(object);
       
  1229     bool isFont = context->isValidFont(object);
       
  1230     RI_IF_ERROR(!isImage && !isPath && !isPaint && !isMaskLayer && !isFont, VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid object handle
       
  1231     if(isImage)
       
  1232     {	//read only, the function does nothing
       
  1233         RI_ASSERT(!isPath && !isPaint && !isMaskLayer && !isFont);
       
  1234         if(paramType < VG_IMAGE_FORMAT || paramType > VG_IMAGE_HEIGHT)
       
  1235             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1236     }
       
  1237     else if(isPath)
       
  1238     {	//read only, the function does nothing
       
  1239         RI_ASSERT(!isImage && !isPaint && !isMaskLayer && !isFont);
       
  1240         if(paramType < VG_PATH_FORMAT || paramType > VG_PATH_NUM_COORDS)
       
  1241             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1242     }
       
  1243     else if(isPaint)
       
  1244     {
       
  1245         RI_ASSERT(!isImage && !isPath && !isMaskLayer && !isFont);
       
  1246         setPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, count, values, false);
       
  1247     }
       
  1248     else if(isMaskLayer)
       
  1249     {
       
  1250         RI_ASSERT(!isImage && !isPath && !isPaint && !isFont);
       
  1251         context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1252     }
       
  1253     else
       
  1254     {	//read only, the function does nothing
       
  1255         RI_ASSERT(!isImage && !isPath && !isPaint && !isMaskLayer && isFont);
       
  1256         if (paramType != VG_FONT_NUM_GLYPHS)
       
  1257             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1258     }
       
  1259     RI_RETURN(RI_NO_RETVAL);
       
  1260 }
       
  1261 
       
  1262 /*-------------------------------------------------------------------*//*!
       
  1263 * \brief
       
  1264 * \param
       
  1265 * \return
       
  1266 * \note
       
  1267 *//*-------------------------------------------------------------------*/
       
  1268 
       
  1269 static void getPaintParameterifv(VGContext* context, Paint* paint, VGPaintParamType type, VGint count, void* values, bool floats)
       
  1270 {
       
  1271     switch(type)
       
  1272     {
       
  1273     case VG_PAINT_TYPE:
       
  1274         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1275         intToParam(values, floats, count, 0, paint->m_paintType);
       
  1276         break;
       
  1277 
       
  1278     case VG_PAINT_COLOR:
       
  1279         if(count > 4)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1280         floatToParam(values, floats, count, 0, paint->m_inputPaintColor.r);
       
  1281         floatToParam(values, floats, count, 1, paint->m_inputPaintColor.g);
       
  1282         floatToParam(values, floats, count, 2, paint->m_inputPaintColor.b);
       
  1283         floatToParam(values, floats, count, 3, paint->m_inputPaintColor.a);
       
  1284         break;
       
  1285 
       
  1286     case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
       
  1287         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1288         intToParam(values, floats, count, 0, paint->m_colorRampSpreadMode);
       
  1289         break;
       
  1290 
       
  1291     case VG_PAINT_COLOR_RAMP_STOPS:
       
  1292         {
       
  1293             if(count > paint->m_inputColorRampStops.size()*5)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1294             int j = 0;
       
  1295             for(int i=0;i<paint->m_inputColorRampStops.size();i++)
       
  1296             {
       
  1297                 floatToParam(values, floats, count, j++, paint->m_inputColorRampStops[i].offset);
       
  1298                 floatToParam(values, floats, count, j++, paint->m_inputColorRampStops[i].color.r);
       
  1299                 floatToParam(values, floats, count, j++, paint->m_inputColorRampStops[i].color.g);
       
  1300                 floatToParam(values, floats, count, j++, paint->m_inputColorRampStops[i].color.b);
       
  1301                 floatToParam(values, floats, count, j++, paint->m_inputColorRampStops[i].color.a);
       
  1302             }
       
  1303             break;
       
  1304         }
       
  1305 
       
  1306     case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
       
  1307         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1308         intToParam(values, floats, count, 0, paint->m_colorRampPremultiplied);
       
  1309         break;
       
  1310 
       
  1311     case VG_PAINT_LINEAR_GRADIENT:
       
  1312         if(count > 4)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1313         floatToParam(values, floats, count, 0, paint->m_inputLinearGradientPoint0.x);
       
  1314         floatToParam(values, floats, count, 1, paint->m_inputLinearGradientPoint0.y);
       
  1315         floatToParam(values, floats, count, 2, paint->m_inputLinearGradientPoint1.x);
       
  1316         floatToParam(values, floats, count, 3, paint->m_inputLinearGradientPoint1.y);
       
  1317         break;
       
  1318 
       
  1319     case VG_PAINT_RADIAL_GRADIENT:
       
  1320         if(count > 5)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1321         floatToParam(values, floats, count, 0, paint->m_inputRadialGradientCenter.x);
       
  1322         floatToParam(values, floats, count, 1, paint->m_inputRadialGradientCenter.y);
       
  1323         floatToParam(values, floats, count, 2, paint->m_inputRadialGradientFocalPoint.x);
       
  1324         floatToParam(values, floats, count, 3, paint->m_inputRadialGradientFocalPoint.y);
       
  1325         floatToParam(values, floats, count, 4, paint->m_inputRadialGradientRadius);
       
  1326         break;
       
  1327 
       
  1328     case VG_PAINT_PATTERN_TILING_MODE:
       
  1329         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1330         intToParam(values, floats, count, 0, paint->m_patternTilingMode);
       
  1331         break;
       
  1332 
       
  1333     default:
       
  1334         context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1335         break;
       
  1336     }
       
  1337 }
       
  1338 
       
  1339 /*-------------------------------------------------------------------*//*!
       
  1340 * \brief
       
  1341 * \param
       
  1342 * \return
       
  1343 * \note
       
  1344 *//*-------------------------------------------------------------------*/
       
  1345 
       
  1346 static void getPathParameterifv(VGContext* context, Path* path, VGPathParamType type, VGint count, void* values, bool floats)
       
  1347 {
       
  1348     switch(type)
       
  1349     {
       
  1350     case VG_PATH_FORMAT:
       
  1351         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1352         intToParam(values, floats, count, 0, path->getFormat());
       
  1353         break;
       
  1354 
       
  1355     case VG_PATH_DATATYPE:
       
  1356         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1357         intToParam(values, floats, count, 0, path->getDatatype());
       
  1358         break;
       
  1359 
       
  1360     case VG_PATH_SCALE:
       
  1361         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1362         floatToParam(values, floats, count, 0, path->getScale());
       
  1363         break;
       
  1364 
       
  1365     case VG_PATH_BIAS:
       
  1366         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1367         floatToParam(values, floats, count, 0, path->getBias());
       
  1368         break;
       
  1369 
       
  1370     case VG_PATH_NUM_SEGMENTS:
       
  1371         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1372         intToParam(values, floats, count, 0, path->getNumSegments());
       
  1373         break;
       
  1374 
       
  1375     case VG_PATH_NUM_COORDS:
       
  1376         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1377         intToParam(values, floats, count, 0, path->getNumCoordinates());
       
  1378         break;
       
  1379 
       
  1380     default:
       
  1381         context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1382         break;
       
  1383     }
       
  1384 }
       
  1385 
       
  1386 /*-------------------------------------------------------------------*//*!
       
  1387 * \brief
       
  1388 * \param
       
  1389 * \return
       
  1390 * \note
       
  1391 *//*-------------------------------------------------------------------*/
       
  1392 
       
  1393 static void getImageParameterifv(VGContext* context, Image* image, VGImageParamType type, VGint count, void* values, bool floats)
       
  1394 {
       
  1395     switch(type)
       
  1396     {
       
  1397     case VG_IMAGE_FORMAT:
       
  1398         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1399         RI_ASSERT(isValidImageFormat(image->getDescriptor().vgFormat));
       
  1400         intToParam(values, floats, count, 0, image->getDescriptor().vgFormat);
       
  1401         break;
       
  1402 
       
  1403     case VG_IMAGE_WIDTH:
       
  1404         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1405         intToParam(values, floats, count, 0, image->getWidth());
       
  1406         break;
       
  1407 
       
  1408     case VG_IMAGE_HEIGHT:
       
  1409         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1410         intToParam(values, floats, count, 0, image->getHeight());
       
  1411         break;
       
  1412 
       
  1413     default:
       
  1414         context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1415         break;
       
  1416     }
       
  1417 }
       
  1418 
       
  1419 /*-------------------------------------------------------------------*//*!
       
  1420 * \brief
       
  1421 * \param
       
  1422 * \return
       
  1423 * \note
       
  1424 *//*-------------------------------------------------------------------*/
       
  1425 
       
  1426 static void getFontParameterifv(VGContext* context, Font* font, VGFontParamType type, VGint count, void* values, bool floats)
       
  1427 {
       
  1428     switch(type)
       
  1429     {
       
  1430     case VG_FONT_NUM_GLYPHS:
       
  1431         if(count > 1)	{ context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; }
       
  1432         intToParam(values, floats, count, 0, font->getNumGlyphs());
       
  1433         break;
       
  1434 
       
  1435     default:
       
  1436         context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid VGParamType
       
  1437         break;
       
  1438     }
       
  1439 }
       
  1440 
       
  1441 /*-------------------------------------------------------------------*//*!
       
  1442 * \brief
       
  1443 * \param
       
  1444 * \return
       
  1445 * \note
       
  1446 *//*-------------------------------------------------------------------*/
       
  1447 
       
  1448 VGfloat RI_APIENTRY vgGetParameterf(VGHandle object, VGint paramType)
       
  1449 {
       
  1450     RI_GET_CONTEXT(0.0f);
       
  1451     RI_IF_ERROR(paramType == VG_PAINT_COLOR || paramType == VG_PAINT_COLOR_RAMP_STOPS || paramType == VG_PAINT_LINEAR_GRADIENT ||
       
  1452                 paramType == VG_PAINT_RADIAL_GRADIENT, VG_ILLEGAL_ARGUMENT_ERROR, 0.0f);	//vector valued parameter
       
  1453     bool isImage = context->isValidImage(object);
       
  1454     bool isPath = context->isValidPath(object);
       
  1455     bool isPaint = context->isValidPaint(object);
       
  1456     bool isFont = context->isValidFont(object);
       
  1457     RI_IF_ERROR(!isImage && !isPath && !isPaint && !isFont, VG_BAD_HANDLE_ERROR, 0.0f);	//invalid object handle
       
  1458     VGfloat ret = 0.0f;
       
  1459     if(isImage)
       
  1460     {
       
  1461         RI_ASSERT(!isPath && !isPaint && !isFont);
       
  1462         getImageParameterifv(context, (Image*)object, (VGImageParamType)paramType, 1, &ret, true);
       
  1463     }
       
  1464     else if(isPath)
       
  1465     {
       
  1466         RI_ASSERT(!isImage && !isPaint && !isFont);
       
  1467         getPathParameterifv(context, (Path*)object, (VGPathParamType)paramType, 1, &ret, true);
       
  1468     }
       
  1469     else if(isPaint)
       
  1470     {
       
  1471         RI_ASSERT(!isImage && !isPath && !isFont);
       
  1472         getPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, 1, &ret, true);
       
  1473     }
       
  1474     else
       
  1475     {
       
  1476         RI_ASSERT(!isImage && !isPath && !isPaint && isFont);
       
  1477         getFontParameterifv(context, (Font*)object, (VGFontParamType)paramType, 1, &ret, true);
       
  1478     }
       
  1479     RI_RETURN(ret);
       
  1480 }
       
  1481 
       
  1482 /*-------------------------------------------------------------------*//*!
       
  1483 * \brief
       
  1484 * \param
       
  1485 * \return
       
  1486 * \note
       
  1487 *//*-------------------------------------------------------------------*/
       
  1488 
       
  1489 VGint RI_APIENTRY vgGetParameteri(VGHandle object, VGint paramType)
       
  1490 {
       
  1491     RI_GET_CONTEXT(0);
       
  1492     RI_IF_ERROR(paramType == VG_PAINT_COLOR || paramType == VG_PAINT_COLOR_RAMP_STOPS || paramType == VG_PAINT_LINEAR_GRADIENT ||
       
  1493                 paramType == VG_PAINT_RADIAL_GRADIENT, VG_ILLEGAL_ARGUMENT_ERROR, 0);	//vector valued parameter
       
  1494     bool isImage = context->isValidImage(object);
       
  1495     bool isPath = context->isValidPath(object);
       
  1496     bool isPaint = context->isValidPaint(object);
       
  1497     bool isFont = context->isValidFont(object);
       
  1498     RI_IF_ERROR(!isImage && !isPath && !isPaint && !isFont, VG_BAD_HANDLE_ERROR, 0);	//invalid object handle
       
  1499     VGint ret = 0;
       
  1500     if(isImage)
       
  1501     {
       
  1502         RI_ASSERT(!isPath && !isPaint && !isFont);
       
  1503         getImageParameterifv(context, (Image*)object, (VGImageParamType)paramType, 1, &ret, false);
       
  1504     }
       
  1505     else if(isPath)
       
  1506     {
       
  1507         RI_ASSERT(!isImage && !isPaint && !isFont);
       
  1508         getPathParameterifv(context, (Path*)object, (VGPathParamType)paramType, 1, &ret, false);
       
  1509     }
       
  1510     else if(isPaint)
       
  1511     {
       
  1512         RI_ASSERT(!isImage && !isPath && !isFont);
       
  1513         getPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, 1, &ret, false);
       
  1514     }
       
  1515     else
       
  1516     {
       
  1517         RI_ASSERT(!isImage && !isPath && !isPaint && isFont);
       
  1518         getFontParameterifv(context, (Font*)object, (VGFontParamType)paramType, 1, &ret, false);
       
  1519     }
       
  1520     RI_RETURN(ret);
       
  1521 }
       
  1522 
       
  1523 /*-------------------------------------------------------------------*//*!
       
  1524 * \brief
       
  1525 * \param
       
  1526 * \return
       
  1527 * \note
       
  1528 *//*-------------------------------------------------------------------*/
       
  1529 
       
  1530 void RI_APIENTRY vgGetParameterfv(VGHandle object, VGint paramType, VGint count, VGfloat * values)
       
  1531 {
       
  1532     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1533     RI_IF_ERROR(count <= 0 || !values || !isAligned(values,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  1534     bool isImage = context->isValidImage(object);
       
  1535     bool isPath = context->isValidPath(object);
       
  1536     bool isPaint = context->isValidPaint(object);
       
  1537     bool isFont = context->isValidFont(object);
       
  1538     RI_IF_ERROR(!isImage && !isPath && !isPaint && !isFont, VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid object handle
       
  1539     if(isImage)
       
  1540     {
       
  1541         RI_ASSERT(!isPath && !isPaint && !isFont);
       
  1542         getImageParameterifv(context, (Image*)object, (VGImageParamType)paramType, count, values, true);
       
  1543     }
       
  1544     else if(isPath)
       
  1545     {
       
  1546         RI_ASSERT(!isImage && !isPaint && !isFont);
       
  1547         getPathParameterifv(context, (Path*)object, (VGPathParamType)paramType, count, values, true);
       
  1548     }
       
  1549     else if(isPaint)
       
  1550     {
       
  1551         RI_ASSERT(!isImage && !isPath && !isFont);
       
  1552         getPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, count, values, true);
       
  1553     }
       
  1554     else
       
  1555     {
       
  1556         RI_ASSERT(!isImage && !isPath && !isPaint && isFont);
       
  1557         getFontParameterifv(context, (Font*)object, (VGFontParamType)paramType, count, values, true);
       
  1558     }
       
  1559     RI_RETURN(RI_NO_RETVAL);
       
  1560 }
       
  1561 
       
  1562 /*-------------------------------------------------------------------*//*!
       
  1563 * \brief
       
  1564 * \param
       
  1565 * \return
       
  1566 * \note
       
  1567 *//*-------------------------------------------------------------------*/
       
  1568 
       
  1569 void RI_APIENTRY vgGetParameteriv(VGHandle object, VGint paramType, VGint count, VGint * values)
       
  1570 {
       
  1571     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1572     RI_IF_ERROR(count <= 0 || !values || !isAligned(values,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  1573     bool isImage = context->isValidImage(object);
       
  1574     bool isPath = context->isValidPath(object);
       
  1575     bool isPaint = context->isValidPaint(object);
       
  1576     bool isFont = context->isValidFont(object);
       
  1577     RI_IF_ERROR(!isImage && !isPath && !isPaint && !isFont, VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid object handle
       
  1578     if(isImage)
       
  1579     {
       
  1580         RI_ASSERT(!isPath && !isPaint && !isFont);
       
  1581         getImageParameterifv(context, (Image*)object, (VGImageParamType)paramType, count, values, false);
       
  1582     }
       
  1583     else if(isPath)
       
  1584     {
       
  1585         RI_ASSERT(!isImage && !isPaint && !isFont);
       
  1586         getPathParameterifv(context, (Path*)object, (VGPathParamType)paramType, count, values, false);
       
  1587     }
       
  1588     else if(isPaint)
       
  1589     {
       
  1590         RI_ASSERT(!isImage && !isPath && !isFont);
       
  1591         getPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, count, values, false);
       
  1592     }
       
  1593     else
       
  1594     {
       
  1595         RI_ASSERT(!isImage && !isPath && !isPaint && isFont);
       
  1596         getFontParameterifv(context, (Font*)object, (VGFontParamType)paramType, count, values, false);
       
  1597     }
       
  1598     RI_RETURN(RI_NO_RETVAL);
       
  1599 }
       
  1600 
       
  1601 /*-------------------------------------------------------------------*//*!
       
  1602 * \brief
       
  1603 * \param
       
  1604 * \return
       
  1605 * \note
       
  1606 *//*-------------------------------------------------------------------*/
       
  1607 
       
  1608 VGint RI_APIENTRY vgGetParameterVectorSize(VGHandle object, VGint paramType)
       
  1609 {
       
  1610     RI_GET_CONTEXT(0);
       
  1611     bool isImage = context->isValidImage(object);
       
  1612     bool isPath = context->isValidPath(object);
       
  1613     bool isPaint = context->isValidPaint(object);
       
  1614     bool isFont = context->isValidFont(object);
       
  1615     RI_IF_ERROR(!isImage && !isPath && !isPaint && !isFont, VG_BAD_HANDLE_ERROR, 0);	//invalid object handle
       
  1616     int ret = 0;
       
  1617     if(isImage)
       
  1618     {
       
  1619         RI_ASSERT(!isPath && !isPaint && !isFont);
       
  1620         switch(paramType)
       
  1621         {
       
  1622         case VG_IMAGE_FORMAT:
       
  1623         case VG_IMAGE_WIDTH:
       
  1624         case VG_IMAGE_HEIGHT:
       
  1625             ret = 1;
       
  1626             break;
       
  1627 
       
  1628         default:
       
  1629             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid paramType
       
  1630             break;
       
  1631         }
       
  1632     }
       
  1633     else if(isPath)
       
  1634     {
       
  1635         RI_ASSERT(!isImage && !isPaint && !isFont);
       
  1636         switch(paramType)
       
  1637         {
       
  1638         case VG_PATH_FORMAT:
       
  1639         case VG_PATH_DATATYPE:
       
  1640         case VG_PATH_SCALE:
       
  1641         case VG_PATH_BIAS:
       
  1642         case VG_PATH_NUM_SEGMENTS:
       
  1643         case VG_PATH_NUM_COORDS:
       
  1644             ret = 1;
       
  1645             break;
       
  1646 
       
  1647         default:
       
  1648             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid paramType
       
  1649             break;
       
  1650         }
       
  1651     }
       
  1652     else if(isPaint)
       
  1653     {
       
  1654         RI_ASSERT(!isImage && !isPath && !isFont);
       
  1655         switch(paramType)
       
  1656         {
       
  1657         case VG_PAINT_TYPE:
       
  1658         case VG_PAINT_COLOR_RAMP_SPREAD_MODE:
       
  1659         case VG_PAINT_PATTERN_TILING_MODE:
       
  1660             ret = 1;
       
  1661             break;
       
  1662 
       
  1663         case VG_PAINT_COLOR:
       
  1664         case VG_PAINT_LINEAR_GRADIENT:
       
  1665             ret = 4;
       
  1666             break;
       
  1667 
       
  1668         case VG_PAINT_COLOR_RAMP_STOPS:
       
  1669             ret = ((Paint*)object)->m_inputColorRampStops.size() * 5;
       
  1670             break;
       
  1671 
       
  1672         case VG_PAINT_COLOR_RAMP_PREMULTIPLIED:
       
  1673             ret = 1;
       
  1674             break;
       
  1675 
       
  1676         case VG_PAINT_RADIAL_GRADIENT:
       
  1677             ret = 5;
       
  1678             break;
       
  1679 
       
  1680         default:
       
  1681             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid paramType
       
  1682             break;
       
  1683         }
       
  1684     }
       
  1685     else
       
  1686     {
       
  1687         RI_ASSERT(!isImage && !isPath && !isPaint && isFont);
       
  1688         switch(paramType)
       
  1689         {
       
  1690         case VG_FONT_NUM_GLYPHS:
       
  1691             ret = 1;
       
  1692             break;
       
  1693 
       
  1694         default:
       
  1695             context->setError(VG_ILLEGAL_ARGUMENT_ERROR);	//invalid paramType
       
  1696             break;
       
  1697         }
       
  1698     }
       
  1699     RI_RETURN(ret);
       
  1700 }
       
  1701 
       
  1702 /*-------------------------------------------------------------------*//*!
       
  1703 * \brief
       
  1704 * \param
       
  1705 * \return
       
  1706 * \note
       
  1707 *//*-------------------------------------------------------------------*/
       
  1708 
       
  1709 static Matrix3x3* getCurrentMatrix(VGContext* context)
       
  1710 {
       
  1711     RI_ASSERT(context);
       
  1712     switch(context->m_matrixMode)
       
  1713     {
       
  1714     case VG_MATRIX_PATH_USER_TO_SURFACE:
       
  1715         return &context->m_pathUserToSurface;
       
  1716 
       
  1717     case VG_MATRIX_IMAGE_USER_TO_SURFACE:
       
  1718         return &context->m_imageUserToSurface;
       
  1719 
       
  1720     case VG_MATRIX_FILL_PAINT_TO_USER:
       
  1721         return &context->m_fillPaintToUser;
       
  1722 
       
  1723     case VG_MATRIX_STROKE_PAINT_TO_USER:
       
  1724         return &context->m_strokePaintToUser;
       
  1725 
       
  1726     default:
       
  1727         RI_ASSERT(context->m_matrixMode == VG_MATRIX_GLYPH_USER_TO_SURFACE);
       
  1728         return &context->m_glyphUserToSurface;
       
  1729     }
       
  1730 }
       
  1731 
       
  1732 /*-------------------------------------------------------------------*//*!
       
  1733 * \brief
       
  1734 * \param
       
  1735 * \return
       
  1736 * \note
       
  1737 *//*-------------------------------------------------------------------*/
       
  1738 
       
  1739 void RI_APIENTRY vgLoadIdentity(void)
       
  1740 {
       
  1741     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1742     Matrix3x3* d = getCurrentMatrix(context);
       
  1743     d->identity();
       
  1744     RI_RETURN(RI_NO_RETVAL);
       
  1745 }
       
  1746 
       
  1747 /*-------------------------------------------------------------------*//*!
       
  1748 * \brief
       
  1749 * \param
       
  1750 * \return
       
  1751 * \note
       
  1752 *//*-------------------------------------------------------------------*/
       
  1753 
       
  1754 void RI_APIENTRY vgLoadMatrix(const VGfloat * m)
       
  1755 {
       
  1756     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1757     RI_IF_ERROR(!m || !isAligned(m,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  1758     Matrix3x3* d = getCurrentMatrix(context);
       
  1759     d->set(inputFloat(m[0]), inputFloat(m[3]), inputFloat(m[6]),
       
  1760            inputFloat(m[1]), inputFloat(m[4]), inputFloat(m[7]),
       
  1761            inputFloat(m[2]), inputFloat(m[5]), inputFloat(m[8]));
       
  1762     if(context->m_matrixMode != VG_MATRIX_IMAGE_USER_TO_SURFACE)
       
  1763     {
       
  1764         (*d)[2].set(0,0,1);
       
  1765     }
       
  1766     RI_RETURN(RI_NO_RETVAL);
       
  1767 }
       
  1768 
       
  1769 /*-------------------------------------------------------------------*//*!
       
  1770 * \brief
       
  1771 * \param
       
  1772 * \return
       
  1773 * \note
       
  1774 *//*-------------------------------------------------------------------*/
       
  1775 
       
  1776 void RI_APIENTRY vgGetMatrix(VGfloat * m)
       
  1777 {
       
  1778     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1779     RI_IF_ERROR(!m || !isAligned(m,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  1780     Matrix3x3* d = getCurrentMatrix(context);
       
  1781     m[0] = (*d)[0][0];
       
  1782     m[1] = (*d)[1][0];
       
  1783     m[2] = (*d)[2][0];
       
  1784     m[3] = (*d)[0][1];
       
  1785     m[4] = (*d)[1][1];
       
  1786     m[5] = (*d)[2][1];
       
  1787     m[6] = (*d)[0][2];
       
  1788     m[7] = (*d)[1][2];
       
  1789     m[8] = (*d)[2][2];
       
  1790     RI_RETURN(RI_NO_RETVAL);
       
  1791 }
       
  1792 
       
  1793 /*-------------------------------------------------------------------*//*!
       
  1794 * \brief
       
  1795 * \param
       
  1796 * \return
       
  1797 * \note
       
  1798 *//*-------------------------------------------------------------------*/
       
  1799 
       
  1800 void RI_APIENTRY vgMultMatrix(const VGfloat * m)
       
  1801 {
       
  1802     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1803     RI_IF_ERROR(!m || !isAligned(m,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  1804     Matrix3x3 n(inputFloat(m[0]), inputFloat(m[3]), inputFloat(m[6]),
       
  1805                 inputFloat(m[1]), inputFloat(m[4]), inputFloat(m[7]),
       
  1806                 inputFloat(m[2]), inputFloat(m[5]), inputFloat(m[8]));
       
  1807     if(context->m_matrixMode != VG_MATRIX_IMAGE_USER_TO_SURFACE)
       
  1808         n[2].set(0,0,1);
       
  1809 
       
  1810     Matrix3x3* d = getCurrentMatrix(context);
       
  1811     *d *= n;
       
  1812 
       
  1813     d->validate();
       
  1814     //d->assertValid();
       
  1815 
       
  1816     if(context->m_matrixMode != VG_MATRIX_IMAGE_USER_TO_SURFACE)
       
  1817     {
       
  1818         (*d)[2].set(0,0,1);	//force affinity
       
  1819     }
       
  1820     RI_RETURN(RI_NO_RETVAL);
       
  1821 }
       
  1822 
       
  1823 /*-------------------------------------------------------------------*//*!
       
  1824 * \brief
       
  1825 * \param
       
  1826 * \return
       
  1827 * \note
       
  1828 *//*-------------------------------------------------------------------*/
       
  1829 
       
  1830 void RI_APIENTRY vgTranslate(VGfloat tx, VGfloat ty)
       
  1831 {
       
  1832     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1833     Matrix3x3 n(1, 0, inputFloat(tx),
       
  1834                 0, 1, inputFloat(ty),
       
  1835                 0, 0, 1 );
       
  1836     Matrix3x3* d = getCurrentMatrix(context);
       
  1837     *d *= n;
       
  1838 
       
  1839     d->validate();
       
  1840     //d->assertValid();
       
  1841 
       
  1842     if(context->m_matrixMode != VG_MATRIX_IMAGE_USER_TO_SURFACE)
       
  1843     {
       
  1844         (*d)[2].set(0,0,1);	//force affinity
       
  1845     }
       
  1846     RI_RETURN(RI_NO_RETVAL);
       
  1847 }
       
  1848 
       
  1849 /*-------------------------------------------------------------------*//*!
       
  1850 * \brief
       
  1851 * \param
       
  1852 * \return
       
  1853 * \note
       
  1854 *//*-------------------------------------------------------------------*/
       
  1855 
       
  1856 void RI_APIENTRY vgScale(VGfloat sx, VGfloat sy)
       
  1857 {
       
  1858     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1859     Matrix3x3 n(inputFloat(sx), 0,              0,
       
  1860                 0,              inputFloat(sy), 0,
       
  1861                 0,              0,              1 );
       
  1862     Matrix3x3* d = getCurrentMatrix(context);
       
  1863     *d *= n;
       
  1864 
       
  1865     d->validate();
       
  1866     //d->assertValid();
       
  1867 
       
  1868     if(context->m_matrixMode != VG_MATRIX_IMAGE_USER_TO_SURFACE)
       
  1869     {
       
  1870         (*d)[2].set(0,0,1);	//force affinity
       
  1871     }
       
  1872     RI_RETURN(RI_NO_RETVAL);
       
  1873 }
       
  1874 
       
  1875 /*-------------------------------------------------------------------*//*!
       
  1876 * \brief
       
  1877 * \param
       
  1878 * \return
       
  1879 * \note
       
  1880 *//*-------------------------------------------------------------------*/
       
  1881 
       
  1882 void RI_APIENTRY vgShear(VGfloat shx, VGfloat shy)
       
  1883 {
       
  1884     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1885     Matrix3x3 n(1,               inputFloat(shx), 0,
       
  1886                 inputFloat(shy), 1,               0,
       
  1887                 0,               0,               1);
       
  1888     Matrix3x3* d = getCurrentMatrix(context);
       
  1889     *d *= n;
       
  1890 
       
  1891     d->validate();
       
  1892     //d->assertValid();
       
  1893 
       
  1894     if(context->m_matrixMode != VG_MATRIX_IMAGE_USER_TO_SURFACE)
       
  1895     {
       
  1896         (*d)[2].set(0,0,1);	//force affinity
       
  1897     }
       
  1898     RI_RETURN(RI_NO_RETVAL);
       
  1899 }
       
  1900 
       
  1901 /*-------------------------------------------------------------------*//*!
       
  1902 * \brief
       
  1903 * \param
       
  1904 * \return
       
  1905 * \note
       
  1906 *//*-------------------------------------------------------------------*/
       
  1907 
       
  1908 void RI_APIENTRY vgRotate(VGfloat angle)
       
  1909 {
       
  1910     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1911     RIfloat a = RI_DEG_TO_RAD(inputFloat(angle));
       
  1912     Matrix3x3 n((RIfloat)cos(a), -(RIfloat)sin(a), 0,
       
  1913                 (RIfloat)sin(a),  (RIfloat)cos(a), 0,
       
  1914                 0,              0,             1 );
       
  1915     Matrix3x3* d = getCurrentMatrix(context);
       
  1916     *d *= n;
       
  1917 
       
  1918     d->validate();
       
  1919     //d->assertValid();
       
  1920 
       
  1921     if(context->m_matrixMode != VG_MATRIX_IMAGE_USER_TO_SURFACE)
       
  1922     {
       
  1923         (*d)[2].set(0,0,1);	//force affinity
       
  1924     }
       
  1925     RI_RETURN(RI_NO_RETVAL);
       
  1926 }
       
  1927 
       
  1928 /*-------------------------------------------------------------------*//*!
       
  1929 * \brief
       
  1930 * \param
       
  1931 * \return
       
  1932 * \note
       
  1933 *//*-------------------------------------------------------------------*/
       
  1934 
       
  1935 void RI_APIENTRY vgMask(VGHandle mask, VGMaskOperation operation, VGint x, VGint y, VGint width, VGint height)
       
  1936 {
       
  1937     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1938     const bool isImage = context->isValidImage(mask);
       
  1939     const bool isMaskLayer = context->isValidMaskLayer(mask);
       
  1940     const bool needInput = (operation != VG_CLEAR_MASK) && (operation != VG_FILL_MASK);
       
  1941     RI_IF_ERROR(operation != VG_CLEAR_MASK && operation != VG_FILL_MASK && !isImage && !isMaskLayer, VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);
       
  1942     RI_IF_ERROR(operation != VG_CLEAR_MASK && operation != VG_FILL_MASK && isImage && eglvgIsInUse((Image*)mask), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  1943     RI_IF_ERROR(operation < VG_CLEAR_MASK || operation > VG_SUBTRACT_MASK, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  1944     RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  1945     Drawable* drawable = context->getCurrentDrawable();
       
  1946     RI_IF_ERROR(isMaskLayer && drawable->getNumSamples() != ((Surface*)mask)->getNumSamples(), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  1947     if(!drawable || !drawable->getMaskBuffer())
       
  1948     {
       
  1949         RI_RETURN(RI_NO_RETVAL);	//no EGL surface is current at the moment or context has no mask buffer
       
  1950     }
       
  1951 
       
  1952     if(isImage)
       
  1953         drawable->getMaskBuffer()->mask(context->getBlitter(), (Image*)mask, operation, x, y, width, height);
       
  1954     else
       
  1955     {
       
  1956         RI_ASSERT(!isMaskLayer ? !needInput : true);
       
  1957         drawable->getMaskBuffer()->mask(context->getBlitter(), (!mask || !needInput) ? NULL : ((Surface*)mask)->getImage(), operation, x, y, width, height);
       
  1958     }
       
  1959 
       
  1960     RI_RETURN(RI_NO_RETVAL);
       
  1961 }
       
  1962 
       
  1963 void RI_APIENTRY vgRenderToMask(VGPath path, VGbitfield paintModes, VGMaskOperation operation)
       
  1964 {
       
  1965     Path* iPath = (Path*)path;
       
  1966     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  1967     RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid path handle
       
  1968     RI_IF_ERROR(!paintModes || (paintModes & ~(VG_FILL_PATH | VG_STROKE_PATH)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);	//invalid paint mode
       
  1969     RI_IF_ERROR(operation < VG_CLEAR_MASK || operation > VG_SUBTRACT_MASK, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  1970     Drawable* curr = context->getCurrentDrawable();
       
  1971     const Surface* mask = curr->getMaskBuffer();
       
  1972     if(!curr || !curr->getMaskBuffer())
       
  1973     {
       
  1974         RI_RETURN(RI_NO_RETVAL);	//no EGL surface is current at the moment or context has no mask buffer
       
  1975     }
       
  1976 
       
  1977     if(operation == VG_CLEAR_MASK || operation == VG_FILL_MASK)
       
  1978     {
       
  1979         //RI_ASSERT(false); // should call fill!
       
  1980         Image* dummy = NULL;
       
  1981         curr->getMaskBuffer()->mask(context->getBlitter(), dummy, operation, 0, 0, curr->getWidth(), curr->getHeight());
       
  1982         RI_RETURN(RI_NO_RETVAL);
       
  1983     }
       
  1984 
       
  1985     try
       
  1986     {
       
  1987         // Create a temporary image to render the path on for some mask operations.
       
  1988         // \todo tero: There are optimizations that can do all the mask operations in one pass, but it
       
  1989         // takes too much time to implement them now.
       
  1990         Drawable *tmpDrawable = NULL;
       
  1991         
       
  1992         try 
       
  1993         {
       
  1994             if (operation == VG_INTERSECT_MASK)
       
  1995             {
       
  1996                 tmpDrawable = RI_NEW(Drawable, (Color::formatToDescriptor(VG_A_8), curr->getWidth(), curr->getHeight(), 1, 0));
       
  1997             }
       
  1998         } catch (std::bad_alloc e)
       
  1999         {
       
  2000             throw e;
       
  2001         }
       
  2002          
       
  2003         //Drawable drawable(Color::formatToDescriptor(VG_A_8), curr->getWidth(), curr->getHeight(), curr->getNumSamples(), 1);    //TODO 0 mask bits (mask buffer is not used)
       
  2004 
       
  2005         Rasterizer& rasterizer = context->m_rasterizer;
       
  2006         rasterizer.clear();
       
  2007 
       
  2008         rasterizer.setScissoring(context->m_scissoring ? true : false);
       
  2009         if(context->m_scissoring)
       
  2010             rasterizer.setScissor(context->m_scissor);	//throws bad_alloc
       
  2011 
       
  2012         PixelPipe& pixelPipe = context->m_pixelPipe;
       
  2013 
       
  2014         // \hack If the mask operation is intersect, we render normally to tempbuffer!
       
  2015         if (!tmpDrawable)
       
  2016             pixelPipe.setRenderToMask(true);
       
  2017         else
       
  2018             pixelPipe.setRenderToMask(false);
       
  2019 
       
  2020         bool skipFill = false;
       
  2021 
       
  2022         if (operation == VG_SET_MASK)
       
  2023         {
       
  2024             Surface *maskSurface = curr->getMaskBuffer();
       
  2025             maskSurface->clear(Color(), 0, 0, maskSurface->getWidth(), maskSurface->getHeight());
       
  2026             skipFill = true;
       
  2027         }
       
  2028 
       
  2029         skipFill = skipFill && (paintModes & VG_STROKE_PATH);
       
  2030 
       
  2031         pixelPipe.setMaskOperation(operation);
       
  2032         pixelPipe.setDrawable(tmpDrawable ? tmpDrawable : curr);
       
  2033         pixelPipe.setImage(NULL, VG_DRAW_IMAGE_NORMAL);
       
  2034         pixelPipe.setMask(false);
       
  2035         pixelPipe.setPaint(NULL);   //use default paint (solid color alpha = 1)
       
  2036         pixelPipe.setBlendMode(VG_BLEND_SRC_OVER);   //write solid color * coverage to dest
       
  2037         bool aa = context->m_renderingQuality == VG_RENDERING_QUALITY_NONANTIALIASED ? false : true;
       
  2038         rasterizer.setAntiAliasing(aa);
       
  2039 
       
  2040         Matrix3x3 userToSurface = context->m_pathUserToSurface;
       
  2041         userToSurface[2].set(0,0,1);	//force affinity
       
  2042 
       
  2043         if((paintModes & VG_FILL_PATH) && (!skipFill))
       
  2044         {
       
  2045             rasterizer.clear();
       
  2046             rasterizer.setup(0, 0, mask->getWidth(), mask->getHeight(), context->m_fillRule, &pixelPipe);
       
  2047             pixelPipe.prepareSpanUniforms(aa);
       
  2048             iPath->fill(userToSurface, rasterizer);	//throws bad_alloc
       
  2049             rasterizer.fill();	//throws bad_alloc
       
  2050             //curr->getMaskBuffer()->mask(drawable.getColorBuffer(), operation, 0, 0, drawable.getWidth(), drawable.getHeight());
       
  2051             if (tmpDrawable)
       
  2052             {
       
  2053                 RI_ASSERT(operation == VG_INTERSECT_MASK);
       
  2054                 curr->getMaskBuffer()->mask(context->getBlitter(), tmpDrawable->getColorBuffer()->getImage(), operation, 0, 0, tmpDrawable->getWidth(), tmpDrawable->getHeight());
       
  2055 
       
  2056                 if (paintModes & VG_STROKE_PATH)
       
  2057                 {
       
  2058                     Surface* tmpSurf = tmpDrawable->getColorBuffer();
       
  2059                     tmpSurf->clear(Color(), 0, 0, 
       
  2060                         tmpSurf->getWidth(), tmpSurf->getHeight());
       
  2061                 }
       
  2062                 else
       
  2063                 {
       
  2064                     RI_DELETE(tmpDrawable);
       
  2065                     tmpDrawable = NULL;
       
  2066                 }
       
  2067             }
       
  2068 
       
  2069         }
       
  2070 
       
  2071         if((paintModes & VG_STROKE_PATH) && context->m_strokeLineWidth > 0.0f)
       
  2072         {
       
  2073             pixelPipe.prepareSpanUniforms(aa);
       
  2074             rasterizer.clear();
       
  2075             rasterizer.setup(0, 0, mask->getWidth(), mask->getHeight(), VG_NON_ZERO, &pixelPipe);
       
  2076 
       
  2077             iPath->stroke(userToSurface, rasterizer, context->m_strokeDashPattern, context->m_strokeDashPhase, context->m_strokeDashPhaseReset ? true : false,
       
  2078                  context->m_strokeLineWidth, context->m_strokeCapStyle, context->m_strokeJoinStyle, RI_MAX(context->m_strokeMiterLimit, 1.0f));	//throws bad_alloc
       
  2079             rasterizer.fill();	//throws bad_alloc
       
  2080             //curr->getMaskBuffer()->mask(drawable.getColorBuffer(), operation, 0, 0, drawable.getWidth(), drawable.getHeight());
       
  2081 
       
  2082             if (tmpDrawable)
       
  2083             {
       
  2084                 RI_ASSERT(operation == VG_INTERSECT_MASK);
       
  2085                 curr->getMaskBuffer()->mask(context->getBlitter(), tmpDrawable->getColorBuffer()->getImage(), operation, 0, 0, tmpDrawable->getWidth(), tmpDrawable->getHeight());
       
  2086                 RI_DELETE(tmpDrawable);
       
  2087                 tmpDrawable = NULL;
       
  2088             }
       
  2089         }
       
  2090         RI_ASSERT(!tmpDrawable);
       
  2091 
       
  2092     }
       
  2093     catch(std::bad_alloc)
       
  2094     {
       
  2095         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2096     }
       
  2097     RI_RETURN(RI_NO_RETVAL);
       
  2098 }
       
  2099 
       
  2100 /*-------------------------------------------------------------------*//*!
       
  2101 * \brief
       
  2102 * \param
       
  2103 * \return
       
  2104 * \note
       
  2105 *//*-------------------------------------------------------------------*/
       
  2106 
       
  2107 VGMaskLayer RI_APIENTRY vgCreateMaskLayer(VGint width, VGint height)
       
  2108 {
       
  2109     RI_GET_CONTEXT(VG_INVALID_HANDLE);
       
  2110     RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);
       
  2111     RI_IF_ERROR(width > RI_MAX_IMAGE_WIDTH || height > RI_MAX_IMAGE_HEIGHT || width*height > RI_MAX_IMAGE_PIXELS ||
       
  2112                 width*height > RI_MAX_IMAGE_BYTES, VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);
       
  2113     Drawable* curr = context->getCurrentDrawable();
       
  2114     if(!curr || !curr->getMaskBuffer())
       
  2115         RI_RETURN(VG_INVALID_HANDLE);   //no current drawing surface
       
  2116 
       
  2117     Surface* layer = NULL;
       
  2118     try
       
  2119     {
       
  2120         layer = RI_NEW(Surface, (Color::formatToDescriptor(VG_A_8), width, height, curr->getNumSamples()));	//throws bad_alloc
       
  2121         RI_ASSERT(layer);
       
  2122         context->m_maskLayerManager->addResource(layer, context);	//throws bad_alloc
       
  2123         layer->clear(Color(1,1,1,1,Color::sRGBA), 0, 0, width, height);
       
  2124         RI_RETURN((VGMaskLayer)layer);
       
  2125     }
       
  2126     catch(std::bad_alloc)
       
  2127     {
       
  2128         RI_DELETE(layer);
       
  2129         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2130         RI_RETURN(VG_INVALID_HANDLE);
       
  2131     }
       
  2132 }
       
  2133 
       
  2134 /*-------------------------------------------------------------------*//*!
       
  2135 * \brief
       
  2136 * \param
       
  2137 * \return
       
  2138 * \note
       
  2139 *//*-------------------------------------------------------------------*/
       
  2140 
       
  2141 void RI_APIENTRY vgDestroyMaskLayer(VGMaskLayer maskLayer)
       
  2142 {
       
  2143     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2144     RI_IF_ERROR(!context->isValidMaskLayer(maskLayer), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid handle
       
  2145 
       
  2146     context->m_maskLayerManager->removeResource((Surface*)maskLayer);
       
  2147     RI_RETURN(RI_NO_RETVAL);
       
  2148 }
       
  2149 
       
  2150 /*-------------------------------------------------------------------*//*!
       
  2151 * \brief
       
  2152 * \param
       
  2153 * \return
       
  2154 * \note
       
  2155 *//*-------------------------------------------------------------------*/
       
  2156 
       
  2157 void RI_APIENTRY vgFillMaskLayer(VGMaskLayer maskLayer, VGint x, VGint y, VGint width, VGint height, VGfloat value)
       
  2158 {
       
  2159     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2160     RI_IF_ERROR(!context->isValidMaskLayer(maskLayer), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid handle
       
  2161     RI_IF_ERROR(value < 0.0f || value > 1.0f, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  2162     Surface* layer = (Surface*)maskLayer;
       
  2163     RI_IF_ERROR(width <= 0 || height <= 0 || x < 0 || y < 0 || x > layer->getWidth()-width || y > layer->getHeight()-height, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  2164     layer->clear(Color(1,1,1,value,Color::sRGBA), x, y, width, height);
       
  2165     RI_RETURN(RI_NO_RETVAL);
       
  2166 }
       
  2167 
       
  2168 /*-------------------------------------------------------------------*//*!
       
  2169 * \brief
       
  2170 * \param
       
  2171 * \return
       
  2172 * \note
       
  2173 *//*-------------------------------------------------------------------*/
       
  2174 
       
  2175 void RI_APIENTRY vgCopyMask(VGMaskLayer maskLayer, VGint dx, VGint dy, VGint sx, VGint sy, VGint width, VGint height)
       
  2176 {
       
  2177     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2178     RI_IF_ERROR(!context->isValidMaskLayer(maskLayer), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid handle
       
  2179     Drawable* drawable = context->getCurrentDrawable();
       
  2180     if(!drawable || !drawable->getMaskBuffer())
       
  2181     {
       
  2182         RI_RETURN(RI_NO_RETVAL);	//no EGL surface is current at the moment or context has no mask buffer
       
  2183     }
       
  2184     Surface* layer = (Surface*)maskLayer;
       
  2185     RI_IF_ERROR(width <= 0 || height <= 0 || drawable->getNumSamples() != layer->getNumSamples(), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  2186     try
       
  2187     {   //copy drawing surface mask to mask layer
       
  2188         // \note Removed support for msaa
       
  2189         layer->m_image->blit(context, drawable->getMaskBuffer()->getImage(), sx, sy, dx, dy, width, height);
       
  2190         //layer->blit(drawable->getMaskBuffer(), sx, sy, dx, dy, width, height);	//throws bad_alloc
       
  2191     }
       
  2192     catch(std::bad_alloc)
       
  2193     {
       
  2194         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2195     }
       
  2196     RI_RETURN(RI_NO_RETVAL);
       
  2197 }
       
  2198 
       
  2199 /*-------------------------------------------------------------------*//*!
       
  2200 * \brief
       
  2201 * \param
       
  2202 * \return
       
  2203 * \note
       
  2204 *//*-------------------------------------------------------------------*/
       
  2205 
       
  2206 void RI_APIENTRY vgClear(VGint x, VGint y, VGint width, VGint height)
       
  2207 {
       
  2208     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2209     RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  2210     Drawable* drawable = context->getCurrentDrawable();
       
  2211     if(!drawable)
       
  2212     {
       
  2213         RI_RETURN(RI_NO_RETVAL);	//no EGL surface is current at the moment
       
  2214     }
       
  2215 
       
  2216     try
       
  2217     {
       
  2218         if(context->m_scissoring)
       
  2219             drawable->getColorBuffer()->clear(context->m_clearColor, x, y, width, height, &context->m_scissor);	//throws bad_alloc
       
  2220         else
       
  2221             drawable->getColorBuffer()->clear(context->m_clearColor, x, y, width, height);
       
  2222     }
       
  2223     catch(std::bad_alloc)
       
  2224     {
       
  2225         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2226     }
       
  2227     RI_RETURN(RI_NO_RETVAL);
       
  2228 }
       
  2229 
       
  2230 /*-------------------------------------------------------------------*//*!
       
  2231 * \brief
       
  2232 * \param
       
  2233 * \return
       
  2234 * \note
       
  2235 *//*-------------------------------------------------------------------*/
       
  2236 
       
  2237 VGPath RI_APIENTRY vgCreatePath(VGint pathFormat, VGPathDatatype datatype, VGfloat scale, VGfloat bias, VGint segmentCapacityHint, VGint coordCapacityHint, VGbitfield capabilities)
       
  2238 {
       
  2239     RI_GET_CONTEXT(VG_INVALID_HANDLE);
       
  2240     RI_IF_ERROR(pathFormat != VG_PATH_FORMAT_STANDARD, VG_UNSUPPORTED_PATH_FORMAT_ERROR, VG_INVALID_HANDLE);
       
  2241     RI_IF_ERROR(datatype < VG_PATH_DATATYPE_S_8 || datatype > VG_PATH_DATATYPE_F, VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);
       
  2242     RIfloat s = inputFloat(scale);
       
  2243     RIfloat b = inputFloat(bias);
       
  2244     RI_IF_ERROR(s == 0.0f, VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);
       
  2245     capabilities &= VG_PATH_CAPABILITY_ALL;	//undefined bits are ignored
       
  2246 
       
  2247     Path* path = NULL;
       
  2248     try
       
  2249     {
       
  2250         path = RI_NEW(Path, (pathFormat, datatype, s, b, segmentCapacityHint, coordCapacityHint, capabilities));	//throws bad_alloc
       
  2251         RI_ASSERT(path);
       
  2252         context->m_pathManager->addResource(path, context);	//throws bad_alloc
       
  2253         RI_RETURN((VGPath)path);
       
  2254     }
       
  2255     catch(std::bad_alloc)
       
  2256     {
       
  2257         RI_DELETE(path);
       
  2258         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2259         RI_RETURN(VG_INVALID_HANDLE);
       
  2260     }
       
  2261 }
       
  2262 
       
  2263 /*-------------------------------------------------------------------*//*!
       
  2264 * \brief
       
  2265 * \param
       
  2266 * \return
       
  2267 * \note
       
  2268 *//*-------------------------------------------------------------------*/
       
  2269 
       
  2270 void RI_APIENTRY vgClearPath(VGPath path, VGbitfield capabilities)
       
  2271 {
       
  2272     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2273     RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid path handle
       
  2274     capabilities &= VG_PATH_CAPABILITY_ALL;	//undefined bits are ignored
       
  2275     ((Path*)path)->clear(capabilities);
       
  2276     RI_RETURN(RI_NO_RETVAL);
       
  2277 }
       
  2278 
       
  2279 /*-------------------------------------------------------------------*//*!
       
  2280 * \brief
       
  2281 * \param
       
  2282 * \return
       
  2283 * \note
       
  2284 *//*-------------------------------------------------------------------*/
       
  2285 
       
  2286 void RI_APIENTRY vgDestroyPath(VGPath path)
       
  2287 {
       
  2288     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2289     RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid path handle
       
  2290 
       
  2291     context->m_pathManager->removeResource((Path*)path);
       
  2292 
       
  2293     RI_RETURN(RI_NO_RETVAL);
       
  2294 }
       
  2295 
       
  2296 /*-------------------------------------------------------------------*//*!
       
  2297 * \brief
       
  2298 * \param
       
  2299 * \return
       
  2300 * \note
       
  2301 *//*-------------------------------------------------------------------*/
       
  2302 
       
  2303 void RI_APIENTRY vgRemovePathCapabilities(VGPath path, VGbitfield capabilities)
       
  2304 {
       
  2305     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2306     RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid path handle
       
  2307     capabilities &= VG_PATH_CAPABILITY_ALL;	//undefined bits are ignored
       
  2308 
       
  2309     VGbitfield caps = ((Path*)path)->getCapabilities();
       
  2310     caps &= ~capabilities;
       
  2311     ((Path*)path)->setCapabilities(caps);
       
  2312     RI_RETURN(RI_NO_RETVAL);
       
  2313 }
       
  2314 
       
  2315 /*-------------------------------------------------------------------*//*!
       
  2316 * \brief
       
  2317 * \param
       
  2318 * \return
       
  2319 * \note
       
  2320 *//*-------------------------------------------------------------------*/
       
  2321 
       
  2322 VGbitfield RI_APIENTRY vgGetPathCapabilities(VGPath path)
       
  2323 {
       
  2324     RI_GET_CONTEXT(0);
       
  2325     RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, 0);	//invalid path handle
       
  2326     VGbitfield ret = ((Path*)path)->getCapabilities();
       
  2327     RI_RETURN(ret);
       
  2328 }
       
  2329 
       
  2330 /*-------------------------------------------------------------------*//*!
       
  2331 * \brief
       
  2332 * \param
       
  2333 * \return
       
  2334 * \note
       
  2335 *//*-------------------------------------------------------------------*/
       
  2336 
       
  2337 void RI_APIENTRY vgAppendPathData(VGPath dstPath, VGint numSegments, const VGubyte * pathSegments, const void * pathData)
       
  2338 {
       
  2339     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2340     RI_IF_ERROR(!context->isValidPath(dstPath), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid path handle
       
  2341     Path* p = (Path*)dstPath;
       
  2342     RI_IF_ERROR(!(p->getCapabilities() & VG_PATH_CAPABILITY_APPEND_TO), VG_PATH_CAPABILITY_ERROR, RI_NO_RETVAL);	//no append cap
       
  2343     RI_IF_ERROR(numSegments <= 0 || !pathSegments || !pathData, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);	//no segments or data
       
  2344     RI_IF_ERROR((p->getDatatype() == VG_PATH_DATATYPE_S_16 && !isAligned(pathData,2)) ||
       
  2345                 ((p->getDatatype() == VG_PATH_DATATYPE_S_32 || p->getDatatype() == VG_PATH_DATATYPE_F) && !isAligned(pathData,4)),
       
  2346                 VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);	//invalid alignment
       
  2347     for(int i=0;i<numSegments;i++)
       
  2348     {
       
  2349         VGPathSegment c = (VGPathSegment)(pathSegments[i] & 0x1e);
       
  2350         RI_IF_ERROR(c < VG_CLOSE_PATH || c > VG_LCWARC_TO, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);	//invalid segment
       
  2351         RI_IF_ERROR(c & ~0x1f, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);	//reserved bits are nonzero
       
  2352     }
       
  2353 
       
  2354     try
       
  2355     {
       
  2356         p->appendData((const RIuint8*)pathSegments, numSegments, (const RIuint8*)pathData);	//throws bad_alloc
       
  2357     }
       
  2358     catch(std::bad_alloc)
       
  2359     {
       
  2360         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2361     }
       
  2362     RI_RETURN(RI_NO_RETVAL);
       
  2363 }
       
  2364 
       
  2365 /*-------------------------------------------------------------------*//*!
       
  2366 * \brief
       
  2367 * \param
       
  2368 * \return
       
  2369 * \note
       
  2370 *//*-------------------------------------------------------------------*/
       
  2371 
       
  2372 void RI_APIENTRY vgModifyPathCoords(VGPath dstPath, VGint startIndex, VGint numSegments, const void * pathData)
       
  2373 {
       
  2374     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2375     RI_IF_ERROR(!context->isValidPath(dstPath), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid path handle
       
  2376     Path* p = (Path*)dstPath;
       
  2377     RI_IF_ERROR(!(p->getCapabilities() & VG_PATH_CAPABILITY_MODIFY), VG_PATH_CAPABILITY_ERROR, RI_NO_RETVAL);	//no modify cap
       
  2378     RI_IF_ERROR(!pathData || startIndex < 0 || numSegments <= 0 || RI_INT_ADDSATURATE(startIndex, numSegments) > p->getNumSegments(), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);	//no segments
       
  2379     RI_IF_ERROR((p->getDatatype() == VG_PATH_DATATYPE_S_16 && !isAligned(pathData,2)) ||
       
  2380                 ((p->getDatatype() == VG_PATH_DATATYPE_S_32 || p->getDatatype() == VG_PATH_DATATYPE_F) && !isAligned(pathData,4)),
       
  2381                 VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);	//invalid alignment
       
  2382     p->modifyCoords(startIndex, numSegments, (const RIuint8*)pathData);
       
  2383     RI_RETURN(RI_NO_RETVAL);
       
  2384 }
       
  2385 
       
  2386 /*-------------------------------------------------------------------*//*!
       
  2387 * \brief
       
  2388 * \param
       
  2389 * \return
       
  2390 * \note
       
  2391 *//*-------------------------------------------------------------------*/
       
  2392 
       
  2393 void RI_APIENTRY vgAppendPath(VGPath dstPath, VGPath srcPath)
       
  2394 {
       
  2395     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2396     RI_IF_ERROR(!context->isValidPath(dstPath) || !context->isValidPath(srcPath), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid path handle
       
  2397     RI_IF_ERROR(!(((Path*)dstPath)->getCapabilities() & VG_PATH_CAPABILITY_APPEND_TO) ||
       
  2398                 !(((Path*)srcPath)->getCapabilities() & VG_PATH_CAPABILITY_APPEND_FROM), VG_PATH_CAPABILITY_ERROR, RI_NO_RETVAL);	//invalid caps
       
  2399 
       
  2400     try
       
  2401     {
       
  2402         ((Path*)dstPath)->append((Path*)srcPath);	//throws bad_alloc
       
  2403     }
       
  2404     catch(std::bad_alloc)
       
  2405     {
       
  2406         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2407     }
       
  2408     RI_RETURN(RI_NO_RETVAL);
       
  2409 }
       
  2410 
       
  2411 /*-------------------------------------------------------------------*//*!
       
  2412 * \brief
       
  2413 * \param
       
  2414 * \return
       
  2415 * \note
       
  2416 *//*-------------------------------------------------------------------*/
       
  2417 
       
  2418 void RI_APIENTRY vgTransformPath(VGPath dstPath, VGPath srcPath)
       
  2419 {
       
  2420     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2421     RI_IF_ERROR(!context->isValidPath(dstPath) || !context->isValidPath(srcPath), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid path handle
       
  2422     RI_IF_ERROR(!(((Path*)dstPath)->getCapabilities() & VG_PATH_CAPABILITY_TRANSFORM_TO) ||
       
  2423                 !(((Path*)srcPath)->getCapabilities() & VG_PATH_CAPABILITY_TRANSFORM_FROM), VG_PATH_CAPABILITY_ERROR, RI_NO_RETVAL);	//invalid caps
       
  2424     try
       
  2425     {
       
  2426         ((Path*)dstPath)->transform((Path*)srcPath, context->m_pathUserToSurface);	//throws bad_alloc
       
  2427     }
       
  2428     catch(std::bad_alloc)
       
  2429     {
       
  2430         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2431     }
       
  2432     RI_RETURN(RI_NO_RETVAL);
       
  2433 }
       
  2434 
       
  2435 /*-------------------------------------------------------------------*//*!
       
  2436 * \brief
       
  2437 * \param
       
  2438 * \return
       
  2439 * \note
       
  2440 *//*-------------------------------------------------------------------*/
       
  2441 
       
  2442 static bool drawPath(VGContext* context, VGPath path, const Matrix3x3& userToSurfaceMatrix, VGbitfield paintModes)
       
  2443 {
       
  2444     Path* iPath = (Path*)path;
       
  2445     //set up rendering surface and mask buffer
       
  2446     Drawable* drawable = context->getCurrentDrawable();
       
  2447     if(!drawable)
       
  2448         return false;   //no EGL surface is current at the moment
       
  2449 
       
  2450     Rasterizer& rasterizer = context->m_rasterizer;
       
  2451     rasterizer.clear();
       
  2452 
       
  2453     if(context->m_scissoring)
       
  2454     {
       
  2455         rasterizer.setScissor(context->m_scissor);	//throws bad_alloc
       
  2456     }
       
  2457     rasterizer.setScissoring(context->m_scissoring ? true : false);
       
  2458 
       
  2459     PixelPipe& pixelPipe = context->m_pixelPipe;
       
  2460     pixelPipe.setRenderToMask(false);
       
  2461     pixelPipe.setDrawable(drawable);
       
  2462     pixelPipe.setImage(NULL, VG_DRAW_IMAGE_NORMAL);
       
  2463     pixelPipe.setMask(context->m_masking ? true : false);
       
  2464     pixelPipe.setBlendMode(context->m_blendMode);
       
  2465     pixelPipe.setTileFillColor(context->m_tileFillColor);
       
  2466     pixelPipe.setImageQuality(context->m_imageQuality);
       
  2467     pixelPipe.setColorTransform(context->m_colorTransform ? true : false, context->m_colorTransformValues);
       
  2468     bool aa = context->m_renderingQuality == VG_RENDERING_QUALITY_NONANTIALIASED ? false : true;
       
  2469     rasterizer.setAntiAliasing(aa);
       
  2470 
       
  2471     Matrix3x3 userToSurface = userToSurfaceMatrix;
       
  2472     userToSurface[2].set(0,0,1);	//force affinity
       
  2473 
       
  2474     if(paintModes & VG_FILL_PATH)
       
  2475     {
       
  2476         // \todo Reorganize so that pipe.setpaint handles/requires the matrix setup?
       
  2477         pixelPipe.setPaint((Paint*)context->m_fillPaint);
       
  2478 
       
  2479         Matrix3x3 paintToSurfaceMatrix = userToSurface * context->m_fillPaintToUser;
       
  2480         Matrix3x3 surfaceToPaintMatrix = paintToSurfaceMatrix; 
       
  2481         if(surfaceToPaintMatrix.invert())
       
  2482         {
       
  2483             surfaceToPaintMatrix[2].set(0,0,1);		//force affinity
       
  2484             pixelPipe.setSurfaceToPaintMatrix(surfaceToPaintMatrix);
       
  2485             pixelPipe.prepareSpanUniforms(aa);
       
  2486 
       
  2487             rasterizer.clear();
       
  2488             rasterizer.setup(0, 0, drawable->getWidth(), drawable->getHeight(), context->m_fillRule, &pixelPipe);
       
  2489             iPath->fill(userToSurface, rasterizer);	//throws bad_alloc
       
  2490             rasterizer.fill();	//throws bad_alloc
       
  2491         }
       
  2492     }
       
  2493 
       
  2494     if(paintModes & VG_STROKE_PATH && context->m_strokeLineWidth > 0.0f)
       
  2495     {
       
  2496         pixelPipe.setPaint((Paint*)context->m_strokePaint);
       
  2497 
       
  2498         Matrix3x3 paintToSurfaceMatrix = userToSurface * context->m_strokePaintToUser;
       
  2499         Matrix3x3 surfaceToPaintMatrix = paintToSurfaceMatrix; 
       
  2500         if(surfaceToPaintMatrix.invert())
       
  2501         {
       
  2502             surfaceToPaintMatrix[2].set(0,0,1);		//force affinity
       
  2503             pixelPipe.setSurfaceToPaintMatrix(surfaceToPaintMatrix);
       
  2504             pixelPipe.prepareSpanUniforms(aa);
       
  2505 
       
  2506             rasterizer.clear();
       
  2507             rasterizer.setup(0, 0, drawable->getWidth(), drawable->getHeight(), VG_NON_ZERO, &pixelPipe);
       
  2508             iPath->stroke(userToSurface, rasterizer, context->m_strokeDashPattern, context->m_strokeDashPhase, context->m_strokeDashPhaseReset ? true : false,
       
  2509                  context->m_strokeLineWidth, context->m_strokeCapStyle, context->m_strokeJoinStyle, RI_MAX(context->m_strokeMiterLimit, 1.0f));	//throws bad_alloc
       
  2510             rasterizer.fill();	//throws bad_alloc
       
  2511 
       
  2512         }
       
  2513     }
       
  2514     return true;
       
  2515 }
       
  2516 
       
  2517 void RI_APIENTRY vgDrawPath(VGPath path, VGbitfield paintModes)
       
  2518 {
       
  2519     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2520     RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid path handle
       
  2521     RI_IF_ERROR(!paintModes || (paintModes & ~(VG_FILL_PATH | VG_STROKE_PATH)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);	//invalid paint mode
       
  2522 
       
  2523     try
       
  2524     {
       
  2525 		eglvgLockSurface(0, 1);
       
  2526         if(!drawPath(context, path, context->m_pathUserToSurface, paintModes))
       
  2527         {
       
  2528 			eglvgUnlockSurface();
       
  2529             RI_RETURN(RI_NO_RETVAL);
       
  2530         }
       
  2531 		eglvgUnlockSurface();
       
  2532     }
       
  2533     catch(std::bad_alloc)
       
  2534     {
       
  2535         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2536     }
       
  2537     RI_RETURN(RI_NO_RETVAL);
       
  2538 }
       
  2539 
       
  2540 /*-------------------------------------------------------------------*//*!
       
  2541 * \brief
       
  2542 * \param
       
  2543 * \return
       
  2544 * \note
       
  2545 *//*-------------------------------------------------------------------*/
       
  2546 
       
  2547 VGfloat RI_APIENTRY vgPathLength(VGPath path, VGint startSegment, VGint numSegments)
       
  2548 {
       
  2549     RI_GET_CONTEXT(-1.0f);
       
  2550     RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, -1.0f);	//invalid path handle
       
  2551     Path* p = (Path*)path;
       
  2552     RI_IF_ERROR(!(p->getCapabilities() & VG_PATH_CAPABILITY_PATH_LENGTH), VG_PATH_CAPABILITY_ERROR, -1.0f);	//invalid caps
       
  2553     RI_IF_ERROR(startSegment < 0 || numSegments <= 0 || RI_INT_ADDSATURATE(startSegment, numSegments) > p->getNumSegments(), VG_ILLEGAL_ARGUMENT_ERROR, -1.0f);
       
  2554     RIfloat pathLength = -1.0f;
       
  2555     try
       
  2556     {
       
  2557         pathLength = p->getPathLength(startSegment, numSegments);	//throws bad_alloc
       
  2558     }
       
  2559     catch(std::bad_alloc)
       
  2560     {
       
  2561         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2562     }
       
  2563     RI_RETURN(pathLength);
       
  2564 }
       
  2565 
       
  2566 /*-------------------------------------------------------------------*//*!
       
  2567 * \brief
       
  2568 * \param
       
  2569 * \return
       
  2570 * \note
       
  2571 *//*-------------------------------------------------------------------*/
       
  2572 
       
  2573 void RI_APIENTRY vgPointAlongPath(VGPath path, VGint startSegment, VGint numSegments, VGfloat distance, VGfloat * x, VGfloat * y, VGfloat * tangentX, VGfloat * tangentY)
       
  2574 {
       
  2575     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2576     RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid path handle
       
  2577     Path* p = (Path*)path;
       
  2578     RI_IF_ERROR((x && y && !(p->getCapabilities() & VG_PATH_CAPABILITY_POINT_ALONG_PATH)) ||
       
  2579                 (tangentX && tangentY && !(p->getCapabilities() & VG_PATH_CAPABILITY_TANGENT_ALONG_PATH)), VG_PATH_CAPABILITY_ERROR, RI_NO_RETVAL);	//invalid caps
       
  2580     RI_IF_ERROR(startSegment < 0 || numSegments <= 0 || RI_INT_ADDSATURATE(startSegment, numSegments) > p->getNumSegments(), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  2581     RI_IF_ERROR(!isAligned(x,4) || !isAligned(y,4) || !isAligned(tangentX,4) || !isAligned(tangentY,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  2582     try
       
  2583     {
       
  2584         Vector2 point, tangent;
       
  2585         p->getPointAlong(startSegment, numSegments, distance, point, tangent);	//throws bad_alloc
       
  2586         if(x && y)
       
  2587         {
       
  2588             *x = point.x;
       
  2589             *y = point.y;
       
  2590         }
       
  2591         if(tangentX && tangentY)
       
  2592         {
       
  2593             tangent.normalize();
       
  2594             *tangentX = tangent.x;
       
  2595             *tangentY = tangent.y;
       
  2596         }
       
  2597     }
       
  2598     catch(std::bad_alloc)
       
  2599     {
       
  2600         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2601     }
       
  2602     RI_RETURN(RI_NO_RETVAL);
       
  2603 }
       
  2604 
       
  2605 /*-------------------------------------------------------------------*//*!
       
  2606 * \brief
       
  2607 * \param
       
  2608 * \return
       
  2609 * \note
       
  2610 *//*-------------------------------------------------------------------*/
       
  2611 
       
  2612 void RI_APIENTRY vgPathBounds(VGPath path, VGfloat * minx, VGfloat * miny, VGfloat * width, VGfloat * height)
       
  2613 {
       
  2614     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2615     RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid path handle
       
  2616     RI_IF_ERROR(!(((Path*)path)->getCapabilities() & VG_PATH_CAPABILITY_PATH_BOUNDS), VG_PATH_CAPABILITY_ERROR, RI_NO_RETVAL);	//invalid caps
       
  2617     RI_IF_ERROR(!minx || !miny || !width || !height, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  2618     RI_IF_ERROR(!isAligned(minx,4) || !isAligned(miny,4) || !isAligned(width,4) || !isAligned(height,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  2619     try
       
  2620     {
       
  2621         RIfloat pminx,pminy,pmaxx,pmaxy;
       
  2622         ((Path*)path)->getPathBounds(pminx, pminy, pmaxx, pmaxy);	//throws bad_alloc
       
  2623         *minx = pminx;
       
  2624         *miny = pminy;
       
  2625         *width = pmaxx - pminx;
       
  2626         *height = pmaxy - pminy;
       
  2627     }
       
  2628     catch(std::bad_alloc)
       
  2629     {
       
  2630         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2631     }
       
  2632     RI_RETURN(RI_NO_RETVAL);
       
  2633 }
       
  2634 
       
  2635 /*-------------------------------------------------------------------*//*!
       
  2636 * \brief
       
  2637 * \param
       
  2638 * \return
       
  2639 * \note
       
  2640 *//*-------------------------------------------------------------------*/
       
  2641 
       
  2642 void RI_APIENTRY vgPathTransformedBounds(VGPath path, VGfloat * minx, VGfloat * miny, VGfloat * width, VGfloat * height)
       
  2643 {
       
  2644     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2645     RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid path handle
       
  2646     RI_IF_ERROR(!(((Path*)path)->getCapabilities() & VG_PATH_CAPABILITY_PATH_TRANSFORMED_BOUNDS), VG_PATH_CAPABILITY_ERROR, RI_NO_RETVAL);	//invalid caps
       
  2647     RI_IF_ERROR(!minx || !miny || !width || !height, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  2648     RI_IF_ERROR(!isAligned(minx,4) || !isAligned(miny,4) || !isAligned(width,4) || !isAligned(height,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  2649     try
       
  2650     {
       
  2651         RIfloat pminx, pminy, pmaxx, pmaxy;
       
  2652         ((Path*)path)->getPathTransformedBounds(context->m_pathUserToSurface, pminx, pminy, pmaxx, pmaxy);	//throws bad_alloc
       
  2653         *minx = pminx;
       
  2654         *miny = pminy;
       
  2655         *width = pmaxx - pminx;
       
  2656         *height = pmaxy - pminy;
       
  2657     }
       
  2658     catch(std::bad_alloc)
       
  2659     {
       
  2660         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2661     }
       
  2662     RI_RETURN(RI_NO_RETVAL);
       
  2663 }
       
  2664 
       
  2665 /*-------------------------------------------------------------------*//*!
       
  2666 * \brief
       
  2667 * \param
       
  2668 * \return
       
  2669 * \note
       
  2670 *//*-------------------------------------------------------------------*/
       
  2671 
       
  2672 VGboolean RI_APIENTRY vgInterpolatePath(VGPath dstPath, VGPath startPath, VGPath endPath, VGfloat amount)
       
  2673 {
       
  2674     RI_GET_CONTEXT(VG_FALSE);
       
  2675     RI_IF_ERROR(!context->isValidPath(dstPath) || !context->isValidPath(startPath) || !context->isValidPath(endPath), VG_BAD_HANDLE_ERROR, VG_FALSE);	//invalid path handle
       
  2676     RI_IF_ERROR(!(((Path*)dstPath)->getCapabilities() & VG_PATH_CAPABILITY_INTERPOLATE_TO) ||
       
  2677                 !(((Path*)startPath)->getCapabilities() & VG_PATH_CAPABILITY_INTERPOLATE_FROM) ||
       
  2678                 !(((Path*)endPath)->getCapabilities() & VG_PATH_CAPABILITY_INTERPOLATE_FROM), VG_PATH_CAPABILITY_ERROR, VG_FALSE);	//invalid caps
       
  2679     VGboolean ret = VG_FALSE;
       
  2680     try
       
  2681     {
       
  2682         if(((Path*)dstPath)->interpolate((const Path*)startPath, (const Path*)endPath, inputFloat(amount)))	//throws bad_alloc
       
  2683             ret = VG_TRUE;
       
  2684     }
       
  2685     catch(std::bad_alloc)
       
  2686     {
       
  2687         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2688     }
       
  2689     RI_RETURN(ret);
       
  2690 }
       
  2691 
       
  2692 /*-------------------------------------------------------------------*//*!
       
  2693 * \brief
       
  2694 * \param
       
  2695 * \return
       
  2696 * \note
       
  2697 *//*-------------------------------------------------------------------*/
       
  2698 
       
  2699 VGPaint RI_APIENTRY vgCreatePaint(void)
       
  2700 {
       
  2701     RI_GET_CONTEXT(VG_INVALID_HANDLE);
       
  2702     Paint* paint = NULL;
       
  2703     RI_TRACE("\n***** vgCreatePaint\n");
       
  2704     try
       
  2705     {
       
  2706         paint = RI_NEW(Paint, ());	//throws bad_alloc
       
  2707         RI_ASSERT(paint);
       
  2708         context->m_paintManager->addResource(paint, context);	//throws bad_alloc
       
  2709         RI_TRACE("===== vgCreatePaint: Created paint obj: %x\n", (int)paint);
       
  2710         RI_RETURN((VGPaint)paint);
       
  2711     }
       
  2712     catch(std::bad_alloc)
       
  2713     {
       
  2714         RI_DELETE(paint);
       
  2715         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2716         RI_RETURN(VG_INVALID_HANDLE);
       
  2717     }
       
  2718 }
       
  2719 
       
  2720 /*-------------------------------------------------------------------*//*!
       
  2721 * \brief
       
  2722 * \param
       
  2723 * \return
       
  2724 * \note
       
  2725 *//*-------------------------------------------------------------------*/
       
  2726 
       
  2727 void RI_APIENTRY vgDestroyPaint(VGPaint paint)
       
  2728 {
       
  2729     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2730     RI_IF_ERROR(!context->isValidPaint(paint), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid paint handle
       
  2731 
       
  2732     context->m_paintManager->removeResource((Paint*)paint);
       
  2733 
       
  2734     RI_RETURN(RI_NO_RETVAL);
       
  2735 }
       
  2736 
       
  2737 /*-------------------------------------------------------------------*//*!
       
  2738 * \brief
       
  2739 * \param
       
  2740 * \return
       
  2741 * \note
       
  2742 *//*-------------------------------------------------------------------*/
       
  2743 
       
  2744 void RI_APIENTRY vgSetPaint(VGPaint paint, VGbitfield paintModes)
       
  2745 {
       
  2746     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2747     RI_TRACE("\n***** vgSetPaint: %x mode: %d\n", (int)paint, (int)paintModes);
       
  2748     RI_IF_ERROR(paint && !context->isValidPaint(paint), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid paint handle
       
  2749     RI_IF_ERROR(!paintModes || paintModes & ~(VG_FILL_PATH | VG_STROKE_PATH), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);	//invalid paint mode
       
  2750 
       
  2751     context->releasePaint(paintModes);
       
  2752 
       
  2753     if(paintModes & VG_FILL_PATH)
       
  2754     {
       
  2755         if(paint)
       
  2756             ((Paint*)paint)->addReference();
       
  2757         context->m_fillPaint = paint;
       
  2758     }
       
  2759     if(paintModes & VG_STROKE_PATH)
       
  2760     {
       
  2761         if(paint)
       
  2762             ((Paint*)paint)->addReference();
       
  2763         context->m_strokePaint = paint;
       
  2764     }
       
  2765     RI_RETURN(RI_NO_RETVAL);
       
  2766 }
       
  2767 
       
  2768 /*-------------------------------------------------------------------*//*!
       
  2769 * \brief
       
  2770 * \param
       
  2771 * \return
       
  2772 * \note
       
  2773 *//*-------------------------------------------------------------------*/
       
  2774 
       
  2775 void RI_APIENTRY vgSetColor(VGPaint paint, VGuint rgba)
       
  2776 {
       
  2777     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2778     RI_TRACE("\n***** vgSetColor: %x, rgba: %x\n", paint, rgba);
       
  2779     RI_IF_ERROR(!context->isValidPaint(paint), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid paint handle
       
  2780     Paint* p = (Paint*)paint;
       
  2781     p->m_inputPaintColor.unpack(rgba, Color::formatToDescriptor(VG_sRGBA_8888));
       
  2782     p->setColor(inputColor(p->m_inputPaintColor));
       
  2783     RI_TRACE("** -> [%.3f %.3f %.3f %.3f]\n", p->m_paintColor.r, p->m_paintColor.g, p->m_paintColor.b, p->m_paintColor.a);
       
  2784 //    p->m_paintColor = inputColor(p->m_inputPaintColor);
       
  2785 //    p->m_paintColor.clamp();
       
  2786 //    p->m_paintColor.premultiply();
       
  2787     RI_RETURN(RI_NO_RETVAL);
       
  2788 }
       
  2789 
       
  2790 /*-------------------------------------------------------------------*//*!
       
  2791 * \brief
       
  2792 * \param
       
  2793 * \return
       
  2794 * \note
       
  2795 *//*-------------------------------------------------------------------*/
       
  2796 
       
  2797 VGuint RI_APIENTRY vgGetColor(VGPaint paint)
       
  2798 {
       
  2799     RI_GET_CONTEXT(0);
       
  2800     RI_IF_ERROR(!context->isValidPaint(paint), VG_BAD_HANDLE_ERROR, 0);	//invalid paint handle
       
  2801     Color tempColor = ((Paint*)paint)->m_inputPaintColor;
       
  2802     tempColor.clamp();
       
  2803     unsigned int ret = tempColor.pack(Color::formatToDescriptor(VG_sRGBA_8888));
       
  2804     RI_RETURN(ret);
       
  2805 }
       
  2806 
       
  2807 /*-------------------------------------------------------------------*//*!
       
  2808 * \brief
       
  2809 * \param
       
  2810 * \return
       
  2811 * \note
       
  2812 *//*-------------------------------------------------------------------*/
       
  2813 
       
  2814 VGPaint RI_APIENTRY vgGetPaint(VGPaintMode paintMode)
       
  2815 {
       
  2816     RI_GET_CONTEXT(VG_INVALID_HANDLE);
       
  2817     RI_IF_ERROR(paintMode != VG_FILL_PATH && paintMode != VG_STROKE_PATH, VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);	//invalid paint mode
       
  2818 
       
  2819     if(paintMode == VG_FILL_PATH)
       
  2820     {
       
  2821         RI_RETURN(context->m_fillPaint);
       
  2822     }
       
  2823     RI_RETURN(context->m_strokePaint);
       
  2824 }
       
  2825 
       
  2826 /*-------------------------------------------------------------------*//*!
       
  2827 * \brief
       
  2828 * \param
       
  2829 * \return
       
  2830 * \note
       
  2831 *//*-------------------------------------------------------------------*/
       
  2832 
       
  2833 void RI_APIENTRY vgPaintPattern(VGPaint paint, VGImage image)
       
  2834 {
       
  2835     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2836     RI_IF_ERROR(!context->isValidPaint(paint) || (image != VG_INVALID_HANDLE && !context->isValidImage(image)), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid handle
       
  2837     Image* img = (Image*)image;
       
  2838     Paint* pnt = (Paint*)paint;
       
  2839     RI_IF_ERROR(image != VG_INVALID_HANDLE && eglvgIsInUse(img), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  2840     Image* pattern = pnt->m_pattern;
       
  2841     if(pattern)
       
  2842     {
       
  2843         pattern->removeInUse();
       
  2844         if(!pattern->removeReference())
       
  2845             RI_DELETE(pattern);
       
  2846     }
       
  2847     pnt->m_pattern = img;
       
  2848 
       
  2849     if(img)
       
  2850     {
       
  2851         img->addReference();
       
  2852         img->addInUse();
       
  2853     }
       
  2854     RI_RETURN(RI_NO_RETVAL);
       
  2855 }
       
  2856 
       
  2857 /*-------------------------------------------------------------------*//*!
       
  2858 * \brief
       
  2859 * \param
       
  2860 * \return
       
  2861 * \note
       
  2862 *//*-------------------------------------------------------------------*/
       
  2863 
       
  2864 VGImage RI_APIENTRY vgCreateImage(VGImageFormat format, VGint width, VGint height, VGbitfield allowedQuality)
       
  2865 {
       
  2866     RI_GET_CONTEXT(VG_INVALID_HANDLE);
       
  2867     RI_IF_ERROR(!isValidImageFormat(format), VG_UNSUPPORTED_IMAGE_FORMAT_ERROR, VG_INVALID_HANDLE);
       
  2868     RI_IF_ERROR(width <= 0 || height <= 0 || !allowedQuality ||
       
  2869                 (allowedQuality & ~(VG_IMAGE_QUALITY_NONANTIALIASED | VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_BETTER)), VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);
       
  2870     RI_IF_ERROR(width > RI_MAX_IMAGE_WIDTH || height > RI_MAX_IMAGE_HEIGHT || width*height > RI_MAX_IMAGE_PIXELS ||
       
  2871                 ((width*Color::formatToDescriptor(format).bitsPerPixel+7)/8)*height > RI_MAX_IMAGE_BYTES, VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);
       
  2872 
       
  2873     Image* image = NULL;
       
  2874     try
       
  2875     {
       
  2876         image = RI_NEW(Image, (Color::formatToDescriptor(format), width, height, allowedQuality));	//throws bad_alloc
       
  2877         RI_ASSERT(image);
       
  2878         context->m_imageManager->addResource(image, context);	//throws bad_alloc
       
  2879         RI_RETURN((VGImage)image);
       
  2880     }
       
  2881     catch(std::bad_alloc)
       
  2882     {
       
  2883         RI_DELETE(image);
       
  2884         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  2885         RI_RETURN(VG_INVALID_HANDLE);
       
  2886     }
       
  2887 }
       
  2888 
       
  2889 /*-------------------------------------------------------------------*//*!
       
  2890 * \brief
       
  2891 * \param
       
  2892 * \return
       
  2893 * \note
       
  2894 *//*-------------------------------------------------------------------*/
       
  2895 
       
  2896 void RI_APIENTRY vgDestroyImage(VGImage image)
       
  2897 {
       
  2898     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2899     RI_IF_ERROR(!context->isValidImage(image), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid image handle
       
  2900 
       
  2901     context->m_imageManager->removeResource((Image*)image);
       
  2902 
       
  2903     RI_RETURN(RI_NO_RETVAL);
       
  2904 }
       
  2905 
       
  2906 /*-------------------------------------------------------------------*//*!
       
  2907 * \brief
       
  2908 * \param
       
  2909 * \return
       
  2910 * \note
       
  2911 *//*-------------------------------------------------------------------*/
       
  2912 
       
  2913 void RI_APIENTRY vgClearImage(VGImage image, VGint x, VGint y, VGint width, VGint height)
       
  2914 {
       
  2915     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2916     RI_IF_ERROR(!context->isValidImage(image), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);
       
  2917     Image* img = (Image*)image;
       
  2918     RI_IF_ERROR(eglvgIsInUse(img), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  2919     RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  2920 	eglvgLockSurface(0, 1);
       
  2921     img->clear(context->m_clearColor, x, y, width, height);
       
  2922 	eglvgUnlockSurface();
       
  2923     RI_RETURN(RI_NO_RETVAL);
       
  2924 }
       
  2925 
       
  2926 /*-------------------------------------------------------------------*//*!
       
  2927 * \brief
       
  2928 * \param
       
  2929 * \return
       
  2930 * \note
       
  2931 *//*-------------------------------------------------------------------*/
       
  2932 
       
  2933 void RI_APIENTRY vgImageSubData(VGImage image, const void * data, VGint dataStride, VGImageFormat dataFormat, VGint x, VGint y, VGint width, VGint height)
       
  2934 {
       
  2935     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2936     RI_IF_ERROR(!context->isValidImage(image), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);
       
  2937     Image* img = (Image*)image;
       
  2938     RI_IF_ERROR(eglvgIsInUse(img), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  2939     RI_IF_ERROR(!isValidImageFormat(dataFormat), VG_UNSUPPORTED_IMAGE_FORMAT_ERROR, RI_NO_RETVAL);
       
  2940     RI_IF_ERROR(!data || !isAligned(data, dataFormat) || width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  2941     {
       
  2942         Image input(Color::formatToDescriptor(dataFormat), width, height, dataStride, const_cast<RIuint8*>((const RIuint8*)data));
       
  2943         input.addReference();
       
  2944         try
       
  2945         {
       
  2946             img->blit(context, &input, 0, 0, x, y, width, height);	//throws bad_alloc
       
  2947         }
       
  2948         catch(std::bad_alloc)
       
  2949         {
       
  2950         }
       
  2951         input.removeReference();
       
  2952     }
       
  2953     RI_RETURN(RI_NO_RETVAL);
       
  2954 }
       
  2955 
       
  2956 /*-------------------------------------------------------------------*//*!
       
  2957 * \brief
       
  2958 * \param
       
  2959 * \return
       
  2960 * \note
       
  2961 *//*-------------------------------------------------------------------*/
       
  2962 
       
  2963 void RI_APIENTRY vgGetImageSubData(VGImage image, void * data, VGint dataStride, VGImageFormat dataFormat, VGint x, VGint y, VGint width, VGint height)
       
  2964 {
       
  2965     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  2966     RI_IF_ERROR(!context->isValidImage(image), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);
       
  2967     Image* img = (Image*)image;
       
  2968     RI_IF_ERROR(eglvgIsInUse(img), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  2969     RI_IF_ERROR(!isValidImageFormat(dataFormat), VG_UNSUPPORTED_IMAGE_FORMAT_ERROR, RI_NO_RETVAL);
       
  2970     RI_IF_ERROR(!data || !isAligned(data, dataFormat) || width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  2971     {
       
  2972         Image output(Color::formatToDescriptor(dataFormat), width, height, dataStride, (RIuint8*)data);
       
  2973         output.addReference();
       
  2974         try
       
  2975         {
       
  2976             output.blit(context, img, x, y, 0, 0, width, height);	//throws bad_alloc
       
  2977         }
       
  2978         catch(std::bad_alloc)
       
  2979         {
       
  2980         }
       
  2981         output.removeReference();
       
  2982     }
       
  2983     RI_RETURN(RI_NO_RETVAL);
       
  2984 }
       
  2985 
       
  2986 /*-------------------------------------------------------------------*//*!
       
  2987 * \brief
       
  2988 * \param
       
  2989 * \return
       
  2990 * \note
       
  2991 *//*-------------------------------------------------------------------*/
       
  2992 
       
  2993 VGImage RI_APIENTRY vgChildImage(VGImage parent, VGint x, VGint y, VGint width, VGint height)
       
  2994 {
       
  2995     RI_GET_CONTEXT(VG_INVALID_HANDLE);
       
  2996     RI_IF_ERROR(!context->isValidImage(parent), VG_BAD_HANDLE_ERROR, VG_INVALID_HANDLE);
       
  2997     Image* p = (Image*)parent;
       
  2998     RI_IF_ERROR(eglvgIsInUse((Image*)parent), VG_IMAGE_IN_USE_ERROR, VG_INVALID_HANDLE);
       
  2999     RI_IF_ERROR(x < 0 || x >= p->getWidth() || y < 0 || y >= p->getHeight() ||
       
  3000                 width <= 0 || height <= 0 || RI_INT_ADDSATURATE(x, width) > p->getWidth() || RI_INT_ADDSATURATE(y, height) > p->getHeight(), VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);
       
  3001 
       
  3002     Image* child = NULL;
       
  3003     try
       
  3004     {
       
  3005         child = RI_NEW(Image, (p, x, y, width, height));	//throws bad_alloc
       
  3006         RI_ASSERT(child);
       
  3007         context->m_imageManager->addResource(child, context);	//throws bad_alloc
       
  3008         RI_RETURN((VGImage)child);
       
  3009     }
       
  3010     catch(std::bad_alloc)
       
  3011     {
       
  3012         RI_DELETE(child);
       
  3013         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  3014         RI_RETURN(VG_INVALID_HANDLE);
       
  3015     }
       
  3016 }
       
  3017 
       
  3018 /*-------------------------------------------------------------------*//*!
       
  3019 * \brief
       
  3020 * \param
       
  3021 * \return
       
  3022 * \note
       
  3023 *//*-------------------------------------------------------------------*/
       
  3024 
       
  3025 VGImage RI_APIENTRY vgGetParent(VGImage image)
       
  3026 {
       
  3027     RI_GET_CONTEXT(VG_INVALID_HANDLE);
       
  3028     RI_IF_ERROR(!context->isValidImage(image), VG_BAD_HANDLE_ERROR, VG_INVALID_HANDLE);
       
  3029     VGImage ret = image;	//if image has no ancestors, image is returned.
       
  3030 
       
  3031     //The vgGetParent function returns the closest valid ancestor (i.e., one that has not been the target of a vgDestroyImage call)
       
  3032     // of the given image.
       
  3033     Image* im = ((Image*)image)->getParent();
       
  3034     for(;im;im = im->getParent())
       
  3035     {
       
  3036         if(context->isValidImage((VGImage)im))
       
  3037         {	//the parent is valid and alive
       
  3038             ret = (VGImage)im;
       
  3039             break;
       
  3040         }
       
  3041     }
       
  3042     RI_RETURN(ret);
       
  3043 }
       
  3044 
       
  3045 /*-------------------------------------------------------------------*//*!
       
  3046 * \brief
       
  3047 * \param
       
  3048 * \return
       
  3049 * \note
       
  3050 *//*-------------------------------------------------------------------*/
       
  3051 
       
  3052 void RI_APIENTRY vgCopyImage(VGImage dst, VGint dx, VGint dy, VGImage src, VGint sx, VGint sy, VGint width, VGint height, VGboolean dither)
       
  3053 {
       
  3054     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3055     RI_IF_ERROR(!context->isValidImage(dst) || !context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);
       
  3056     RI_IF_ERROR(eglvgIsInUse((Image*)dst) || eglvgIsInUse((Image*)src), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  3057     RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3058     try
       
  3059     {
       
  3060         ((Image*)dst)->blit(context, (Image*)src, sx, sy, dx, dy, width, height, NULL, dither ? true : false);	//throws bad_alloc
       
  3061     }
       
  3062     catch(std::bad_alloc)
       
  3063     {
       
  3064     }
       
  3065     RI_RETURN(RI_NO_RETVAL);
       
  3066 }
       
  3067  
       
  3068 
       
  3069 /*-------------------------------------------------------------------*//*!
       
  3070 * \brief
       
  3071 * \param
       
  3072 * \return
       
  3073 * \note
       
  3074 *//*-------------------------------------------------------------------*/
       
  3075 
       
  3076 static bool drawImage(VGContext* context, VGImage image, const Matrix3x3& userToSurfaceMatrix)
       
  3077 {
       
  3078     Drawable* drawable = context->getCurrentDrawable();
       
  3079     if(!drawable)
       
  3080         return false;   //no EGL surface is current at the moment
       
  3081 
       
  3082     Image* img = (Image*)image;
       
  3083     //transform image corners into the surface space
       
  3084     Vector3 p0(0, 0, 1);
       
  3085     Vector3 p1(0, (RIfloat)img->getHeight(), 1);
       
  3086     Vector3 p2((RIfloat)img->getWidth(), (RIfloat)img->getHeight(), 1);
       
  3087     Vector3 p3((RIfloat)img->getWidth(), 0, 1);
       
  3088     p0 = userToSurfaceMatrix * p0;
       
  3089     p1 = userToSurfaceMatrix * p1;
       
  3090     p2 = userToSurfaceMatrix * p2;
       
  3091     p3 = userToSurfaceMatrix * p3;
       
  3092     if(p0.z <= 0.0f || p1.z <= 0.0f || p2.z <= 0.0f || p3.z <= 0.0f)
       
  3093         return false;
       
  3094 
       
  3095     //projection
       
  3096     p0 *= 1.0f/p0.z;
       
  3097     p1 *= 1.0f/p1.z;
       
  3098     p2 *= 1.0f/p2.z;
       
  3099     p3 *= 1.0f/p3.z;
       
  3100 
       
  3101     Rasterizer& rasterizer = context->m_rasterizer;
       
  3102     rasterizer.clear();
       
  3103 
       
  3104     rasterizer.setScissoring(context->m_scissoring ? true : false);
       
  3105     if(context->m_scissoring)
       
  3106         rasterizer.setScissor(context->m_scissor);	//throws bad_alloc
       
  3107 
       
  3108     PixelPipe& pixelPipe = context->m_pixelPipe;
       
  3109     pixelPipe.setTileFillColor(context->m_tileFillColor);
       
  3110     pixelPipe.setPaint((Paint*)context->m_fillPaint);
       
  3111     pixelPipe.setImageQuality(context->m_imageQuality);
       
  3112     pixelPipe.setBlendMode(context->m_blendMode);
       
  3113     pixelPipe.setRenderToMask(false);
       
  3114     pixelPipe.setDrawable(drawable);
       
  3115     pixelPipe.setMask(context->m_masking ? true : false);
       
  3116     pixelPipe.setColorTransform(context->m_colorTransform ? true : false, context->m_colorTransformValues);
       
  3117     const bool aa = context->m_renderingQuality == VG_RENDERING_QUALITY_NONANTIALIASED ? false : true;
       
  3118     rasterizer.setAntiAliasing(aa);
       
  3119 
       
  3120     Matrix3x3 surfaceToImageMatrix = userToSurfaceMatrix;
       
  3121     Matrix3x3 surfaceToPaintMatrix = userToSurfaceMatrix * context->m_fillPaintToUser;
       
  3122     if(surfaceToImageMatrix.invert() && surfaceToPaintMatrix.invert())
       
  3123     {
       
  3124         VGImageMode imode = context->m_imageMode;
       
  3125         if(!surfaceToPaintMatrix.isAffine())
       
  3126             imode = VG_DRAW_IMAGE_NORMAL;	//if paint matrix is not affine, always use normal image mode
       
  3127         surfaceToPaintMatrix[2].set(0,0,1);	//force affine
       
  3128 
       
  3129         pixelPipe.setImage(img, imode);
       
  3130         pixelPipe.setSurfaceToPaintMatrix(surfaceToPaintMatrix);
       
  3131         pixelPipe.setSurfaceToImageMatrix(surfaceToImageMatrix);
       
  3132         pixelPipe.prepareSpanUniforms(aa);
       
  3133         rasterizer.setup(0, 0, drawable->getWidth(), drawable->getHeight(), VG_EVEN_ODD, &pixelPipe);
       
  3134 
       
  3135         rasterizer.addEdge(Vector2(p0.x,p0.y), Vector2(p1.x,p1.y));	//throws bad_alloc
       
  3136         rasterizer.addEdge(Vector2(p1.x,p1.y), Vector2(p2.x,p2.y));	//throws bad_alloc
       
  3137         rasterizer.addEdge(Vector2(p2.x,p2.y), Vector2(p3.x,p3.y));	//throws bad_alloc
       
  3138         rasterizer.addEdge(Vector2(p3.x,p3.y), Vector2(p0.x,p0.y));	//throws bad_alloc
       
  3139 
       
  3140         rasterizer.fill();	//throws bad_alloc
       
  3141     }
       
  3142     return true;
       
  3143 }
       
  3144 
       
  3145 void RI_APIENTRY vgDrawImage(VGImage image)
       
  3146 {
       
  3147     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3148     RI_IF_ERROR(!context->isValidImage(image), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);
       
  3149     Image* img = (Image*)image;
       
  3150     RI_IF_ERROR(eglvgIsInUse(img), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  3151 
       
  3152     try
       
  3153     {
       
  3154         if(!drawImage(context, image, context->m_imageUserToSurface))
       
  3155         {
       
  3156             RI_RETURN(RI_NO_RETVAL);
       
  3157         }
       
  3158     }
       
  3159     catch(std::bad_alloc)
       
  3160     {
       
  3161         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  3162     }
       
  3163     RI_RETURN(RI_NO_RETVAL);
       
  3164 }
       
  3165 
       
  3166 /*-------------------------------------------------------------------*//*!
       
  3167 * \brief
       
  3168 * \param
       
  3169 * \return
       
  3170 * \note
       
  3171 *//*-------------------------------------------------------------------*/
       
  3172 
       
  3173 void RI_APIENTRY vgSetPixels(VGint dx, VGint dy, VGImage src, VGint sx, VGint sy, VGint width, VGint height)
       
  3174 {
       
  3175     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3176     RI_IF_ERROR(!context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);
       
  3177     RI_IF_ERROR(eglvgIsInUse((Image*)src), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  3178     RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3179 
       
  3180     Drawable* drawable = context->getCurrentDrawable();
       
  3181     Array<OpenVGRI::Rectangle>* scissors = !context->m_scissoring ? NULL : &context->m_scissor;
       
  3182     if(!drawable)
       
  3183     {
       
  3184         RI_RETURN(RI_NO_RETVAL);	//no EGL surface is current at the moment
       
  3185     }
       
  3186     try
       
  3187     {
       
  3188         drawable->getColorBuffer()->m_image->blit(context, (Image*)src, sx, sy, dx, dy, width, height, scissors, false);	//throws bad_alloc
       
  3189         //drawable->getColorBuffer()->blit(*(Image*)src, sx, sy, dx, dy, width, height);	//throws bad_alloc
       
  3190     }
       
  3191     catch(std::bad_alloc)
       
  3192     {
       
  3193     }
       
  3194     RI_RETURN(RI_NO_RETVAL);
       
  3195 }
       
  3196 
       
  3197 /*-------------------------------------------------------------------*//*!
       
  3198 * \brief
       
  3199 * \param
       
  3200 * \return
       
  3201 * \note
       
  3202 *//*-------------------------------------------------------------------*/
       
  3203 
       
  3204 void RI_APIENTRY vgWritePixels(const void * data, VGint dataStride, VGImageFormat dataFormat, VGint dx, VGint dy, VGint width, VGint height)
       
  3205 {
       
  3206     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3207     RI_IF_ERROR(!isValidImageFormat(dataFormat), VG_UNSUPPORTED_IMAGE_FORMAT_ERROR, RI_NO_RETVAL);
       
  3208     RI_IF_ERROR(!data || !isAligned(data, dataFormat) || width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3209     Drawable* drawable = context->getCurrentDrawable();
       
  3210     if(!drawable)
       
  3211     {
       
  3212         RI_RETURN(RI_NO_RETVAL);	//no EGL surface is current at the moment
       
  3213     }
       
  3214     {
       
  3215         Array<OpenVGRI::Rectangle>* scissors = !context->m_scissoring ? NULL : &context->m_scissor;
       
  3216         Image input(Color::formatToDescriptor(dataFormat), width, height, dataStride, const_cast<RIuint8*>((const RIuint8*)data));
       
  3217         input.addReference();
       
  3218         try
       
  3219         {
       
  3220             drawable->getColorBuffer()->m_image->blit(context, &input, 0, 0, dx, dy, width, height, scissors, false);	//throws bad_alloc
       
  3221         }
       
  3222         catch(std::bad_alloc)
       
  3223         {
       
  3224             // TEROP: out-of-mem?
       
  3225         }
       
  3226         input.removeReference();
       
  3227     }
       
  3228     RI_RETURN(RI_NO_RETVAL);
       
  3229 }
       
  3230 
       
  3231 /*-------------------------------------------------------------------*//*!
       
  3232 * \brief
       
  3233 * \param
       
  3234 * \return
       
  3235 * \note
       
  3236 *//*-------------------------------------------------------------------*/
       
  3237 
       
  3238 void RI_APIENTRY vgGetPixels(VGImage dst, VGint dx, VGint dy, VGint sx, VGint sy, VGint width, VGint height)
       
  3239 {
       
  3240     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3241     RI_IF_ERROR(!context->isValidImage(dst), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);
       
  3242     RI_IF_ERROR(eglvgIsInUse((Image*)dst), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  3243     RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3244     Drawable* drawable = context->getCurrentDrawable();
       
  3245     if(!drawable)
       
  3246     {
       
  3247         RI_RETURN(RI_NO_RETVAL);	//no EGL surface is current at the moment
       
  3248     }
       
  3249     try
       
  3250     {
       
  3251         ((Image*)dst)->blit(context, drawable->getColorBuffer()->m_image, sx, sy, dx, dy, width, height);	//throws bad_alloc
       
  3252     }
       
  3253     catch(std::bad_alloc)
       
  3254     {
       
  3255     }
       
  3256     RI_RETURN(RI_NO_RETVAL);
       
  3257 }
       
  3258 
       
  3259 /*-------------------------------------------------------------------*//*!
       
  3260 * \brief
       
  3261 * \param
       
  3262 * \return
       
  3263 * \note
       
  3264 *//*-------------------------------------------------------------------*/
       
  3265 
       
  3266 void RI_APIENTRY vgReadPixels(void* data, VGint dataStride, VGImageFormat dataFormat, VGint sx, VGint sy, VGint width, VGint height)
       
  3267 {
       
  3268     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3269     RI_IF_ERROR(!isValidImageFormat(dataFormat), VG_UNSUPPORTED_IMAGE_FORMAT_ERROR, RI_NO_RETVAL);
       
  3270     RI_IF_ERROR(!data || !isAligned(data, dataFormat) || width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3271     Drawable* drawable = context->getCurrentDrawable();
       
  3272     if(!drawable)
       
  3273     {
       
  3274         RI_RETURN(RI_NO_RETVAL);	//no EGL surface is current at the moment
       
  3275     }
       
  3276     {
       
  3277         Image output(Color::formatToDescriptor(dataFormat), width, height, dataStride, (RIuint8*)data);
       
  3278         output.addReference();
       
  3279         try
       
  3280         {
       
  3281             output.blit(context, drawable->getColorBuffer()->m_image, sx, sy, 0, 0, width, height);	//throws bad_alloc
       
  3282         }
       
  3283         catch(std::bad_alloc)
       
  3284         {
       
  3285         }
       
  3286         output.removeReference();
       
  3287     }
       
  3288     RI_RETURN(RI_NO_RETVAL);
       
  3289 }
       
  3290 
       
  3291 /*-------------------------------------------------------------------*//*!
       
  3292 * \brief
       
  3293 * \param
       
  3294 * \return
       
  3295 * \note
       
  3296 *//*-------------------------------------------------------------------*/
       
  3297 
       
  3298 void RI_APIENTRY vgCopyPixels(VGint dx, VGint dy, VGint sx, VGint sy, VGint width, VGint height)
       
  3299 {
       
  3300     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3301     RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3302     Drawable* drawable = context->getCurrentDrawable();
       
  3303     Array<OpenVGRI::Rectangle>* scissors = !context->m_scissoring ? NULL : &context->m_scissor;
       
  3304     if(!drawable)
       
  3305     {
       
  3306         RI_RETURN(RI_NO_RETVAL);	//no EGL surface is current at the moment
       
  3307     }
       
  3308     try
       
  3309     {
       
  3310         drawable->getColorBuffer()->m_image->blit(context, drawable->getColorBuffer()->m_image, sx, sy, dx, dy, width, height, scissors, false);	//throws bad_alloc
       
  3311         //drawable->getColorBuffer()->blit(drawable->getColorBuffer(), sx, sy, dx, dy, width, height);	//throws bad_alloc
       
  3312     }
       
  3313     catch(std::bad_alloc)
       
  3314     {
       
  3315     }
       
  3316     RI_RETURN(RI_NO_RETVAL);
       
  3317 }
       
  3318 
       
  3319 /*-------------------------------------------------------------------*//*!
       
  3320 * \brief
       
  3321 * \param
       
  3322 * \return
       
  3323 * \note
       
  3324 *//*-------------------------------------------------------------------*/
       
  3325 
       
  3326 void RI_APIENTRY vgColorMatrix(VGImage dst, VGImage src, const VGfloat * matrix)
       
  3327 {
       
  3328     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3329     RI_IF_ERROR(!context->isValidImage(dst) || !context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);
       
  3330     Image* d = (Image*)dst;
       
  3331     Image* s = (Image*)src;
       
  3332     RI_IF_ERROR(eglvgIsInUse(d) || eglvgIsInUse(s), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  3333     RI_IF_ERROR(d->overlaps(s), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3334     RI_IF_ERROR(!matrix || !isAligned(matrix,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3335     unsigned int channelMask = context->m_filterChannelMask & (VG_RED|VG_GREEN|VG_BLUE|VG_ALPHA);	//undefined bits are ignored
       
  3336 
       
  3337     RIfloat m[20];
       
  3338     for(int i=0;i<20;i++)
       
  3339     {
       
  3340         m[i] = inputFloat(matrix[i]);
       
  3341     }
       
  3342     try
       
  3343     {
       
  3344         d->colorMatrix(*s, m, context->m_filterFormatLinear ? true : false, context->m_filterFormatPremultiplied ? true : false, channelMask);
       
  3345     }
       
  3346     catch(std::bad_alloc)
       
  3347     {
       
  3348     }
       
  3349     RI_RETURN(RI_NO_RETVAL);
       
  3350 }
       
  3351 
       
  3352 /*-------------------------------------------------------------------*//*!
       
  3353 * \brief
       
  3354 * \param
       
  3355 * \return
       
  3356 * \note
       
  3357 *//*-------------------------------------------------------------------*/
       
  3358 
       
  3359 void RI_APIENTRY vgConvolve(VGImage dst, VGImage src, VGint kernelWidth, VGint kernelHeight, VGint shiftX, VGint shiftY, const VGshort * kernel, VGfloat scale, VGfloat bias, VGTilingMode tilingMode)
       
  3360 {
       
  3361     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3362     RI_IF_ERROR(!context->isValidImage(dst) || !context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);
       
  3363     Image* d = (Image*)dst;
       
  3364     Image* s = (Image*)src;
       
  3365     RI_IF_ERROR(eglvgIsInUse(d) || eglvgIsInUse(s), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  3366     RI_IF_ERROR(d->overlaps(s), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3367     RI_IF_ERROR(!kernel || !isAligned(kernel,2) || kernelWidth <= 0 || kernelHeight <= 0 || kernelWidth > RI_MAX_KERNEL_SIZE || kernelHeight > RI_MAX_KERNEL_SIZE, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3368     RI_IF_ERROR(tilingMode < VG_TILE_FILL || tilingMode > VG_TILE_REFLECT, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3369     unsigned int channelMask = context->m_filterChannelMask & (VG_RED|VG_GREEN|VG_BLUE|VG_ALPHA);	//undefined bits are ignored
       
  3370     try
       
  3371     {
       
  3372         d->convolve(*s, kernelWidth, kernelHeight, shiftX, shiftY, (const RIint16*)kernel, inputFloat(scale), inputFloat(bias), tilingMode, context->m_tileFillColor, context->m_filterFormatLinear ? true : false, context->m_filterFormatPremultiplied ? true : false, channelMask);
       
  3373     }
       
  3374     catch(std::bad_alloc)
       
  3375     {
       
  3376     }
       
  3377     RI_RETURN(RI_NO_RETVAL);
       
  3378 }
       
  3379 
       
  3380 /*-------------------------------------------------------------------*//*!
       
  3381 * \brief
       
  3382 * \param
       
  3383 * \return
       
  3384 * \note
       
  3385 *//*-------------------------------------------------------------------*/
       
  3386 
       
  3387 void RI_APIENTRY vgSeparableConvolve(VGImage dst, VGImage src, VGint kernelWidth, VGint kernelHeight, VGint shiftX, VGint shiftY, const VGshort * kernelX, const VGshort * kernelY, VGfloat scale, VGfloat bias, VGTilingMode tilingMode)
       
  3388 {
       
  3389     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3390     RI_IF_ERROR(!context->isValidImage(dst) || !context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);
       
  3391     Image* d = (Image*)dst;
       
  3392     Image* s = (Image*)src;
       
  3393     RI_IF_ERROR(eglvgIsInUse(d) || eglvgIsInUse(s), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  3394     RI_IF_ERROR(d->overlaps(s), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3395     RI_IF_ERROR(!kernelX || !kernelY || !isAligned(kernelX,2) || !isAligned(kernelY,2) || kernelWidth <= 0 || kernelHeight <= 0 || kernelWidth > RI_MAX_SEPARABLE_KERNEL_SIZE || kernelHeight > RI_MAX_SEPARABLE_KERNEL_SIZE, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3396     RI_IF_ERROR(tilingMode < VG_TILE_FILL || tilingMode > VG_TILE_REFLECT, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3397     unsigned int channelMask = context->m_filterChannelMask & (VG_RED|VG_GREEN|VG_BLUE|VG_ALPHA);	//undefined bits are ignored
       
  3398     try
       
  3399     {
       
  3400         d->separableConvolve(*s, kernelWidth, kernelHeight, shiftX, shiftY, (const RIint16*)kernelX, (const RIint16*)kernelY,
       
  3401                                          inputFloat(scale), inputFloat(bias), tilingMode, context->m_tileFillColor, context->m_filterFormatLinear ? true : false,
       
  3402                                          context->m_filterFormatPremultiplied ? true : false, channelMask);
       
  3403     }
       
  3404     catch(std::bad_alloc)
       
  3405     {
       
  3406     }
       
  3407     RI_RETURN(RI_NO_RETVAL);
       
  3408 }
       
  3409 
       
  3410 /*-------------------------------------------------------------------*//*!
       
  3411 * \brief
       
  3412 * \param
       
  3413 * \return
       
  3414 * \note
       
  3415 *//*-------------------------------------------------------------------*/
       
  3416 
       
  3417 void RI_APIENTRY vgGaussianBlur(VGImage dst, VGImage src, VGfloat stdDeviationX, VGfloat stdDeviationY, VGTilingMode tilingMode)
       
  3418 {
       
  3419     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3420     RI_IF_ERROR(!context->isValidImage(dst) || !context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);
       
  3421     Image* d = (Image*)dst;
       
  3422     Image* s = (Image*)src;
       
  3423     RI_IF_ERROR(eglvgIsInUse(d) || eglvgIsInUse(s), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  3424     RI_IF_ERROR(d->overlaps(s), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3425     RIfloat sx = inputFloat(stdDeviationX);
       
  3426     RIfloat sy = inputFloat(stdDeviationY);
       
  3427     RI_IF_ERROR(sx <= 0.0f || sy <= 0.0f || sx > (RIfloat)RI_MAX_GAUSSIAN_STD_DEVIATION || sy > (RIfloat)RI_MAX_GAUSSIAN_STD_DEVIATION, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3428     RI_IF_ERROR(tilingMode < VG_TILE_FILL || tilingMode > VG_TILE_REFLECT, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3429     unsigned int channelMask = context->m_filterChannelMask & (VG_RED|VG_GREEN|VG_BLUE|VG_ALPHA);	//undefined bits are ignored
       
  3430     try
       
  3431     {
       
  3432         d->gaussianBlur(*s, sx, sy, tilingMode, context->m_tileFillColor, context->m_filterFormatLinear ? true : false,
       
  3433                         context->m_filterFormatPremultiplied ? true : false, channelMask);
       
  3434     }
       
  3435     catch(std::bad_alloc)
       
  3436     {
       
  3437     }
       
  3438     RI_RETURN(RI_NO_RETVAL);
       
  3439 }
       
  3440 
       
  3441 /*-------------------------------------------------------------------*//*!
       
  3442 * \brief
       
  3443 * \param
       
  3444 * \return
       
  3445 * \note
       
  3446 *//*-------------------------------------------------------------------*/
       
  3447 
       
  3448 void RI_APIENTRY vgLookup(VGImage dst, VGImage src, const VGubyte * redLUT, const VGubyte * greenLUT, const VGubyte * blueLUT, const VGubyte * alphaLUT, VGboolean outputLinear, VGboolean outputPremultiplied)
       
  3449 {
       
  3450     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3451     RI_IF_ERROR(!context->isValidImage(dst) || !context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);
       
  3452     Image* d = (Image*)dst;
       
  3453     Image* s = (Image*)src;
       
  3454     RI_IF_ERROR(eglvgIsInUse(d) || eglvgIsInUse(s), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  3455     RI_IF_ERROR(d->overlaps(s), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3456     RI_IF_ERROR(!redLUT || !greenLUT || !blueLUT || !alphaLUT, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3457     unsigned int channelMask = context->m_filterChannelMask & (VG_RED|VG_GREEN|VG_BLUE|VG_ALPHA);	//undefined bits are ignored
       
  3458     try
       
  3459     {
       
  3460         d->lookup(*s, (const RIuint8*)redLUT, (const RIuint8*)greenLUT, (const RIuint8*)blueLUT, (const RIuint8*)alphaLUT,
       
  3461                   outputLinear ? true : false, outputPremultiplied ? true : false, context->m_filterFormatLinear ? true : false,
       
  3462                   context->m_filterFormatPremultiplied ? true : false, channelMask);
       
  3463     }
       
  3464     catch(std::bad_alloc)
       
  3465     {
       
  3466     }
       
  3467     RI_RETURN(RI_NO_RETVAL);
       
  3468 }
       
  3469 
       
  3470 /*-------------------------------------------------------------------*//*!
       
  3471 * \brief
       
  3472 * \param
       
  3473 * \return
       
  3474 * \note
       
  3475 *//*-------------------------------------------------------------------*/
       
  3476 
       
  3477 void RI_APIENTRY vgLookupSingle(VGImage dst, VGImage src, const VGuint * lookupTable, VGImageChannel sourceChannel, VGboolean outputLinear, VGboolean outputPremultiplied)
       
  3478 {
       
  3479     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3480     RI_IF_ERROR(!context->isValidImage(dst) || !context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);
       
  3481     Image* d = (Image*)dst;
       
  3482     Image* s = (Image*)src;
       
  3483     RI_IF_ERROR(eglvgIsInUse(d) || eglvgIsInUse(s), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL);
       
  3484     RI_IF_ERROR(d->overlaps(s), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3485     RI_IF_ERROR(!lookupTable || !isAligned(lookupTable,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3486     const Color::Descriptor& desc = s->getDescriptor();
       
  3487     RI_ASSERT(Color::isValidDescriptor(desc));
       
  3488     //give an error if src is in rgb format and the source channel is not valid
       
  3489     RI_IF_ERROR((!desc.isLuminance() && !desc.isAlphaOnly()) && (sourceChannel != VG_RED && sourceChannel != VG_GREEN && sourceChannel != VG_BLUE && sourceChannel != VG_ALPHA), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3490     unsigned int channelMask = context->m_filterChannelMask & (VG_RED|VG_GREEN|VG_BLUE|VG_ALPHA);	//undefined bits are ignored
       
  3491     try
       
  3492     {
       
  3493         d->lookupSingle(*s, (const RIuint32*)lookupTable, sourceChannel, outputLinear ? true : false, outputPremultiplied ? true : false,
       
  3494                         context->m_filterFormatLinear ? true : false, context->m_filterFormatPremultiplied ? true : false, channelMask);
       
  3495     }
       
  3496     catch(std::bad_alloc)
       
  3497     {
       
  3498     }
       
  3499     RI_RETURN(RI_NO_RETVAL);
       
  3500 }
       
  3501 
       
  3502 /*-------------------------------------------------------------------*//*!
       
  3503 * \brief
       
  3504 * \param
       
  3505 * \return
       
  3506 * \note
       
  3507 *//*-------------------------------------------------------------------*/
       
  3508 
       
  3509 VGHardwareQueryResult RI_APIENTRY vgHardwareQuery(VGHardwareQueryType key, VGint setting)
       
  3510 {
       
  3511     RI_GET_CONTEXT(VG_HARDWARE_UNACCELERATED);
       
  3512     RI_IF_ERROR(key != VG_IMAGE_FORMAT_QUERY && key != VG_PATH_DATATYPE_QUERY, VG_ILLEGAL_ARGUMENT_ERROR, VG_HARDWARE_UNACCELERATED);
       
  3513     RI_IF_ERROR(key == VG_IMAGE_FORMAT_QUERY && !isValidImageFormat(setting), VG_ILLEGAL_ARGUMENT_ERROR, VG_HARDWARE_UNACCELERATED);
       
  3514     RI_IF_ERROR(key == VG_PATH_DATATYPE_QUERY && (setting < VG_PATH_DATATYPE_S_8 || setting > VG_PATH_DATATYPE_F), VG_ILLEGAL_ARGUMENT_ERROR, VG_HARDWARE_UNACCELERATED);
       
  3515     RI_RETURN(VG_HARDWARE_UNACCELERATED);
       
  3516 }
       
  3517 
       
  3518 /*-------------------------------------------------------------------*//*!
       
  3519 * \brief
       
  3520 * \param
       
  3521 * \return
       
  3522 * \note
       
  3523 *//*-------------------------------------------------------------------*/
       
  3524      
       
  3525 const VGubyte * RI_APIENTRY vgGetString(VGStringID name)
       
  3526 {
       
  3527     static const VGubyte vendor[] = "Nokia";
       
  3528     static const VGubyte renderer[] = {"OpenVG 1.1 Faster Reference Implementation May 13 2008"};
       
  3529     static const VGubyte version[] = "1.1";
       
  3530     static const VGubyte extensions[] = "";
       
  3531     const VGubyte* r = NULL;
       
  3532     RI_GET_CONTEXT(NULL);
       
  3533     switch(name)
       
  3534     {
       
  3535     case VG_VENDOR:
       
  3536         r = vendor;
       
  3537         break;
       
  3538     case VG_RENDERER:
       
  3539         r = renderer;
       
  3540         break;
       
  3541     case VG_VERSION:
       
  3542         r = version;
       
  3543         break;
       
  3544     case VG_EXTENSIONS:
       
  3545         r = extensions;
       
  3546         break;
       
  3547     default:
       
  3548         break;
       
  3549     }
       
  3550     RI_RETURN(r);
       
  3551 }
       
  3552 
       
  3553 /*-------------------------------------------------------------------*//*!
       
  3554 * \brief
       
  3555 * \param
       
  3556 * \return
       
  3557 * \note
       
  3558 *//*-------------------------------------------------------------------*/
       
  3559 
       
  3560 VGFont RI_APIENTRY vgCreateFont(VGint glyphCapacityHint)
       
  3561 {
       
  3562     RI_GET_CONTEXT(VG_INVALID_HANDLE);
       
  3563     RI_IF_ERROR(glyphCapacityHint < 0, VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE);
       
  3564 
       
  3565     Font* font = NULL;
       
  3566     try
       
  3567     {
       
  3568         font = RI_NEW(Font, (glyphCapacityHint));	//throws bad_alloc
       
  3569         RI_ASSERT(font);
       
  3570         context->m_fontManager->addResource(font, context);	//throws bad_alloc
       
  3571         RI_RETURN((VGFont)font);
       
  3572     }
       
  3573     catch(std::bad_alloc)
       
  3574     {
       
  3575         RI_DELETE(font);
       
  3576         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  3577         RI_RETURN(VG_INVALID_HANDLE);
       
  3578     }
       
  3579 }
       
  3580 
       
  3581 /*-------------------------------------------------------------------*//*!
       
  3582 * \brief
       
  3583 * \param
       
  3584 * \return
       
  3585 * \note
       
  3586 *//*-------------------------------------------------------------------*/
       
  3587 
       
  3588 void RI_APIENTRY vgDestroyFont(VGFont font)
       
  3589 {
       
  3590     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3591     RI_IF_ERROR(!context->isValidFont(font), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid font handle
       
  3592 
       
  3593     context->m_fontManager->removeResource((Font*)font);
       
  3594 
       
  3595     RI_RETURN(RI_NO_RETVAL);
       
  3596 }
       
  3597 
       
  3598 /*-------------------------------------------------------------------*//*!
       
  3599 * \brief
       
  3600 * \param
       
  3601 * \return
       
  3602 * \note
       
  3603 *//*-------------------------------------------------------------------*/
       
  3604 
       
  3605 void RI_APIENTRY vgSetGlyphToPath(VGFont font, VGuint glyphIndex, VGPath path, VGboolean isHinted, const VGfloat glyphOrigin[2], const VGfloat escapement[2])
       
  3606 {
       
  3607     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3608     RI_IF_ERROR(!context->isValidFont(font), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid font handle
       
  3609     RI_IF_ERROR(path != VG_INVALID_HANDLE && !context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid path handle
       
  3610     RI_IF_ERROR(!glyphOrigin || !escapement || !isAligned(glyphOrigin,sizeof(VGfloat)) || !isAligned(escapement,sizeof(VGfloat)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3611     Font* f = (Font*)font;
       
  3612 
       
  3613     try
       
  3614     {
       
  3615         f->setGlyphToPath(glyphIndex, path, isHinted ? true : false, Vector2(inputFloat(glyphOrigin[0]), inputFloat(glyphOrigin[1])), Vector2(inputFloat(escapement[0]), inputFloat(escapement[1])));
       
  3616     }
       
  3617     catch(std::bad_alloc)
       
  3618     {
       
  3619         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  3620     }
       
  3621     RI_RETURN(RI_NO_RETVAL);
       
  3622 }
       
  3623 
       
  3624 /*-------------------------------------------------------------------*//*!
       
  3625 * \brief
       
  3626 * \param
       
  3627 * \return
       
  3628 * \note
       
  3629 *//*-------------------------------------------------------------------*/
       
  3630 
       
  3631 void RI_APIENTRY vgSetGlyphToImage(VGFont font, VGuint glyphIndex, VGImage image, const VGfloat glyphOrigin[2], const VGfloat escapement[2])
       
  3632 {
       
  3633     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3634     RI_IF_ERROR(!context->isValidFont(font), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid font handle
       
  3635     if(image != VG_INVALID_HANDLE)
       
  3636     {
       
  3637         RI_IF_ERROR(!context->isValidImage(image), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid image handle
       
  3638         RI_IF_ERROR(eglvgIsInUse((Image*)image), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); //image in use
       
  3639     }
       
  3640     RI_IF_ERROR(!glyphOrigin || !escapement || !isAligned(glyphOrigin,sizeof(VGfloat)) || !isAligned(escapement,sizeof(VGfloat)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3641     Font* f = (Font*)font;
       
  3642 
       
  3643     try
       
  3644     {
       
  3645         f->setGlyphToImage(glyphIndex, image, Vector2(inputFloat(glyphOrigin[0]), inputFloat(glyphOrigin[1])), Vector2(inputFloat(escapement[0]), inputFloat(escapement[1])));
       
  3646     }
       
  3647     catch(std::bad_alloc)
       
  3648     {
       
  3649         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  3650     }
       
  3651     RI_RETURN(RI_NO_RETVAL);
       
  3652 }
       
  3653 
       
  3654 /*-------------------------------------------------------------------*//*!
       
  3655 * \brief
       
  3656 * \param
       
  3657 * \return
       
  3658 * \note
       
  3659 *//*-------------------------------------------------------------------*/
       
  3660 
       
  3661 void RI_APIENTRY vgClearGlyph(VGFont font, VGuint glyphIndex)
       
  3662 {
       
  3663     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3664     RI_IF_ERROR(!context->isValidFont(font), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid font handle
       
  3665     Font* f = (Font*)font;
       
  3666     Font::Glyph* g = f->findGlyph(glyphIndex);
       
  3667     RI_IF_ERROR(!g, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);   //glyphIndex not defined
       
  3668 
       
  3669     f->clearGlyph(g);
       
  3670 
       
  3671     RI_RETURN(RI_NO_RETVAL);
       
  3672 }
       
  3673 
       
  3674 /*-------------------------------------------------------------------*//*!
       
  3675 * \brief
       
  3676 * \param
       
  3677 * \return
       
  3678 * \note
       
  3679 *//*-------------------------------------------------------------------*/
       
  3680 
       
  3681 void RI_APIENTRY vgDrawGlyph(VGFont font, VGuint glyphIndex, VGbitfield paintModes, VGboolean allowAutoHinting)
       
  3682 {
       
  3683     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3684     RI_IF_ERROR(!context->isValidFont(font), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid font handle
       
  3685     RI_IF_ERROR(paintModes & ~(VG_FILL_PATH | VG_STROKE_PATH), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);	//invalid paint mode
       
  3686     Font* f = (Font*)font;
       
  3687     Font::Glyph* g = f->findGlyph(glyphIndex);
       
  3688     RI_IF_ERROR(!g, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);   //glyphIndex not defined
       
  3689     RI_UNREF(allowAutoHinting); //RI doesn't implement autohinting
       
  3690 
       
  3691     try
       
  3692     {
       
  3693         if(paintModes)
       
  3694         {
       
  3695             Matrix3x3 userToSurfaceMatrix = context->m_glyphUserToSurface;
       
  3696             Vector2 t = context->m_glyphOrigin - g->m_origin;
       
  3697             Matrix3x3 n(1, 0, t.x,
       
  3698                         0, 1, t.y,
       
  3699                         0, 0, 1 );
       
  3700             userToSurfaceMatrix *= n;
       
  3701             userToSurfaceMatrix[2].set(0,0,1);		//force affinity
       
  3702 
       
  3703             bool ret = true;
       
  3704 			eglvgLockSurface(0, 1);
       
  3705             if(g->m_image != VG_INVALID_HANDLE)
       
  3706                 ret = drawImage(context, g->m_image, userToSurfaceMatrix);
       
  3707             else if(g->m_path != VG_INVALID_HANDLE)
       
  3708                 ret = drawPath(context, g->m_path, userToSurfaceMatrix, paintModes);
       
  3709 			eglvgUnlockSurface();
       
  3710             if(!ret)
       
  3711             {
       
  3712                 RI_RETURN(RI_NO_RETVAL);
       
  3713             }
       
  3714         }
       
  3715 
       
  3716         context->m_glyphOrigin += g->m_escapement;
       
  3717         context->m_inputGlyphOrigin = context->m_glyphOrigin;
       
  3718     }
       
  3719     catch(std::bad_alloc)
       
  3720     {
       
  3721         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  3722     }
       
  3723 
       
  3724     RI_RETURN(RI_NO_RETVAL);
       
  3725 }
       
  3726 
       
  3727 /*-------------------------------------------------------------------*//*!
       
  3728 * \brief
       
  3729 * \param
       
  3730 * \return
       
  3731 * \note
       
  3732 *//*-------------------------------------------------------------------*/
       
  3733 
       
  3734 void RI_APIENTRY vgDrawGlyphs(VGFont font, VGint glyphCount, const VGuint *glyphIndices, const VGfloat *adjustments_x, const VGfloat *adjustments_y, VGbitfield paintModes, VGboolean allowAutoHinting)
       
  3735 {
       
  3736     RI_GET_CONTEXT(RI_NO_RETVAL);
       
  3737     RI_IF_ERROR(!context->isValidFont(font), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL);	//invalid font handle
       
  3738     RI_IF_ERROR(!glyphIndices || !isAligned(glyphIndices, sizeof(VGuint)) || glyphCount <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3739     RI_IF_ERROR((adjustments_x && !isAligned(adjustments_x, sizeof(VGfloat))) || (adjustments_y && !isAligned(adjustments_y, sizeof(VGfloat))), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);
       
  3740     RI_IF_ERROR(paintModes & ~(VG_FILL_PATH | VG_STROKE_PATH), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);	//invalid paint mode
       
  3741     Font* f = (Font*)font;
       
  3742     for(int i=0;i<glyphCount;i++)
       
  3743     {
       
  3744         Font::Glyph* g = f->findGlyph(glyphIndices[i]);
       
  3745         RI_IF_ERROR(!g, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL);   //glyphIndex not defined
       
  3746     }
       
  3747     RI_UNREF(allowAutoHinting); //RI doesn't implement autohinting
       
  3748 
       
  3749     try
       
  3750     {
       
  3751         for(int i=0;i<glyphCount;i++)
       
  3752         {
       
  3753             Font::Glyph* g = f->findGlyph(glyphIndices[i]);
       
  3754 
       
  3755             if(paintModes)
       
  3756             {
       
  3757                 Matrix3x3 userToSurfaceMatrix = context->m_glyphUserToSurface;
       
  3758                 Vector2 t = context->m_glyphOrigin - g->m_origin;
       
  3759                 Matrix3x3 n(1, 0, t.x,
       
  3760                             0, 1, t.y,
       
  3761                             0, 0, 1 );
       
  3762                 userToSurfaceMatrix *= n;
       
  3763                 userToSurfaceMatrix[2].set(0,0,1);		//force affinity
       
  3764 
       
  3765                 bool ret = true;
       
  3766                 if(g->m_image != VG_INVALID_HANDLE)
       
  3767                     ret = drawImage(context, g->m_image, userToSurfaceMatrix);
       
  3768                 else if(g->m_path != VG_INVALID_HANDLE)
       
  3769                     ret = drawPath(context, g->m_path, userToSurfaceMatrix, paintModes);
       
  3770                 if(!ret)
       
  3771                 {
       
  3772                     RI_RETURN(RI_NO_RETVAL);
       
  3773                 }
       
  3774             }
       
  3775 
       
  3776             context->m_glyphOrigin += g->m_escapement;
       
  3777             if(adjustments_x)
       
  3778                 context->m_glyphOrigin.x += inputFloat(adjustments_x[i]);
       
  3779             if(adjustments_y)
       
  3780                 context->m_glyphOrigin.y += inputFloat(adjustments_y[i]);
       
  3781             context->m_inputGlyphOrigin = context->m_glyphOrigin;
       
  3782         }
       
  3783     }
       
  3784     catch(std::bad_alloc)
       
  3785     {
       
  3786         context->setError(VG_OUT_OF_MEMORY_ERROR);
       
  3787     }
       
  3788 	RI_RETURN(RI_NO_RETVAL);
       
  3789 }
       
  3790 
       
  3791 VGint vgePathCoordsSizeInBytes(VGPath path, VGint startIndex, VGint numSegments)
       
  3792 {
       
  3793     RI_GET_CONTEXT( 0 );
       
  3794     RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, 0);
       
  3795     VGint ret = ((OpenVGRI::Path*)path)->coordsSizeInBytes( startIndex, numSegments );
       
  3796     RI_RETURN(ret);
       
  3797 }
       
  3798 
       
  3799 
       
  3800 VGImage vgCreateEGLImageTargetKHR(VGeglImageKHR image)
       
  3801 {
       
  3802 #if defined(USE_FULL_EGL)
       
  3803     RI_GET_CONTEXT( 0 );
       
  3804     VGImage ret;
       
  3805     OpenVGRI::Color::Descriptor desc;
       
  3806     OpenVGRI::RIuint8* data;
       
  3807     // Get data for VGImage
       
  3808     int width;
       
  3809     int height;
       
  3810     int stride;
       
  3811 
       
  3812     eglvgGetImageDescriptor( image, desc, width, height, stride );
       
  3813     // There is some error.
       
  3814     // EGLImage is null or EGLImage target is EGL_VG_PARENT_IMAGE_KHR.
       
  3815     RI_IF_ERROR(!width || !height || !stride, VG_ILLEGAL_ARGUMENT_ERROR, NULL);
       
  3816     // Data is created in EGLImage class.
       
  3817     data = (OpenVGRI::RIuint8*)eglvgGetImageData( image );    
       
  3818     // Create VGImage
       
  3819     // allowedQuality = VG_IMAGE_QUALITY_NONANTIALIASED | VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_BETTER
       
  3820     ret = vgCreateImage( desc.vgFormat, width, height, VG_IMAGE_QUALITY_NONANTIALIASED );
       
  3821     // If VGImage is not created raise error and return null
       
  3822     RI_IF_ERROR(!ret, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR, NULL);
       
  3823     // Set data for VGImage.
       
  3824     // This will copy that data-object.
       
  3825     vgImageSubData( ret, 
       
  3826                     data, 
       
  3827                     stride, 
       
  3828                     desc.vgFormat, 
       
  3829                     0, 
       
  3830                     0,
       
  3831                     width, 
       
  3832                     height);
       
  3833     // Return VGImage
       
  3834     RI_RETURN(ret);
       
  3835 #else
       
  3836     (void)image;
       
  3837     return VG_INVALID_HANDLE;
       
  3838 #endif //USE_FULL_EGL
       
  3839 }