egl/sfopenvg/riVGU.cpp
branchEGL_MERGE
changeset 57 2bf8a359aa2f
equal deleted inserted replaced
14:0be82064630b 57:2bf8a359aa2f
       
     1 /*------------------------------------------------------------------------
       
     2  *
       
     3  * VGU library for OpenVG 1.1 Reference Implementation
       
     4  * ---------------------------------------------------
       
     5  *
       
     6  * Copyright (c) 2007 The Khronos Group Inc.
       
     7  *
       
     8  * Permission is hereby granted, free of charge, to any person obtaining a
       
     9  * copy of this software and /or associated documentation files
       
    10  * (the "Materials "), to deal in the Materials without restriction,
       
    11  * including without limitation the rights to use, copy, modify, merge,
       
    12  * publish, distribute, sublicense, and/or sell copies of the Materials,
       
    13  * and to permit persons to whom the Materials are furnished to do so,
       
    14  * subject to the following conditions: 
       
    15  *
       
    16  * The above copyright notice and this permission notice shall be included 
       
    17  * in all copies or substantial portions of the Materials. 
       
    18  *
       
    19  * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
       
    20  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
       
    21  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
       
    22  * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
       
    23  * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
       
    24  * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR
       
    25  * THE USE OR OTHER DEALINGS IN THE MATERIALS.
       
    26  *
       
    27  *//**
       
    28  * \file
       
    29  * \brief	Implementation of the VGU utility library for OpenVG
       
    30  *//*-------------------------------------------------------------------*/
       
    31 
       
    32 #include "vgu.h"
       
    33 #include "openvg.h"
       
    34 #include "riMath.h"
       
    35 
       
    36 #ifdef BUILD_WITH_PRIVATE_VGU
       
    37 #include "vguinternal.h"
       
    38 #endif
       
    39 
       
    40 #ifdef BUILD_WITH_PRIVATE_OPENVG
       
    41 #include "openvginternal.h"
       
    42 #endif
       
    43 
       
    44 using namespace OpenVGRI;
       
    45 
       
    46 /*-------------------------------------------------------------------*//*!
       
    47 * \brief	
       
    48 * \param	
       
    49 * \return	
       
    50 * \note		
       
    51 *//*-------------------------------------------------------------------*/
       
    52 
       
    53 static void append(VGPath path, int numSegments, const VGubyte* segments, int numCoordinates, const VGfloat* coordinates)
       
    54 {
       
    55 	RI_ASSERT(numCoordinates <= 26);
       
    56 
       
    57 
       
    58 #ifdef BUILD_WITH_PRIVATE_OPENVG
       
    59 	VGPathDatatype datatype = (VGPathDatatype)do_vgGetParameteri(path, VG_PATH_DATATYPE);
       
    60 	VGfloat scale = do_vgGetParameterf(path, VG_PATH_SCALE);
       
    61 	VGfloat bias = do_vgGetParameterf(path, VG_PATH_BIAS);
       
    62 #else
       
    63 	VGPathDatatype datatype = (VGPathDatatype)vgGetParameteri(path, VG_PATH_DATATYPE);
       
    64 	VGfloat scale = vgGetParameterf(path, VG_PATH_SCALE);
       
    65 	VGfloat bias = vgGetParameterf(path, VG_PATH_BIAS);
       
    66 #endif
       
    67 
       
    68 	switch(datatype)
       
    69 	{
       
    70 	case VG_PATH_DATATYPE_S_8:
       
    71 	{
       
    72 		RIint8 data[26];
       
    73 		for(int i=0;i<numCoordinates;i++)
       
    74 			data[i] = (RIint8)floor((coordinates[i] - bias) / scale + 0.5f);	//add 0.5 for correct rounding
       
    75 #ifdef BUILD_WITH_PRIVATE_OPENVG
       
    76 		do_vgAppendPathData(path, numSegments, segments, data);
       
    77 #else
       
    78 		vgAppendPathData(path, numSegments, segments, data);
       
    79 #endif
       
    80 		break;
       
    81 	}
       
    82 
       
    83 	case VG_PATH_DATATYPE_S_16:
       
    84 	{
       
    85 		RIint16 data[26];
       
    86 		for(int i=0;i<numCoordinates;i++)
       
    87 			data[i] = (RIint16)floor((coordinates[i] - bias) / scale + 0.5f);	//add 0.5 for correct rounding
       
    88 #ifdef BUILD_WITH_PRIVATE_OPENVG
       
    89 		do_vgAppendPathData(path, numSegments, segments, data);
       
    90 #else
       
    91 		vgAppendPathData(path, numSegments, segments, data);
       
    92 #endif
       
    93 		break;
       
    94 	}
       
    95 
       
    96 	case VG_PATH_DATATYPE_S_32:
       
    97 	{
       
    98 		RIint32 data[26];
       
    99 		for(int i=0;i<numCoordinates;i++)
       
   100 			data[i] = (RIint32)floor((coordinates[i] - bias) / scale + 0.5f);	//add 0.5 for correct rounding
       
   101 #ifdef BUILD_WITH_PRIVATE_OPENVG
       
   102 		do_vgAppendPathData(path, numSegments, segments, data);
       
   103 #else
       
   104 		vgAppendPathData(path, numSegments, segments, data);
       
   105 #endif
       
   106 		break;
       
   107 	}
       
   108 
       
   109 	default:
       
   110 	{
       
   111 		RI_ASSERT(datatype == VG_PATH_DATATYPE_F);
       
   112 		RIfloat32 data[26];
       
   113 		for(int i=0;i<numCoordinates;i++)
       
   114 			data[i] = (RIfloat32)((coordinates[i] - bias) / scale);
       
   115 #ifdef BUILD_WITH_PRIVATE_OPENVG
       
   116 		do_vgAppendPathData(path, numSegments, segments, data);
       
   117 #else
       
   118 		vgAppendPathData(path, numSegments, segments, data);
       
   119 #endif
       
   120 		break;
       
   121 	}
       
   122 	}
       
   123 }
       
   124 
       
   125 /*-------------------------------------------------------------------*//*!
       
   126 * \brief	
       
   127 * \param	
       
   128 * \return	
       
   129 * \note		
       
   130 *//*-------------------------------------------------------------------*/
       
   131 
       
   132 #ifdef BUILD_WITH_PRIVATE_VGU
       
   133 VGUErrorCode RI_APIENTRY do_vguLine(VGPath path, VGfloat x0, VGfloat y0, VGfloat x1, VGfloat y1)
       
   134 #else
       
   135 VGUErrorCode RI_APIENTRY vguLine(VGPath path, VGfloat x0, VGfloat y0, VGfloat x1, VGfloat y1)
       
   136 #endif
       
   137 {
       
   138 	#ifdef BUILD_WITH_PRIVATE_OPENVG
       
   139 		VGErrorCode error = do_vgGetError();	//clear the error state
       
   140 	#else
       
   141 		VGErrorCode error = vgGetError();	//clear the error state
       
   142 	#endif
       
   143 		
       
   144 	
       
   145 	static const VGubyte segments[2] = {VG_MOVE_TO | VG_ABSOLUTE, VG_LINE_TO | VG_ABSOLUTE};
       
   146 	const VGfloat data[4] = {x0, y0, x1, y1};
       
   147 	append(path, 2, segments, 4, data);
       
   148 
       
   149 	
       
   150 	#ifdef BUILD_WITH_PRIVATE_OPENVG
       
   151 		error = do_vgGetError();	
       
   152 	#else
       
   153 		error = vgGetError();	
       
   154 	#endif
       
   155 		
       
   156 	if(error == VG_BAD_HANDLE_ERROR)
       
   157 		return VGU_BAD_HANDLE_ERROR;
       
   158 	else if(error == VG_PATH_CAPABILITY_ERROR)
       
   159 		return VGU_PATH_CAPABILITY_ERROR;
       
   160 	return VGU_NO_ERROR;
       
   161 }
       
   162 
       
   163 /*-------------------------------------------------------------------*//*!
       
   164 * \brief	
       
   165 * \param	
       
   166 * \return	
       
   167 * \note		
       
   168 *//*-------------------------------------------------------------------*/
       
   169 
       
   170 #ifdef BUILD_WITH_PRIVATE_VGU
       
   171 VGUErrorCode RI_APIENTRY do_vguPolygon(VGPath path, const VGfloat * points, VGint count, VGboolean closed)
       
   172 #else
       
   173 VGUErrorCode RI_APIENTRY vguPolygon(VGPath path, const VGfloat * points, VGint count, VGboolean closed)
       
   174 #endif
       
   175 {
       
   176 	#ifdef BUILD_WITH_PRIVATE_OPENVG
       
   177 		VGErrorCode error = do_vgGetError();	
       
   178 	#else
       
   179 		VGErrorCode error = vgGetError();	//clear the error state	
       
   180 	#endif
       
   181 	
       
   182 	if(!points || (((RIuintptr)points) & 3) || count <= 0)
       
   183 		return VGU_ILLEGAL_ARGUMENT_ERROR;
       
   184 
       
   185 	VGubyte segments[1] = {VG_MOVE_TO | VG_ABSOLUTE};
       
   186 	VGfloat data[2];
       
   187 	for(int i=0;i<count;i++)
       
   188 	{
       
   189 		data[0] = points[i*2+0];
       
   190 		data[1] = points[i*2+1];
       
   191 		append(path, 1, segments, 2, data);
       
   192 		segments[0] = VG_LINE_TO | VG_ABSOLUTE;
       
   193 	}
       
   194 	if(closed)
       
   195 	{
       
   196 		segments[0] = VG_CLOSE_PATH;
       
   197 		append(path, 1, segments, 0, data);
       
   198 	}
       
   199 
       
   200 	#ifdef BUILD_WITH_PRIVATE_OPENVG
       
   201 		error = do_vgGetError();	
       
   202 	#else
       
   203 		error = vgGetError();	//clear the error state	
       
   204 	#endif
       
   205 	
       
   206 	if(error == VG_BAD_HANDLE_ERROR)
       
   207 		return VGU_BAD_HANDLE_ERROR;
       
   208 	else if(error == VG_PATH_CAPABILITY_ERROR)
       
   209 		return VGU_PATH_CAPABILITY_ERROR;
       
   210 	return VGU_NO_ERROR;
       
   211 }
       
   212 
       
   213 /*-------------------------------------------------------------------*//*!
       
   214 * \brief	
       
   215 * \param	
       
   216 * \return	
       
   217 * \note		
       
   218 *//*-------------------------------------------------------------------*/
       
   219 
       
   220 #ifdef BUILD_WITH_PRIVATE_VGU
       
   221 VGUErrorCode RI_APIENTRY do_vguRect(VGPath path, VGfloat x, VGfloat y, VGfloat width, VGfloat height)
       
   222 #else
       
   223 VGUErrorCode RI_APIENTRY vguRect(VGPath path, VGfloat x, VGfloat y, VGfloat width, VGfloat height)
       
   224 #endif
       
   225 {
       
   226 	#ifdef BUILD_WITH_PRIVATE_OPENVG
       
   227 		VGErrorCode error = do_vgGetError();	
       
   228 	#else
       
   229 		VGErrorCode error = vgGetError();	//clear the error state	
       
   230 	#endif
       
   231 	
       
   232 	if(width <= 0 || height <= 0)
       
   233 		return VGU_ILLEGAL_ARGUMENT_ERROR;
       
   234 
       
   235 	static const VGubyte segments[5] = {VG_MOVE_TO | VG_ABSOLUTE,
       
   236 										VG_HLINE_TO | VG_ABSOLUTE,
       
   237 										VG_VLINE_TO | VG_ABSOLUTE,
       
   238 										VG_HLINE_TO | VG_ABSOLUTE,
       
   239 										VG_CLOSE_PATH};
       
   240 	const VGfloat data[5] = {x, y, x + width, y + height, x};
       
   241 	append(path, 5, segments, 5, data);
       
   242 
       
   243 
       
   244 	#ifdef BUILD_WITH_PRIVATE_OPENVG
       
   245 		error = do_vgGetError();	
       
   246 	#else
       
   247 		error = vgGetError();	//clear the error state
       
   248 	#endif
       
   249 		
       
   250 	if(error == VG_BAD_HANDLE_ERROR)
       
   251 		return VGU_BAD_HANDLE_ERROR;
       
   252 	else if(error == VG_PATH_CAPABILITY_ERROR)
       
   253 		return VGU_PATH_CAPABILITY_ERROR;
       
   254 	return VGU_NO_ERROR;
       
   255 }
       
   256 
       
   257 /*-------------------------------------------------------------------*//*!
       
   258 * \brief	
       
   259 * \param	
       
   260 * \return	
       
   261 * \note		
       
   262 *//*-------------------------------------------------------------------*/
       
   263 #ifdef BUILD_WITH_PRIVATE_VGU
       
   264 VGUErrorCode RI_APIENTRY do_vguRoundRect(VGPath path, VGfloat x, VGfloat y, VGfloat width, VGfloat height, VGfloat arcWidth, VGfloat arcHeight)
       
   265 #else
       
   266 VGUErrorCode RI_APIENTRY vguRoundRect(VGPath path, VGfloat x, VGfloat y, VGfloat width, VGfloat height, VGfloat arcWidth, VGfloat arcHeight)
       
   267 #endif
       
   268 {
       
   269 	#ifdef BUILD_WITH_PRIVATE_OPENVG
       
   270 		VGErrorCode error = do_vgGetError();	
       
   271 	#else
       
   272 		VGErrorCode error = vgGetError();	//clear the error state
       
   273 	#endif
       
   274 	
       
   275 	if(width <= 0 || height <= 0)
       
   276 		return VGU_ILLEGAL_ARGUMENT_ERROR;
       
   277 
       
   278 	arcWidth = RI_CLAMP(arcWidth, 0.0f, width);
       
   279 	arcHeight = RI_CLAMP(arcHeight, 0.0f, height);
       
   280 
       
   281 	static const VGubyte segments[10] = {VG_MOVE_TO | VG_ABSOLUTE,
       
   282 										 VG_HLINE_TO | VG_ABSOLUTE,
       
   283 										 VG_SCCWARC_TO | VG_ABSOLUTE,
       
   284 										 VG_VLINE_TO | VG_ABSOLUTE,
       
   285 										 VG_SCCWARC_TO | VG_ABSOLUTE,
       
   286 										 VG_HLINE_TO | VG_ABSOLUTE,
       
   287 										 VG_SCCWARC_TO | VG_ABSOLUTE,
       
   288 										 VG_VLINE_TO | VG_ABSOLUTE,
       
   289 										 VG_SCCWARC_TO | VG_ABSOLUTE,
       
   290 										 VG_CLOSE_PATH};
       
   291 	const VGfloat data[26] = {x + arcWidth/2, y,
       
   292 							  x + width - arcWidth/2,
       
   293 							  arcWidth/2, arcHeight/2, 0, x + width, y + arcHeight/2,
       
   294 							  y + height - arcHeight/2,
       
   295 							  arcWidth/2, arcHeight/2, 0, x + width - arcWidth/2, y + height,
       
   296 							  x + arcWidth/2,
       
   297 							  arcWidth/2, arcHeight/2, 0, x, y + height - arcHeight/2,
       
   298 							  y + arcHeight/2,
       
   299 							  arcWidth/2, arcHeight/2, 0, x + arcWidth/2, y};
       
   300 	append(path, 10, segments, 26, data);
       
   301 
       
   302 	#ifdef BUILD_WITH_PRIVATE_OPENVG
       
   303 		do_vgGetError();	
       
   304 	#else
       
   305 		error = vgGetError();	//clear the error state
       
   306 	#endif
       
   307 	
       
   308 	if(error == VG_BAD_HANDLE_ERROR)
       
   309 		return VGU_BAD_HANDLE_ERROR;
       
   310 	else if(error == VG_PATH_CAPABILITY_ERROR)
       
   311 		return VGU_PATH_CAPABILITY_ERROR;
       
   312 	return VGU_NO_ERROR;
       
   313 }
       
   314 
       
   315 /*-------------------------------------------------------------------*//*!
       
   316 * \brief	
       
   317 * \param	
       
   318 * \return	
       
   319 * \note		
       
   320 *//*-------------------------------------------------------------------*/
       
   321 #ifdef BUILD_WITH_PRIVATE_VGU
       
   322 VGUErrorCode RI_APIENTRY do_vguEllipse(VGPath path, VGfloat cx, VGfloat cy, VGfloat width, VGfloat height)
       
   323 #else
       
   324 VGUErrorCode RI_APIENTRY vguEllipse(VGPath path, VGfloat cx, VGfloat cy, VGfloat width, VGfloat height)
       
   325 #endif
       
   326 {
       
   327 	#ifdef BUILD_WITH_PRIVATE_OPENVG
       
   328 		VGErrorCode error = do_vgGetError();	
       
   329 	#else
       
   330 		VGErrorCode error = vgGetError();	//clear the error state
       
   331 	#endif
       
   332 		
       
   333 	if(width <= 0 || height <= 0)
       
   334 		return VGU_ILLEGAL_ARGUMENT_ERROR;
       
   335 
       
   336 	static const VGubyte segments[4] = {VG_MOVE_TO | VG_ABSOLUTE,
       
   337 										VG_SCCWARC_TO | VG_ABSOLUTE,
       
   338 										VG_SCCWARC_TO | VG_ABSOLUTE,
       
   339 										VG_CLOSE_PATH};
       
   340 	const VGfloat data[12] = {cx + width/2, cy,
       
   341 							  width/2, height/2, 0, cx - width/2, cy,
       
   342 							  width/2, height/2, 0, cx + width/2, cy};
       
   343 	append(path, 4, segments, 12, data);
       
   344 
       
   345 	#ifdef BUILD_WITH_PRIVATE_OPENVG
       
   346 		error = do_vgGetError();	
       
   347 	#else
       
   348 		error = vgGetError();	//clear the error state
       
   349 	#endif
       
   350 		
       
   351 	if(error == VG_BAD_HANDLE_ERROR)
       
   352 		return VGU_BAD_HANDLE_ERROR;
       
   353 	else if(error == VG_PATH_CAPABILITY_ERROR)
       
   354 		return VGU_PATH_CAPABILITY_ERROR;
       
   355 	return VGU_NO_ERROR;
       
   356 }
       
   357 
       
   358 /*-------------------------------------------------------------------*//*!
       
   359 * \brief	
       
   360 * \param	
       
   361 * \return	
       
   362 * \note		
       
   363 *//*-------------------------------------------------------------------*/
       
   364 #ifdef BUILD_WITH_PRIVATE_VGU
       
   365 VGUErrorCode RI_APIENTRY do_vguArc(VGPath path, VGfloat x, VGfloat y, VGfloat width, VGfloat height, VGfloat startAngle, VGfloat angleExtent, VGUArcType arcType)
       
   366 #else
       
   367 VGUErrorCode RI_APIENTRY vguArc(VGPath path, VGfloat x, VGfloat y, VGfloat width, VGfloat height, VGfloat startAngle, VGfloat angleExtent, VGUArcType arcType)
       
   368 #endif
       
   369 {
       
   370 	#ifdef BUILD_WITH_PRIVATE_OPENVG
       
   371 		VGErrorCode error = do_vgGetError();	
       
   372 	#else
       
   373 		VGErrorCode error = vgGetError();	//clear the error state
       
   374 	#endif
       
   375 		
       
   376 	if((arcType != VGU_ARC_OPEN && arcType != VGU_ARC_CHORD && arcType != VGU_ARC_PIE) || width <= 0.0f || height <= 0.0f)
       
   377 		return VGU_ILLEGAL_ARGUMENT_ERROR;
       
   378 
       
   379 	startAngle = RI_DEG_TO_RAD(startAngle);
       
   380 	angleExtent = RI_DEG_TO_RAD(angleExtent);
       
   381 
       
   382 	VGfloat w = width/2.0f;
       
   383 	VGfloat h = height/2.0f;
       
   384 
       
   385 	VGubyte segments[1];
       
   386 	VGfloat data[5];
       
   387 
       
   388 	segments[0] = VG_MOVE_TO | VG_ABSOLUTE;
       
   389 	data[0] = x + w * (VGfloat)cos(startAngle);
       
   390 	data[1] = y + h * (VGfloat)sin(startAngle);
       
   391 	append(path, 1, segments, 2, data);
       
   392 
       
   393 	data[0] = w;
       
   394 	data[1] = h;
       
   395 	data[2] = 0.0f;
       
   396 	VGfloat endAngle = startAngle + angleExtent;
       
   397 	if(angleExtent >= 0.0f)
       
   398 	{
       
   399 		segments[0] = VG_SCCWARC_TO | VG_ABSOLUTE;
       
   400 		for(VGfloat a = startAngle + PI;a < endAngle; a += PI)
       
   401 		{
       
   402 			data[3] = x + w * (VGfloat)cos(a);
       
   403 			data[4] = y + h * (VGfloat)sin(a);
       
   404 			append(path, 1, segments, 5, data);
       
   405 		}
       
   406 	}
       
   407 	else
       
   408 	{
       
   409 		segments[0] = VG_SCWARC_TO | VG_ABSOLUTE;
       
   410 		for(VGfloat a = startAngle - PI;a > endAngle; a -= PI)
       
   411 		{
       
   412 			data[3] = x + w * (VGfloat)cos(a);
       
   413 			data[4] = y + h * (VGfloat)sin(a);
       
   414 			append(path, 1, segments, 5, data);
       
   415 		}
       
   416 	}
       
   417 	data[3] = x + w * (VGfloat)cos(endAngle);
       
   418 	data[4] = y + h * (VGfloat)sin(endAngle);
       
   419 	append(path, 1, segments, 5, data);
       
   420 
       
   421 	if(arcType == VGU_ARC_CHORD)
       
   422 	{
       
   423 		segments[0] = VG_CLOSE_PATH;
       
   424 		append(path, 1, segments, 0, data);
       
   425 	}
       
   426 	else if(arcType == VGU_ARC_PIE)
       
   427 	{
       
   428 		segments[0] = VG_LINE_TO | VG_ABSOLUTE;
       
   429 		data[0] = x;
       
   430 		data[1] = y;
       
   431 		append(path, 1, segments, 2, data);
       
   432 		segments[0] = VG_CLOSE_PATH;
       
   433 		append(path, 1, segments, 0, data);
       
   434 	}
       
   435 
       
   436 	#ifdef BUILD_WITH_PRIVATE_OPENVG
       
   437 		error = do_vgGetError();	
       
   438 	#else
       
   439 		error = vgGetError();	//clear the error state
       
   440 	#endif
       
   441 		
       
   442 	if(error == VG_BAD_HANDLE_ERROR)
       
   443 		return VGU_BAD_HANDLE_ERROR;
       
   444 	else if(error == VG_PATH_CAPABILITY_ERROR)
       
   445 		return VGU_PATH_CAPABILITY_ERROR;
       
   446 	return VGU_NO_ERROR;
       
   447 }
       
   448 
       
   449 /*-------------------------------------------------------------------*//*!
       
   450 * \brief	
       
   451 * \param	
       
   452 * \return	
       
   453 * \note		
       
   454 *//*-------------------------------------------------------------------*/
       
   455 #ifdef BUILD_WITH_PRIVATE_VGU
       
   456 VGUErrorCode RI_APIENTRY do_vguComputeWarpQuadToSquare(VGfloat sx0, VGfloat sy0, VGfloat sx1, VGfloat sy1, VGfloat sx2, VGfloat sy2, VGfloat sx3, VGfloat sy3, VGfloat * matrix)
       
   457 #else
       
   458 VGUErrorCode RI_APIENTRY vguComputeWarpQuadToSquare(VGfloat sx0, VGfloat sy0, VGfloat sx1, VGfloat sy1, VGfloat sx2, VGfloat sy2, VGfloat sx3, VGfloat sy3, VGfloat * matrix)
       
   459 #endif
       
   460 {
       
   461 	if(!matrix || ((RIuintptr)matrix) & 3)
       
   462 		return VGU_ILLEGAL_ARGUMENT_ERROR;
       
   463 
       
   464 	VGfloat mat[9];
       
   465 #ifdef BUILD_WITH_PRIVATE_VGU
       
   466 	VGUErrorCode ret = do_vguComputeWarpSquareToQuad(sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3, mat);
       
   467 #else
       
   468 	VGUErrorCode ret = vguComputeWarpSquareToQuad(sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3, mat);
       
   469 #endif
       
   470 	if(ret == VGU_BAD_WARP_ERROR)
       
   471 		return VGU_BAD_WARP_ERROR;
       
   472 	Matrix3x3 m(mat[0], mat[3], mat[6],
       
   473 				mat[1], mat[4], mat[7],
       
   474 				mat[2], mat[5], mat[8]);
       
   475 	bool nonsingular = m.invert();
       
   476 	if(!nonsingular)
       
   477 		return VGU_BAD_WARP_ERROR;
       
   478 	matrix[0] = m[0][0];
       
   479 	matrix[1] = m[1][0];
       
   480 	matrix[2] = m[2][0];
       
   481 	matrix[3] = m[0][1];
       
   482 	matrix[4] = m[1][1];
       
   483 	matrix[5] = m[2][1];
       
   484 	matrix[6] = m[0][2];
       
   485 	matrix[7] = m[1][2];
       
   486 	matrix[8] = m[2][2];
       
   487 	return VGU_NO_ERROR;
       
   488 }
       
   489 
       
   490 /*-------------------------------------------------------------------*//*!
       
   491 * \brief	
       
   492 * \param	
       
   493 * \return	
       
   494 * \note		
       
   495 *//*-------------------------------------------------------------------*/
       
   496 #ifdef BUILD_WITH_PRIVATE_VGU
       
   497 VGUErrorCode RI_APIENTRY do_vguComputeWarpSquareToQuad(VGfloat dx0, VGfloat dy0, VGfloat dx1, VGfloat dy1, VGfloat dx2, VGfloat dy2, VGfloat dx3, VGfloat dy3, VGfloat * matrix)
       
   498 #else
       
   499 VGUErrorCode RI_APIENTRY vguComputeWarpSquareToQuad(VGfloat dx0, VGfloat dy0, VGfloat dx1, VGfloat dy1, VGfloat dx2, VGfloat dy2, VGfloat dx3, VGfloat dy3, VGfloat * matrix)
       
   500 #endif
       
   501 {
       
   502 	if(!matrix || ((RIuintptr)matrix) & 3)
       
   503 		return VGU_ILLEGAL_ARGUMENT_ERROR;
       
   504 
       
   505 	//from Heckbert:Fundamentals of Texture Mapping and Image Warping
       
   506 	//Note that his mapping of vertices is different from OpenVG's
       
   507 	//(0,0) => (dx0,dy0)
       
   508 	//(1,0) => (dx1,dy1)
       
   509 	//(0,1) => (dx2,dy2)
       
   510 	//(1,1) => (dx3,dy3)
       
   511 
       
   512 	VGfloat diffx1 = dx1 - dx3;
       
   513 	VGfloat diffy1 = dy1 - dy3;
       
   514 	VGfloat diffx2 = dx2 - dx3;
       
   515 	VGfloat diffy2 = dy2 - dy3;
       
   516 
       
   517 	VGfloat det = diffx1*diffy2 - diffx2*diffy1;
       
   518 	if(det == 0.0f)
       
   519 		return VGU_BAD_WARP_ERROR;
       
   520 
       
   521 	VGfloat sumx = dx0 - dx1 + dx3 - dx2;
       
   522 	VGfloat sumy = dy0 - dy1 + dy3 - dy2;
       
   523 
       
   524 	if(sumx == 0.0f && sumy == 0.0f)
       
   525 	{	//affine mapping
       
   526 		matrix[0] = dx1 - dx0;
       
   527 		matrix[1] = dy1 - dy0;
       
   528 		matrix[2] = 0.0f;
       
   529 		matrix[3] = dx3 - dx1;
       
   530 		matrix[4] = dy3 - dy1;
       
   531 		matrix[5] = 0.0f;
       
   532 		matrix[6] = dx0;
       
   533 		matrix[7] = dy0;
       
   534 		matrix[8] = 1.0f;
       
   535 		return VGU_NO_ERROR;
       
   536 	}
       
   537 
       
   538 	VGfloat oodet = 1.0f / det;
       
   539 	VGfloat g = (sumx*diffy2 - diffx2*sumy) * oodet;
       
   540 	VGfloat h = (diffx1*sumy - sumx*diffy1) * oodet;
       
   541 
       
   542 	matrix[0] = dx1-dx0+g*dx1;
       
   543 	matrix[1] = dy1-dy0+g*dy1;
       
   544 	matrix[2] = g;
       
   545 	matrix[3] = dx2-dx0+h*dx2;
       
   546 	matrix[4] = dy2-dy0+h*dy2;
       
   547 	matrix[5] = h;
       
   548 	matrix[6] = dx0;
       
   549 	matrix[7] = dy0;
       
   550 	matrix[8] = 1.0f;
       
   551 	return VGU_NO_ERROR;
       
   552 }
       
   553 
       
   554 /*-------------------------------------------------------------------*//*!
       
   555 * \brief	
       
   556 * \param	
       
   557 * \return	
       
   558 * \note		
       
   559 *//*-------------------------------------------------------------------*/
       
   560 
       
   561 #ifdef BUILD_WITH_PRIVATE_VGU
       
   562 VGUErrorCode RI_APIENTRY do_vguComputeWarpQuadToQuad(VGfloat dx0, VGfloat dy0, VGfloat dx1, VGfloat dy1, VGfloat dx2, VGfloat dy2, VGfloat dx3, VGfloat dy3, VGfloat sx0, VGfloat sy0, VGfloat sx1, VGfloat sy1, VGfloat sx2, VGfloat sy2, VGfloat sx3, VGfloat sy3, VGfloat * matrix)
       
   563 #else
       
   564 VGUErrorCode RI_APIENTRY vguComputeWarpQuadToQuad(VGfloat dx0, VGfloat dy0, VGfloat dx1, VGfloat dy1, VGfloat dx2, VGfloat dy2, VGfloat dx3, VGfloat dy3, VGfloat sx0, VGfloat sy0, VGfloat sx1, VGfloat sy1, VGfloat sx2, VGfloat sy2, VGfloat sx3, VGfloat sy3, VGfloat * matrix)
       
   565 #endif
       
   566 {
       
   567 	if(!matrix || ((RIuintptr)matrix) & 3)
       
   568 		return VGU_ILLEGAL_ARGUMENT_ERROR;
       
   569 
       
   570 	VGfloat qtos[9];
       
   571 #ifdef BUILD_WITH_PRIVATE_VGU
       
   572 	VGUErrorCode ret1 = do_vguComputeWarpQuadToSquare(sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3, qtos);
       
   573 #else
       
   574 	VGUErrorCode ret1 = vguComputeWarpQuadToSquare(sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3, qtos);
       
   575 #endif
       
   576 	if(ret1 == VGU_BAD_WARP_ERROR)
       
   577 		return VGU_BAD_WARP_ERROR;
       
   578 
       
   579 	VGfloat stoq[9];
       
   580 #ifdef BUILD_WITH_PRIVATE_VGU
       
   581 	VGUErrorCode ret2 = do_vguComputeWarpSquareToQuad(dx0, dy0, dx1, dy1, dx2, dy2, dx3, dy3, stoq);
       
   582 #else
       
   583 	VGUErrorCode ret2 = vguComputeWarpSquareToQuad(dx0, dy0, dx1, dy1, dx2, dy2, dx3, dy3, stoq);
       
   584 #endif
       
   585 	if(ret2 == VGU_BAD_WARP_ERROR)
       
   586 		return VGU_BAD_WARP_ERROR;
       
   587 
       
   588 	Matrix3x3 m1(qtos[0], qtos[3], qtos[6],
       
   589 				 qtos[1], qtos[4], qtos[7],
       
   590 				 qtos[2], qtos[5], qtos[8]);
       
   591 	Matrix3x3 m2(stoq[0], stoq[3], stoq[6],
       
   592 				 stoq[1], stoq[4], stoq[7],
       
   593 				 stoq[2], stoq[5], stoq[8]);
       
   594 	Matrix3x3 r = m2 * m1;
       
   595 
       
   596 	matrix[0] = r[0][0];
       
   597 	matrix[1] = r[1][0];
       
   598 	matrix[2] = r[2][0];
       
   599 	matrix[3] = r[0][1];
       
   600 	matrix[4] = r[1][1];
       
   601 	matrix[5] = r[2][1];
       
   602 	matrix[6] = r[0][2];
       
   603 	matrix[7] = r[1][2];
       
   604 	matrix[8] = r[2][2];
       
   605 	return VGU_NO_ERROR;
       
   606 }