2 * Copyright (c) 2007 Ivan Leben
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library in the file COPYING;
16 * if not, write to the Free Software Foundation, Inc.,
17 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 #include <vg/openvg.h>
24 #include "shContext.h"
27 static VGUErrorCode shAppend(VGPath path, SHint commSize, const VGubyte *comm,
28 SHint dataSize, const VGfloat *data)
30 VGErrorCode err = VG_NO_ERROR;
31 VGPathDatatype type = vgGetParameterf(path, VG_PATH_DATATYPE);
32 VGfloat scale = vgGetParameterf(path, VG_PATH_SCALE);
33 VGfloat bias = vgGetParameterf(path, VG_PATH_BIAS);
34 SH_ASSERT(dataSize <= 26);
38 case VG_PATH_DATATYPE_S_8: {
40 SHint8 data8[26]; int i;
41 for (i=0; i<dataSize; ++i)
42 data8[i] = (SHint8)SH_FLOOR((data[i] - bias) / scale + 0.5f);
43 vgAppendPathData(path, commSize, comm, data8);
46 case VG_PATH_DATATYPE_S_16: {
48 SHint16 data16[26]; int i;
49 for (i=0; i<dataSize; ++i)
50 data16[i] = (SHint16)SH_FLOOR((data[i] - bias) / scale + 0.5f);
51 vgAppendPathData(path, commSize, comm, data16);
54 case VG_PATH_DATATYPE_S_32: {
56 SHint32 data32[26]; int i;
57 for (i=0; i<dataSize; ++i)
58 data32[i] = (SHint32)SH_FLOOR((data[i] - bias) / scale + 0.5f);
59 vgAppendPathData(path, commSize, comm, data32);
64 VGfloat dataF[26]; int i;
65 for (i=0; i<dataSize; ++i)
66 dataF[i] = (data[i] - bias) / scale;
67 vgAppendPathData(path, commSize, comm, dataF);
73 if (err == VG_PATH_CAPABILITY_ERROR)
74 return VGU_PATH_CAPABILITY_ERROR;
75 else if (err == VG_BAD_HANDLE_ERROR)
76 return VGU_BAD_HANDLE_ERROR;
77 else if (err == VG_OUT_OF_MEMORY_ERROR)
78 return VGU_OUT_OF_MEMORY_ERROR;
83 VGU_API_CALL VGUErrorCode vguLine(VGPath path,
84 VGfloat x0, VGfloat y0,
85 VGfloat x1, VGfloat y1)
87 VGUErrorCode err = VGU_NO_ERROR;
88 const VGubyte comm[] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS};
91 data[0] = x0; data[1] = y0;
92 data[2] = x1; data[3] = y1;
94 err = shAppend(path, 2, comm, 4, data);
98 VGU_API_CALL VGUErrorCode vguPolygon(VGPath path,
99 const VGfloat * points, VGint count,
103 VGubyte *comm = NULL;
104 VGUErrorCode err = VGU_NO_ERROR;
106 if (points == NULL || count <= 0)
107 return VGU_ILLEGAL_ARGUMENT_ERROR;
108 /* TODO: check points array alignment */
110 comm = (VGubyte*)malloc( (count+1) * sizeof(VGubyte) );
111 if (comm == NULL) return VGU_OUT_OF_MEMORY_ERROR;
113 comm[0] = VG_MOVE_TO_ABS;
114 for (i=1; i<count; ++i)
115 comm[i] = VG_LINE_TO_ABS;
116 comm[count] = VG_CLOSE_PATH;
118 if (closed) err = shAppend(path, count+1, comm, count*2, points);
119 else err = shAppend(path, count, comm, count*2, points);
125 VGU_API_CALL VGUErrorCode vguRect(VGPath path,
126 VGfloat x, VGfloat y,
127 VGfloat width, VGfloat height)
129 VGUErrorCode err = VGU_NO_ERROR;
132 VG_MOVE_TO_ABS, VG_HLINE_TO_REL,
133 VG_VLINE_TO_REL, VG_HLINE_TO_REL,
138 if (width <= 0 || height <= 0)
139 return VGU_ILLEGAL_ARGUMENT_ERROR;
141 data[0] = x; data[1] = y;
142 data[2] = width; data[3] = height;
145 err = shAppend(path, 5, comm, 5, data);
149 VGU_API_CALL VGUErrorCode vguRoundRect(VGPath path,
150 VGfloat x, VGfloat y,
151 VGfloat width, VGfloat height,
152 VGfloat arcWidth, VGfloat arcHeight)
154 VGUErrorCode err = VGU_NO_ERROR;
158 VG_HLINE_TO_REL, VG_SCCWARC_TO_REL,
159 VG_VLINE_TO_REL, VG_SCCWARC_TO_REL,
160 VG_HLINE_TO_REL, VG_SCCWARC_TO_REL,
161 VG_VLINE_TO_REL, VG_SCCWARC_TO_REL,
167 if (width <= 0 || height <= 0)
168 return VGU_ILLEGAL_ARGUMENT_ERROR;
170 SH_CLAMP(arcWidth, 0.0f, width);
171 SH_CLAMP(arcHeight, 0.0f, height);
175 data[0] = x + rx; data[1] = y;
177 data[2] = width - arcWidth;
178 data[3] = rx; data[4] = ry; data[5] = 0;
179 data[6] = rx; data[7] = ry;
181 data[8] = height - arcHeight;
182 data[9] = rx; data[10] = ry; data[11] = 0;
183 data[12] = -rx; data[13] = ry;
185 data[14] = -(width - arcWidth);
186 data[15] = rx; data[16] = ry; data[17] = 0;
187 data[18] = -rx; data[19] = -ry;
189 data[20] = -(height - arcHeight);
190 data[21] = rx; data[22] = ry; data[23] = 0;
191 data[24] = rx; data[25] = -ry;
193 err = shAppend(path, 10, comm, 26, data);
197 VGU_API_CALL VGUErrorCode vguEllipse(VGPath path,
198 VGfloat cx, VGfloat cy,
199 VGfloat width, VGfloat height)
201 VGUErrorCode err = VGU_NO_ERROR;
203 const VGubyte comm[] = {
204 VG_MOVE_TO_ABS, VG_SCCWARC_TO_REL,
205 VG_SCCWARC_TO_REL, VG_CLOSE_PATH};
209 if (width <= 0 || height <= 0)
210 return VGU_ILLEGAL_ARGUMENT_ERROR;
212 data[0] = cx + width/2; data[1] = cy;
214 data[2] = width/2; data[3] = height/2; data[4] = 0;
215 data[5] = -width; data[6] = 0;
217 data[7] = width/2; data[8] = height/2; data[9] = 0;
218 data[10] = width; data[11] = 0;
220 err = shAppend(path, 4, comm, 12, data);
226 VGU_API_CALL VGUErrorCode vguArc(VGPath path,
227 VGfloat x, VGfloat y,
228 VGfloat width, VGfloat height,
229 VGfloat startAngle, VGfloat angleExtent,
232 VGUErrorCode err = VGU_NO_ERROR;
234 VGubyte commStart[1] = {VG_MOVE_TO_ABS};
235 VGfloat dataStart[2];
237 VGubyte commArcCCW[1] = {VG_SCCWARC_TO_ABS};
238 VGubyte commArcCW[1] = {VG_SCWARC_TO_ABS};
241 VGubyte commEndPie[2] = {VG_LINE_TO_ABS, VG_CLOSE_PATH};
242 VGfloat dataEndPie[2];
244 VGubyte commEndChord[1] = {VG_CLOSE_PATH};
245 VGfloat dataEndChord[1] = {0.0f};
247 VGfloat alast, a = 0.0f;
248 VGfloat rx = width/2, ry = height/2;
250 if (width <= 0 || height <= 0)
251 return VGU_ILLEGAL_ARGUMENT_ERROR;
253 if (arcType != VGU_ARC_OPEN &&
254 arcType != VGU_ARC_CHORD &&
255 arcType != VGU_ARC_PIE)
256 return VGU_ILLEGAL_ARGUMENT_ERROR;
258 startAngle = SH_DEG2RAD(startAngle);
259 angleExtent = SH_DEG2RAD(angleExtent);
260 alast = startAngle + angleExtent;
262 dataStart[0] = x + SH_COS(startAngle) * rx;
263 dataStart[1] = y + SH_SIN(startAngle) * ry;
264 err = shAppend(path, 1, commStart, 2, dataStart);
265 if (err != VGU_NO_ERROR) return err;
271 if (angleExtent > 0) {
275 dataArc[3] = x + SH_COS(a) * rx;
276 dataArc[4] = y + SH_SIN(a) * ry;
277 err = shAppend(path, 1, commArcCCW, 5, dataArc);
278 if (err != VGU_NO_ERROR) return err;
281 dataArc[3] = x + SH_COS(alast) * rx;
282 dataArc[4] = y + SH_SIN(alast) * ry;
283 err = shAppend(path, 1, commArcCCW, 5, dataArc);
284 if (err != VGU_NO_ERROR) return err;
290 dataArc[3] = x + SH_COS(a) * rx;
291 dataArc[4] = y + SH_SIN(a) * ry;
292 err = shAppend(path, 1, commArcCW, 5, dataArc);
293 if (err != VGU_NO_ERROR) return err;
296 dataArc[3] = x + SH_COS(alast) * rx;
297 dataArc[4] = y + SH_SIN(alast) * ry;
298 err = shAppend(path, 1, commArcCW, 5, dataArc);
299 if (err != VGU_NO_ERROR) return err;
303 if (arcType == VGU_ARC_PIE) {
304 dataEndPie[0] = x; dataEndPie[1] = y;
305 err = shAppend(path, 2, commEndPie, 2, dataEndPie);
306 }else if (arcType == VGU_ARC_CHORD) {
307 err = shAppend(path, 1, commEndChord, 0, dataEndChord);
313 VGU_API_CALL VGUErrorCode vguComputeWarpQuadToSquare(VGfloat sx0, VGfloat sy0,
314 VGfloat sx1, VGfloat sy1,
315 VGfloat sx2, VGfloat sy2,
316 VGfloat sx3, VGfloat sy3,
319 /* Basic idea taken from the reference implementation */
321 VGfloat det, det00, det01, det02;
324 return VGU_ILLEGAL_ARGUMENT_ERROR;
326 if( vguComputeWarpSquareToQuad( sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3,
328 == VGU_BAD_WARP_ERROR )
329 return VGU_BAD_WARP_ERROR;
331 // Invert the matrix...
332 det00 = mat[1][1]*mat[2][2] - mat[2][1]*mat[1][2];
333 det01 = mat[2][0]*mat[1][2] - mat[1][0]*mat[2][2];
334 det02 = mat[1][0]*mat[2][1] - mat[2][0]*mat[1][1];
336 det = mat[0][0]*det00 + mat[0][1]*det01 + mat[0][2]*det02;
338 return VGU_BAD_WARP_ERROR;
342 matrix[0] = det * det00;
343 matrix[3] = det * det01;
344 matrix[6] = det * det02;
345 matrix[1] = det * (mat[2][1]*mat[0][2] - mat[0][1]*mat[2][2]);
346 matrix[4] = det * (mat[0][0]*mat[2][2] - mat[2][0]*mat[0][2]);
347 matrix[7] = det * (mat[2][0]*mat[0][1] - mat[0][0]*mat[2][1]);
348 matrix[2] = det * (mat[0][1]*mat[1][2] - mat[1][1]*mat[0][2]);
349 matrix[5] = det * (mat[1][0]*mat[0][2] - mat[0][0]*mat[1][2]);
350 matrix[8] = det * (mat[0][0]*mat[1][1] - mat[1][0]*mat[0][1]);
355 VGU_API_CALL VGUErrorCode vguComputeWarpSquareToQuad(VGfloat dx0, VGfloat dy0,
356 VGfloat dx1, VGfloat dy1,
357 VGfloat dx2, VGfloat dy2,
358 VGfloat dx3, VGfloat dy3,
361 /* Taken from https://github.com/mvr/shivavg (who has taken it from the
362 reference implementation) */
364 VGfloat diffx1 = dx1 - dx3;
365 VGfloat diffy1 = dy1 - dy3;
366 VGfloat diffx2 = dx2 - dx3;
367 VGfloat diffy2 = dy2 - dy3;
369 VGfloat det = diffx1*diffy2 - diffx2*diffy1;
371 VGfloat sumx = dx0 - dx1 + dx3 - dx2;
372 VGfloat sumy = dy0 - dy1 + dy3 - dy2;
377 return VGU_ILLEGAL_ARGUMENT_ERROR;
380 return VGU_BAD_WARP_ERROR;
382 if(sumx == 0.0f && sumy == 0.0f)
385 matrix[0] = dx1 - dx0;
386 matrix[1] = dy1 - dy0;
388 matrix[3] = dx3 - dx1;
389 matrix[4] = dy3 - dy1;
398 g = (sumx*diffy2 - diffx2*sumy) * oodet;
399 h = (diffx1*sumy - sumx*diffy1) * oodet;
401 matrix[0] = dx1-dx0+g*dx1;
402 matrix[1] = dy1-dy0+g*dy1;
404 matrix[3] = dx2-dx0+h*dx2;
405 matrix[4] = dy2-dy0+h*dy2;
414 VGU_API_CALL VGUErrorCode vguComputeWarpQuadToQuad(VGfloat dx0, VGfloat dy0,
415 VGfloat dx1, VGfloat dy1,
416 VGfloat dx2, VGfloat dy2,
417 VGfloat dx3, VGfloat dy3,
418 VGfloat sx0, VGfloat sy0,
419 VGfloat sx1, VGfloat sy1,
420 VGfloat sx2, VGfloat sy2,
421 VGfloat sx3, VGfloat sy3,