Tizen 2.0 Release
[profile/ivi/osmesa.git] / src / gallium / state_trackers / vega / vgu.c
1 /**************************************************************************
2  *
3  * Copyright 2009 VMware, Inc.  All Rights Reserved.
4  *
5  * Permission is hereby granted, free of charge, to any person obtaining a
6  * copy of this software and associated documentation files (the
7  * "Software"), to deal in the Software without restriction, including
8  * without limitation the rights to use, copy, modify, merge, publish,
9  * distribute, sub license, and/or sell copies of the Software, and to
10  * permit persons to whom the Software is furnished to do so, subject to
11  * the following conditions:
12  *
13  * The above copyright notice and this permission notice (including the
14  * next paragraph) shall be included in all copies or substantial portions
15  * of the Software.
16  *
17  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
18  * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
19  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
20  * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
21  * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
22  * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
23  * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
24  *
25  **************************************************************************/
26
27 #include "VG/openvg.h"
28 #include "VG/vgu.h"
29
30 #include "matrix.h"
31 #include "path.h"
32 #include "handle.h"
33
34 #include "util/u_debug.h"
35 #include "util/u_pointer.h"
36
37 #include <math.h>
38 #include <assert.h>
39
40
41 static void vgu_append_float_coords(VGPath path,
42                                     const VGubyte *cmds,
43                                     VGint num_cmds,
44                                     const VGfloat *coords,
45                                     VGint num_coords)
46 {
47    VGubyte common_data[40 * sizeof(VGfloat)];
48    struct path *p = handle_to_path(path);
49
50    vg_float_to_datatype(path_datatype(p), common_data, coords, num_coords);
51    vgAppendPathData(path, num_cmds, cmds, common_data);
52 }
53
54 VGUErrorCode vguLine(VGPath path,
55                      VGfloat x0, VGfloat y0,
56                      VGfloat x1, VGfloat y1)
57 {
58    static const VGubyte cmds[] = {VG_MOVE_TO_ABS, VG_LINE_TO_ABS};
59    VGfloat coords[4];
60    VGbitfield caps;
61
62    if (path == VG_INVALID_HANDLE) {
63       return VGU_BAD_HANDLE_ERROR;
64    }
65    caps = vgGetPathCapabilities(path);
66    if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
67       return VGU_PATH_CAPABILITY_ERROR;
68    }
69
70    coords[0] = x0;
71    coords[1] = y0;
72    coords[2] = x1;
73    coords[3] = y1;
74
75    vgu_append_float_coords(path, cmds, 2, coords, 4);
76
77    return VGU_NO_ERROR;
78 }
79
80 VGUErrorCode vguPolygon(VGPath path,
81                         const VGfloat * points,
82                         VGint count,
83                         VGboolean closed)
84 {
85    VGubyte *cmds;
86    VGfloat *coords;
87    VGbitfield caps;
88    VGint i;
89
90    if (path == VG_INVALID_HANDLE) {
91       return VGU_BAD_HANDLE_ERROR;
92    }
93
94    if (!points || count <= 0 || !is_aligned(points)) {
95       return VGU_ILLEGAL_ARGUMENT_ERROR;
96    }
97
98    caps = vgGetPathCapabilities(path);
99    if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
100       return VGU_PATH_CAPABILITY_ERROR;
101    }
102
103    cmds   = malloc(sizeof(VGubyte) * count + 1);
104    coords = malloc(sizeof(VGfloat) * count * 2);
105
106    cmds[0] = VG_MOVE_TO_ABS;
107    coords[0] = points[0];
108    coords[1] = points[1];
109    for (i = 1; i < count; ++i) {
110       cmds[i] = VG_LINE_TO_ABS;
111       coords[2*i + 0] = points[2*i + 0];
112       coords[2*i + 1] = points[2*i + 1];
113    }
114
115    if (closed) {
116       cmds[i] = VG_CLOSE_PATH;
117       ++i;
118    }
119
120    vgu_append_float_coords(path, cmds, i, coords, 2*i);
121
122    free(cmds);
123    free(coords);
124
125    return VGU_NO_ERROR;
126 }
127
128 VGUErrorCode  vguRect(VGPath path,
129                       VGfloat x, VGfloat y,
130                       VGfloat width, VGfloat height)
131 {
132    static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
133                                   VG_HLINE_TO_REL,
134                                   VG_VLINE_TO_REL,
135                                   VG_HLINE_TO_REL,
136                                   VG_CLOSE_PATH
137    };
138    VGfloat coords[5];
139    VGbitfield caps;
140
141    if (path == VG_INVALID_HANDLE) {
142       return VGU_BAD_HANDLE_ERROR;
143    }
144    caps = vgGetPathCapabilities(path);
145    if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
146       return VGU_PATH_CAPABILITY_ERROR;
147    }
148    if (width <= 0 || height <= 0) {
149       return VGU_ILLEGAL_ARGUMENT_ERROR;
150    }
151
152    coords[0] =  x;
153    coords[1] =  y;
154    coords[2] =  width;
155    coords[3] =  height;
156    coords[4] = -width;
157
158    vgu_append_float_coords(path, cmds, 5, coords, 5);
159
160    return VGU_NO_ERROR;
161 }
162
163 VGUErrorCode vguRoundRect(VGPath path,
164                           VGfloat x, VGfloat y,
165                           VGfloat width,
166                           VGfloat height,
167                           VGfloat arcWidth,
168                           VGfloat arcHeight)
169 {
170    static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
171                                   VG_HLINE_TO_REL,
172                                   VG_SCCWARC_TO_REL,
173                                   VG_VLINE_TO_REL,
174                                   VG_SCCWARC_TO_REL,
175                                   VG_HLINE_TO_REL,
176                                   VG_SCCWARC_TO_REL,
177                                   VG_VLINE_TO_REL,
178                                   VG_SCCWARC_TO_REL,
179                                   VG_CLOSE_PATH
180    };
181    VGfloat c[26];
182    VGbitfield caps;
183
184    if (path == VG_INVALID_HANDLE) {
185       return VGU_BAD_HANDLE_ERROR;
186    }
187    caps = vgGetPathCapabilities(path);
188    if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
189       return VGU_PATH_CAPABILITY_ERROR;
190    }
191    if (width <= 0 || height <= 0) {
192       return VGU_ILLEGAL_ARGUMENT_ERROR;
193    }
194
195    c[0] =  x + arcWidth/2; c[1] =  y;
196
197    c[2] = width - arcWidth;
198
199    c[3] = arcWidth/2; c[4] = arcHeight/2; c[5] = 0;
200    c[6] = arcWidth/2; c[7] = arcHeight/2;
201
202    c[8] = height - arcHeight;
203
204    c[9] = arcWidth/2; c[10] = arcHeight/2; c[11] = 0;
205    c[12] = -arcWidth/2; c[13] = arcHeight/2;
206
207    c[14] = -(width - arcWidth);
208
209    c[15] = arcWidth/2; c[16] = arcHeight/2; c[17] = 0;
210    c[18] = -arcWidth/2; c[19] = -arcHeight/2;
211
212    c[20] = -(height - arcHeight);
213
214    c[21] = arcWidth/2; c[22] = arcHeight/2; c[23] = 0;
215    c[24] = arcWidth/2; c[25] = -arcHeight/2;
216
217    vgu_append_float_coords(path, cmds, 10, c, 26);
218
219    return VGU_NO_ERROR;
220 }
221
222 VGUErrorCode vguEllipse(VGPath path,
223                         VGfloat cx, VGfloat cy,
224                         VGfloat width,
225                         VGfloat height)
226 {
227    static const VGubyte cmds[] = {VG_MOVE_TO_ABS,
228                                   VG_SCCWARC_TO_REL,
229                                   VG_SCCWARC_TO_REL,
230                                   VG_CLOSE_PATH
231    };
232    VGfloat coords[12];
233    VGbitfield caps;
234
235    if (path == VG_INVALID_HANDLE) {
236       return VGU_BAD_HANDLE_ERROR;
237    }
238    caps = vgGetPathCapabilities(path);
239    if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
240       return VGU_PATH_CAPABILITY_ERROR;
241    }
242    if (width <= 0 || height <= 0) {
243       return VGU_ILLEGAL_ARGUMENT_ERROR;
244    }
245
246    coords[0] = cx + width/2; coords[1] = cy;
247
248    coords[2] = width/2; coords[3] = height/2; coords[4] = 0;
249    coords[5] = -width; coords[6] = 0;
250
251    coords[7] = width/2; coords[8] = height/2; coords[9] = 0;
252    coords[10] = width; coords[11] = 0;
253
254    vgu_append_float_coords(path, cmds, 4, coords, 11);
255
256    return VGU_NO_ERROR;
257 }
258
259 VGUErrorCode vguArc(VGPath path,
260                     VGfloat x, VGfloat y,
261                     VGfloat width, VGfloat height,
262                     VGfloat startAngle,
263                     VGfloat angleExtent,
264                     VGUArcType arcType)
265 {
266    VGubyte cmds[11];
267    VGfloat coords[40];
268    VGbitfield caps;
269    VGfloat last = startAngle + angleExtent;
270    VGint i, c = 0;
271
272    if (path == VG_INVALID_HANDLE) {
273       return VGU_BAD_HANDLE_ERROR;
274    }
275    caps = vgGetPathCapabilities(path);
276    if (!(caps & VG_PATH_CAPABILITY_APPEND_TO)) {
277       return VGU_PATH_CAPABILITY_ERROR;
278    }
279    if (width <= 0 || height <= 0) {
280       return VGU_ILLEGAL_ARGUMENT_ERROR;
281    }
282    if (arcType != VGU_ARC_OPEN &&
283        arcType != VGU_ARC_CHORD &&
284        arcType != VGU_ARC_PIE) {
285       return VGU_ILLEGAL_ARGUMENT_ERROR;
286    }
287
288    cmds[c] = VG_MOVE_TO_ABS; ++c;
289    coords[0] = x+cos(DEGREES_TO_RADIANS(startAngle))*width/2;
290    coords[1] = y+sin(DEGREES_TO_RADIANS(startAngle))*height/2;
291 #ifdef DEBUG_VGUARC
292    debug_printf("start [%f, %f]\n", coords[0], coords[1]);
293 #endif
294    i = 2;
295    if (angleExtent > 0) {
296       VGfloat angle = startAngle + 180;
297       while (angle < last) {
298          cmds[c] = VG_SCCWARC_TO_ABS; ++c;
299          coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
300          coords[i+3] = x + cos(DEGREES_TO_RADIANS(angle))*width/2;
301          coords[i+4] = y + sin(DEGREES_TO_RADIANS(angle))*height/2;
302 #ifdef DEBUG_VGUARC
303          debug_printf("1 [%f, %f]\n", coords[i+3],
304                       coords[i+4]);
305 #endif
306          i += 5;
307          angle += 180;
308       }
309       cmds[c] = VG_SCCWARC_TO_ABS; ++c;
310       coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
311       coords[i+3] = x+cos(DEGREES_TO_RADIANS(last))*width/2;
312       coords[i+4] = y+sin(DEGREES_TO_RADIANS(last))*height/2;
313 #ifdef DEBUG_VGUARC
314       debug_printf("2 [%f, %f]\n", coords[i+3],
315                    coords[i+4]);
316 #endif
317       i += 5;
318    } else {
319       VGfloat angle = startAngle - 180;
320       while (angle > last) {
321          cmds[c] = VG_SCWARC_TO_ABS; ++c;
322          coords[i] =  width/2; coords[i+1] = height/2; coords[i+2] = 0;
323          coords[i+3] = x + cos(DEGREES_TO_RADIANS(angle)) * width/2;
324          coords[i+4] = y + sin(DEGREES_TO_RADIANS(angle)) * height/2;
325 #ifdef DEBUG_VGUARC
326          debug_printf("3 [%f, %f]\n", coords[i+3],
327                       coords[i+4]);
328 #endif
329          angle -= 180;
330          i += 5;
331       }
332       cmds[c] = VG_SCWARC_TO_ABS; ++c;
333       coords[i] = width/2; coords[i+1] = height/2; coords[i+2] = 0;
334       coords[i+3] = x + cos(DEGREES_TO_RADIANS(last)) * width/2;
335       coords[i+4] = y + sin(DEGREES_TO_RADIANS(last)) * height/2;
336 #ifdef DEBUG_VGUARC
337       debug_printf("4 [%f, %f]\n", coords[i+3],
338                    coords[i+4]);
339 #endif
340       i += 5;
341    }
342
343    if (arcType == VGU_ARC_PIE) {
344       cmds[c] = VG_LINE_TO_ABS; ++c;
345       coords[i] = x; coords[i + 1] = y;
346       i += 2;
347    }
348    if (arcType == VGU_ARC_PIE || arcType == VGU_ARC_CHORD) {
349       cmds[c] = VG_CLOSE_PATH;
350       ++c;
351    }
352
353    assert(c < 11);
354
355    vgu_append_float_coords(path, cmds, c, coords, i);
356
357    return VGU_NO_ERROR;
358 }
359
360 VGUErrorCode vguComputeWarpQuadToSquare(VGfloat sx0, VGfloat sy0,
361                                         VGfloat sx1, VGfloat sy1,
362                                         VGfloat sx2, VGfloat sy2,
363                                         VGfloat sx3, VGfloat sy3,
364                                         VGfloat * matrix)
365 {
366    struct matrix mat;
367
368    if (!matrix || !is_aligned(matrix))
369       return VGU_ILLEGAL_ARGUMENT_ERROR;
370
371    if (!matrix_quad_to_square(sx0, sy0,
372                               sx1, sy1,
373                               sx2, sy2,
374                               sx3, sy3,
375                               &mat))
376       return VGU_BAD_WARP_ERROR;
377
378    if (!matrix_is_invertible(&mat))
379       return VGU_BAD_WARP_ERROR;
380
381    memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
382
383    return VGU_NO_ERROR;
384 }
385
386 VGUErrorCode vguComputeWarpSquareToQuad(VGfloat dx0, VGfloat dy0,
387                                         VGfloat dx1, VGfloat dy1,
388                                         VGfloat dx2, VGfloat dy2,
389                                         VGfloat dx3, VGfloat dy3,
390                                         VGfloat * matrix)
391 {
392    struct matrix mat;
393
394    if (!matrix || !is_aligned(matrix))
395       return VGU_ILLEGAL_ARGUMENT_ERROR;
396
397    if (!matrix_square_to_quad(dx0, dy0,
398                               dx1, dy1,
399                               dx2, dy2,
400                               dx3, dy3,
401                               &mat))
402       return VGU_BAD_WARP_ERROR;
403
404    if (!matrix_is_invertible(&mat))
405       return VGU_BAD_WARP_ERROR;
406
407    memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
408
409    return VGU_NO_ERROR;
410 }
411
412 VGUErrorCode vguComputeWarpQuadToQuad(VGfloat dx0, VGfloat dy0,
413                                       VGfloat dx1, VGfloat dy1,
414                                       VGfloat dx2, VGfloat dy2,
415                                       VGfloat dx3, VGfloat dy3,
416                                       VGfloat sx0, VGfloat sy0,
417                                       VGfloat sx1, VGfloat sy1,
418                                       VGfloat sx2, VGfloat sy2,
419                                       VGfloat sx3, VGfloat sy3,
420                                       VGfloat * matrix)
421 {
422    struct matrix mat;
423
424    if (!matrix || !is_aligned(matrix))
425       return VGU_ILLEGAL_ARGUMENT_ERROR;
426
427    if (!matrix_quad_to_quad(dx0, dy0,
428                             dx1, dy1,
429                             dx2, dy2,
430                             dx3, dy3,
431                             sx0, sy0,
432                             sx1, sy1,
433                             sx2, sy2,
434                             sx3, sy3,
435                             &mat))
436       return VGU_BAD_WARP_ERROR;
437
438    memcpy(matrix, mat.m, sizeof(VGfloat) * 9);
439
440    return VGU_NO_ERROR;
441 }