]> git.mxchange.org Git - simgear.git/blob - simgear/canvas/ShivaVG/src/shVgu.c
Update for OpenSceneGraph 3.3.2 API changes.
[simgear.git] / simgear / canvas / ShivaVG / src / shVgu.c
1 /*
2  * Copyright (c) 2007 Ivan Leben
3  *
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.
8  * 
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.
13  * 
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
18  *
19  */
20
21 #include <vg/openvg.h>
22 #include <vg/vgu.h>
23 #include "shDefs.h"
24 #include "shContext.h"
25 #include <math.h>
26
27 static VGUErrorCode shAppend(VGPath path, SHint commSize, const VGubyte *comm,
28                              SHint dataSize, const VGfloat *data)
29 {
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);
35   
36   switch(type)
37   {
38   case VG_PATH_DATATYPE_S_8: {
39       
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);
44       
45       break;}
46   case VG_PATH_DATATYPE_S_16: {
47       
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);
52       
53       break;}
54   case VG_PATH_DATATYPE_S_32: {
55       
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);
60       
61       break;}
62   default: {
63       
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);
68       
69       break;}
70   }
71   
72   err = vgGetError();
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;
79   
80   return VGU_NO_ERROR;
81 }
82
83 VGU_API_CALL VGUErrorCode vguLine(VGPath path,
84                                   VGfloat x0, VGfloat y0,
85                                   VGfloat x1, VGfloat y1)
86 {
87   VGUErrorCode err = VGU_NO_ERROR;
88   const VGubyte comm[] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS};
89   
90   VGfloat data[4];
91   data[0] = x0; data[1] = y0;
92   data[2] = x1; data[3] = y1;
93   
94   err = shAppend(path, 2, comm, 4, data);
95   return err;
96 }
97
98 VGU_API_CALL VGUErrorCode vguPolygon(VGPath path,
99                                      const VGfloat * points, VGint count,
100                                      VGboolean closed)
101 {
102   VGint i;
103   VGubyte *comm = NULL;
104   VGUErrorCode err = VGU_NO_ERROR;
105   
106   if (points == NULL || count <= 0)
107     return VGU_ILLEGAL_ARGUMENT_ERROR;
108   /* TODO: check points array alignment */
109   
110   comm = (VGubyte*)malloc( (count+1) * sizeof(VGubyte) );
111   if (comm == NULL) return VGU_OUT_OF_MEMORY_ERROR;
112   
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;
117   
118   if (closed) err = shAppend(path, count+1, comm, count*2, points);
119   else        err = shAppend(path, count, comm, count*2, points);
120   
121   free(comm);
122   return err;
123 }
124
125 VGU_API_CALL VGUErrorCode vguRect(VGPath path,
126                                   VGfloat x, VGfloat y,
127                                   VGfloat width, VGfloat height)
128 {
129   VGUErrorCode err = VGU_NO_ERROR;
130   
131   VGubyte comm[5] = {
132     VG_MOVE_TO_ABS, VG_HLINE_TO_REL,
133     VG_VLINE_TO_REL, VG_HLINE_TO_REL,
134     VG_CLOSE_PATH };
135   
136   VGfloat data[5];
137   
138   if (width <= 0 || height <= 0)
139     return VGU_ILLEGAL_ARGUMENT_ERROR;
140   
141   data[0] =  x;     data[1] = y;
142   data[2] =  width; data[3] = height;
143   data[4] = -width;
144   
145   err = shAppend(path, 5, comm, 5, data);
146   return err;
147 }
148
149 VGU_API_CALL VGUErrorCode vguRoundRect(VGPath path,
150                                        VGfloat x, VGfloat y,
151                                        VGfloat width, VGfloat height,
152                                        VGfloat arcWidth, VGfloat arcHeight)
153 {
154   VGUErrorCode err = VGU_NO_ERROR;
155   
156   VGubyte comm[10] = {
157     VG_MOVE_TO_ABS,
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,
162     VG_CLOSE_PATH };
163   
164   VGfloat data[26];
165   VGfloat rx, ry;
166   
167   if (width <= 0 || height <= 0)
168     return VGU_ILLEGAL_ARGUMENT_ERROR;
169   
170   SH_CLAMP(arcWidth, 0.0f, width);
171   SH_CLAMP(arcHeight, 0.0f, height);
172   rx = arcWidth/2;
173   ry = arcHeight/2;
174   
175   data[0]  =  x + rx; data[1] = y;
176   
177   data[2]  =  width - arcWidth;
178   data[3]  =  rx; data[4]  =  ry; data[5]  = 0;
179   data[6]  =  rx; data[7]  =  ry;
180   
181   data[8]  =  height - arcHeight;
182   data[9]  =  rx; data[10] =  ry; data[11] = 0;
183   data[12] = -rx; data[13] =  ry;
184   
185   data[14] = -(width - arcWidth);
186   data[15] =  rx; data[16] =  ry; data[17] = 0;
187   data[18] = -rx; data[19] = -ry;
188   
189   data[20] = -(height - arcHeight);
190   data[21] =  rx; data[22] =  ry; data[23] = 0;
191   data[24] =  rx; data[25] = -ry;
192   
193   err = shAppend(path, 10, comm, 26, data);
194   return err;
195 }
196
197 VGU_API_CALL VGUErrorCode vguEllipse(VGPath path,
198                                      VGfloat cx, VGfloat cy,
199                                      VGfloat width, VGfloat height)
200 {
201   VGUErrorCode err = VGU_NO_ERROR;
202   
203   const VGubyte comm[] = {
204     VG_MOVE_TO_ABS, VG_SCCWARC_TO_REL,
205     VG_SCCWARC_TO_REL, VG_CLOSE_PATH};
206   
207   VGfloat data[12];
208   
209   if (width <= 0 || height <= 0)
210     return VGU_ILLEGAL_ARGUMENT_ERROR;
211   
212   data[0] = cx + width/2; data[1] = cy;
213   
214   data[2] = width/2; data[3] = height/2; data[4] = 0;
215   data[5] = -width; data[6] = 0;
216   
217   data[7] = width/2; data[8] = height/2; data[9] = 0;
218   data[10] = width; data[11] = 0;
219   
220   err = shAppend(path, 4, comm, 12, data);
221   return err;
222 }
223
224 #include <stdio.h>
225
226 VGU_API_CALL VGUErrorCode vguArc(VGPath path,
227                                  VGfloat x, VGfloat y,
228                                  VGfloat width, VGfloat height,
229                                  VGfloat startAngle, VGfloat angleExtent,
230                                  VGUArcType arcType)
231 {
232   VGUErrorCode err = VGU_NO_ERROR;
233   
234   VGubyte commStart[1] = {VG_MOVE_TO_ABS};
235   VGfloat dataStart[2];
236   
237   VGubyte commArcCCW[1] = {VG_SCCWARC_TO_ABS};
238   VGubyte commArcCW[1]  = {VG_SCWARC_TO_ABS};
239   VGfloat dataArc[5];
240   
241   VGubyte commEndPie[2] = {VG_LINE_TO_ABS, VG_CLOSE_PATH};
242   VGfloat dataEndPie[2];
243   
244   VGubyte commEndChord[1] = {VG_CLOSE_PATH};
245   VGfloat dataEndChord[1] = {0.0f};
246   
247   VGfloat alast, a = 0.0f;
248   VGfloat rx = width/2, ry = height/2;
249   
250   if (width <= 0 || height <= 0)
251     return VGU_ILLEGAL_ARGUMENT_ERROR;
252   
253   if (arcType != VGU_ARC_OPEN &&
254       arcType != VGU_ARC_CHORD &&
255       arcType != VGU_ARC_PIE)
256       return VGU_ILLEGAL_ARGUMENT_ERROR;
257   
258   startAngle = SH_DEG2RAD(startAngle);
259   angleExtent = SH_DEG2RAD(angleExtent);
260   alast = startAngle + angleExtent;
261   
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;
266   
267   dataArc[0] = rx;
268   dataArc[1] = ry;
269   dataArc[2] = 0.0f;
270   
271   if (angleExtent > 0) {
272     
273     a = startAngle + PI;
274     while (a < alast) {
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;
279       a += PI; }
280     
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;
285     
286   }else{
287     
288     a = startAngle - PI;
289     while (a > alast) {
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;
294       a -= PI; }
295     
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;
300   }
301   
302   
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);
308   }
309   
310   return err;
311 }
312
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,
317                                                      VGfloat *matrix)
318 {
319   /* Basic idea taken from the reference implementation */
320   VGfloat mat[3][3];
321   VGfloat det, det00, det01, det02;
322
323   if( !matrix )
324     return VGU_ILLEGAL_ARGUMENT_ERROR;
325
326   if(    vguComputeWarpSquareToQuad( sx0, sy0, sx1, sy1, sx2, sy2, sx3, sy3,
327                                      (VGfloat*)mat )
328       == VGU_BAD_WARP_ERROR )
329     return VGU_BAD_WARP_ERROR;
330
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];
335
336   det = mat[0][0]*det00 + mat[0][1]*det01 + mat[0][2]*det02;
337   if( det == 0.0f )
338     return VGU_BAD_WARP_ERROR;
339
340   det = 1 / det;
341
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]);
351
352   return VGU_NO_ERROR;
353 }
354
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,
359                                                      VGfloat * matrix)
360 {
361   /* Taken from https://github.com/mvr/shivavg (who has taken it from the
362      reference implementation) */
363
364   VGfloat diffx1 = dx1 - dx3;
365   VGfloat diffy1 = dy1 - dy3;
366   VGfloat diffx2 = dx2 - dx3;
367   VGfloat diffy2 = dy2 - dy3;
368
369   VGfloat det = diffx1*diffy2 - diffx2*diffy1;
370
371   VGfloat sumx = dx0 - dx1 + dx3 - dx2;
372   VGfloat sumy = dy0 - dy1 + dy3 - dy2;
373
374   VGfloat g, h, oodet;
375
376   if(!matrix)
377     return VGU_ILLEGAL_ARGUMENT_ERROR;
378
379   if(det == 0.0f)
380     return VGU_BAD_WARP_ERROR;
381
382   if(sumx == 0.0f && sumy == 0.0f)
383   {
384     /* Affine mapping */
385     matrix[0] = dx1 - dx0;
386     matrix[1] = dy1 - dy0;
387     matrix[2] = 0.0f;
388     matrix[3] = dx3 - dx1;
389     matrix[4] = dy3 - dy1;
390     matrix[5] = 0.0f;
391     matrix[6] = dx0;
392     matrix[7] = dy0;
393     matrix[8] = 1.0f;
394     return VGU_NO_ERROR;
395   }
396
397   oodet = 1.0f / det;
398   g = (sumx*diffy2 - diffx2*sumy) * oodet;
399   h = (diffx1*sumy - sumx*diffy1) * oodet;
400
401   matrix[0] = dx1-dx0+g*dx1;
402   matrix[1] = dy1-dy0+g*dy1;
403   matrix[2] = g;
404   matrix[3] = dx2-dx0+h*dx2;
405   matrix[4] = dy2-dy0+h*dy2;
406   matrix[5] = h;
407   matrix[6] = dx0;
408   matrix[7] = dy0;
409   matrix[8] = 1.0f;
410
411   return VGU_NO_ERROR;
412 }
413
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,
422                                                    VGfloat * matrix)
423 {
424   return VGU_NO_ERROR;
425 }