1 /**************************************************************************
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
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:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
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.
25 **************************************************************************/
27 #include "VG/openvg.h"
34 #include "util/u_debug.h"
35 #include "util/u_pointer.h"
40 static void vgu_append_float_coords(VGPath path
,
43 const VGfloat
*coords
,
46 VGubyte common_data
[40 * sizeof(VGfloat
)];
47 struct path
*p
= handle_to_path(path
);
49 vg_float_to_datatype(path_datatype(p
), common_data
, coords
, num_coords
);
50 vgAppendPathData(path
, num_cmds
, cmds
, common_data
);
53 VGUErrorCode
vguLine(VGPath path
,
54 VGfloat x0
, VGfloat y0
,
55 VGfloat x1
, VGfloat y1
)
57 static const VGubyte cmds
[] = {VG_MOVE_TO_ABS
, VG_LINE_TO_ABS
};
61 if (path
== VG_INVALID_HANDLE
) {
62 return VGU_BAD_HANDLE_ERROR
;
64 caps
= vgGetPathCapabilities(path
);
65 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
66 return VGU_PATH_CAPABILITY_ERROR
;
74 vgu_append_float_coords(path
, cmds
, 2, coords
, 4);
79 VGUErrorCode
vguPolygon(VGPath path
,
80 const VGfloat
* points
,
89 if (path
== VG_INVALID_HANDLE
) {
90 return VGU_BAD_HANDLE_ERROR
;
93 if (!points
|| count
<= 0 || !is_aligned(points
)) {
94 return VGU_ILLEGAL_ARGUMENT_ERROR
;
97 caps
= vgGetPathCapabilities(path
);
98 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
99 return VGU_PATH_CAPABILITY_ERROR
;
102 cmds
= malloc(sizeof(VGubyte
) * count
+ 1);
103 coords
= malloc(sizeof(VGfloat
) * count
* 2);
105 cmds
[0] = VG_MOVE_TO_ABS
;
106 coords
[0] = points
[0];
107 coords
[1] = points
[1];
108 for (i
= 1; i
< count
; ++i
) {
109 cmds
[i
] = VG_LINE_TO_ABS
;
110 coords
[2*i
+ 0] = points
[2*i
+ 0];
111 coords
[2*i
+ 1] = points
[2*i
+ 1];
115 cmds
[i
] = VG_CLOSE_PATH
;
119 vgu_append_float_coords(path
, cmds
, i
, coords
, 2*i
);
127 VGUErrorCode
vguRect(VGPath path
,
128 VGfloat x
, VGfloat y
,
129 VGfloat width
, VGfloat height
)
131 static const VGubyte cmds
[] = {VG_MOVE_TO_ABS
,
140 if (path
== VG_INVALID_HANDLE
) {
141 return VGU_BAD_HANDLE_ERROR
;
143 caps
= vgGetPathCapabilities(path
);
144 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
145 return VGU_PATH_CAPABILITY_ERROR
;
147 if (width
<= 0 || height
<= 0) {
148 return VGU_ILLEGAL_ARGUMENT_ERROR
;
157 vgu_append_float_coords(path
, cmds
, 5, coords
, 5);
162 VGUErrorCode
vguRoundRect(VGPath path
,
163 VGfloat x
, VGfloat y
,
169 static const VGubyte cmds
[] = {VG_MOVE_TO_ABS
,
183 if (path
== VG_INVALID_HANDLE
) {
184 return VGU_BAD_HANDLE_ERROR
;
186 caps
= vgGetPathCapabilities(path
);
187 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
188 return VGU_PATH_CAPABILITY_ERROR
;
190 if (width
<= 0 || height
<= 0) {
191 return VGU_ILLEGAL_ARGUMENT_ERROR
;
194 c
[0] = x
+ arcWidth
/2; c
[1] = y
;
196 c
[2] = width
- arcWidth
;
198 c
[3] = arcWidth
/2; c
[4] = arcHeight
/2; c
[5] = 0;
199 c
[6] = arcWidth
/2; c
[7] = arcHeight
/2;
201 c
[8] = height
- arcHeight
;
203 c
[9] = arcWidth
/2; c
[10] = arcHeight
/2; c
[11] = 0;
204 c
[12] = -arcWidth
/2; c
[13] = arcHeight
/2;
206 c
[14] = -(width
- arcWidth
);
208 c
[15] = arcWidth
/2; c
[16] = arcHeight
/2; c
[17] = 0;
209 c
[18] = -arcWidth
/2; c
[19] = -arcHeight
/2;
211 c
[20] = -(height
- arcHeight
);
213 c
[21] = arcWidth
/2; c
[22] = arcHeight
/2; c
[23] = 0;
214 c
[24] = arcWidth
/2; c
[25] = -arcHeight
/2;
216 vgu_append_float_coords(path
, cmds
, 10, c
, 26);
221 VGUErrorCode
vguEllipse(VGPath path
,
222 VGfloat cx
, VGfloat cy
,
226 static const VGubyte cmds
[] = {VG_MOVE_TO_ABS
,
234 if (path
== VG_INVALID_HANDLE
) {
235 return VGU_BAD_HANDLE_ERROR
;
237 caps
= vgGetPathCapabilities(path
);
238 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
239 return VGU_PATH_CAPABILITY_ERROR
;
241 if (width
<= 0 || height
<= 0) {
242 return VGU_ILLEGAL_ARGUMENT_ERROR
;
245 coords
[0] = cx
+ width
/2; coords
[1] = cy
;
247 coords
[2] = width
/2; coords
[3] = height
/2; coords
[4] = 0;
248 coords
[5] = -width
; coords
[6] = 0;
250 coords
[7] = width
/2; coords
[8] = height
/2; coords
[9] = 0;
251 coords
[10] = width
; coords
[11] = 0;
253 vgu_append_float_coords(path
, cmds
, 4, coords
, 11);
258 VGUErrorCode
vguArc(VGPath path
,
259 VGfloat x
, VGfloat y
,
260 VGfloat width
, VGfloat height
,
268 VGfloat last
= startAngle
+ angleExtent
;
271 if (path
== VG_INVALID_HANDLE
) {
272 return VGU_BAD_HANDLE_ERROR
;
274 caps
= vgGetPathCapabilities(path
);
275 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
276 return VGU_PATH_CAPABILITY_ERROR
;
278 if (width
<= 0 || height
<= 0) {
279 return VGU_ILLEGAL_ARGUMENT_ERROR
;
281 if (arcType
!= VGU_ARC_OPEN
&&
282 arcType
!= VGU_ARC_CHORD
&&
283 arcType
!= VGU_ARC_PIE
) {
284 return VGU_ILLEGAL_ARGUMENT_ERROR
;
287 cmds
[c
] = VG_MOVE_TO_ABS
; ++c
;
288 coords
[0] = x
+cos(DEGREES_TO_RADIANS(startAngle
))*width
/2;
289 coords
[1] = y
+sin(DEGREES_TO_RADIANS(startAngle
))*height
/2;
291 debug_printf("start [%f, %f]\n", coords
[0], coords
[1]);
294 if (angleExtent
> 0) {
295 VGfloat angle
= startAngle
+ 180;
296 while (angle
< last
) {
297 cmds
[c
] = VG_SCCWARC_TO_ABS
; ++c
;
298 coords
[i
] = width
/2; coords
[i
+1] = height
/2; coords
[i
+2] = 0;
299 coords
[i
+3] = x
+ cos(DEGREES_TO_RADIANS(angle
))*width
/2;
300 coords
[i
+4] = y
+ sin(DEGREES_TO_RADIANS(angle
))*height
/2;
302 debug_printf("1 [%f, %f]\n", coords
[i
+3],
308 cmds
[c
] = VG_SCCWARC_TO_ABS
; ++c
;
309 coords
[i
] = width
/2; coords
[i
+1] = height
/2; coords
[i
+2] = 0;
310 coords
[i
+3] = x
+cos(DEGREES_TO_RADIANS(last
))*width
/2;
311 coords
[i
+4] = y
+sin(DEGREES_TO_RADIANS(last
))*height
/2;
313 debug_printf("2 [%f, %f]\n", coords
[i
+3],
318 VGfloat angle
= startAngle
- 180;
319 while (angle
> last
) {
320 cmds
[c
] = VG_SCWARC_TO_ABS
; ++c
;
321 coords
[i
] = width
/2; coords
[i
+1] = height
/2; coords
[i
+2] = 0;
322 coords
[i
+3] = x
+ cos(DEGREES_TO_RADIANS(angle
)) * width
/2;
323 coords
[i
+4] = y
+ sin(DEGREES_TO_RADIANS(angle
)) * height
/2;
325 debug_printf("3 [%f, %f]\n", coords
[i
+3],
331 cmds
[c
] = VG_SCWARC_TO_ABS
; ++c
;
332 coords
[i
] = width
/2; coords
[i
+1] = height
/2; coords
[i
+2] = 0;
333 coords
[i
+3] = x
+ cos(DEGREES_TO_RADIANS(last
)) * width
/2;
334 coords
[i
+4] = y
+ sin(DEGREES_TO_RADIANS(last
)) * height
/2;
336 debug_printf("4 [%f, %f]\n", coords
[i
+3],
342 if (arcType
== VGU_ARC_PIE
) {
343 cmds
[c
] = VG_LINE_TO_ABS
; ++c
;
344 coords
[i
] = x
; coords
[i
+ 1] = y
;
347 if (arcType
== VGU_ARC_PIE
|| arcType
== VGU_ARC_CHORD
) {
348 cmds
[c
] = VG_CLOSE_PATH
;
354 vgu_append_float_coords(path
, cmds
, c
, coords
, i
);
359 VGUErrorCode
vguComputeWarpQuadToSquare(VGfloat sx0
, VGfloat sy0
,
360 VGfloat sx1
, VGfloat sy1
,
361 VGfloat sx2
, VGfloat sy2
,
362 VGfloat sx3
, VGfloat sy3
,
367 if (!matrix
|| !is_aligned(matrix
))
368 return VGU_ILLEGAL_ARGUMENT_ERROR
;
370 if (!matrix_quad_to_square(sx0
, sy0
,
375 return VGU_BAD_WARP_ERROR
;
377 if (!matrix_is_invertible(&mat
))
378 return VGU_BAD_WARP_ERROR
;
380 memcpy(matrix
, mat
.m
, sizeof(VGfloat
) * 9);
385 VGUErrorCode
vguComputeWarpSquareToQuad(VGfloat dx0
, VGfloat dy0
,
386 VGfloat dx1
, VGfloat dy1
,
387 VGfloat dx2
, VGfloat dy2
,
388 VGfloat dx3
, VGfloat dy3
,
393 if (!matrix
|| !is_aligned(matrix
))
394 return VGU_ILLEGAL_ARGUMENT_ERROR
;
396 if (!matrix_square_to_quad(dx0
, dy0
,
401 return VGU_BAD_WARP_ERROR
;
403 if (!matrix_is_invertible(&mat
))
404 return VGU_BAD_WARP_ERROR
;
406 memcpy(matrix
, mat
.m
, sizeof(VGfloat
) * 9);
411 VGUErrorCode
vguComputeWarpQuadToQuad(VGfloat dx0
, VGfloat dy0
,
412 VGfloat dx1
, VGfloat dy1
,
413 VGfloat dx2
, VGfloat dy2
,
414 VGfloat dx3
, VGfloat dy3
,
415 VGfloat sx0
, VGfloat sy0
,
416 VGfloat sx1
, VGfloat sy1
,
417 VGfloat sx2
, VGfloat sy2
,
418 VGfloat sx3
, VGfloat sy3
,
423 if (!matrix
|| !is_aligned(matrix
))
424 return VGU_ILLEGAL_ARGUMENT_ERROR
;
426 if (!matrix_quad_to_quad(dx0
, dy0
,
435 return VGU_BAD_WARP_ERROR
;
437 memcpy(matrix
, mat
.m
, sizeof(VGfloat
) * 9);