|
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 } |