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"
33 #include "util/u_debug.h"
34 #include "util/u_pointer.h"
39 static VGboolean
is_aligned_to(const void *ptr
, VGbyte alignment
)
41 void *aligned
= align_pointer(ptr
, alignment
);
42 return (ptr
== aligned
) ? VG_TRUE
: VG_FALSE
;
45 static VGboolean
is_aligned(const void *ptr
)
47 return is_aligned_to(ptr
, 4);
50 static void vgu_append_float_coords(VGPath path
,
53 const VGfloat
*coords
,
56 VGubyte common_data
[40 * sizeof(VGfloat
)];
57 struct path
*p
= (struct path
*)path
;
59 vg_float_to_datatype(path_datatype(p
), common_data
, coords
, num_coords
);
60 vgAppendPathData(path
, num_cmds
, cmds
, common_data
);
63 VGUErrorCode
vguLine(VGPath path
,
64 VGfloat x0
, VGfloat y0
,
65 VGfloat x1
, VGfloat y1
)
67 static const VGubyte cmds
[] = {VG_MOVE_TO_ABS
, VG_LINE_TO_ABS
};
71 if (path
== VG_INVALID_HANDLE
) {
72 return VGU_BAD_HANDLE_ERROR
;
74 caps
= vgGetPathCapabilities(path
);
75 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
76 return VGU_PATH_CAPABILITY_ERROR
;
84 vgu_append_float_coords(path
, cmds
, 2, coords
, 4);
89 VGUErrorCode
vguPolygon(VGPath path
,
90 const VGfloat
* points
,
99 if (path
== VG_INVALID_HANDLE
) {
100 return VGU_BAD_HANDLE_ERROR
;
103 if (!points
|| count
<= 0 || !is_aligned(points
)) {
104 return VGU_ILLEGAL_ARGUMENT_ERROR
;
107 caps
= vgGetPathCapabilities(path
);
108 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
109 return VGU_PATH_CAPABILITY_ERROR
;
112 cmds
= malloc(sizeof(VGubyte
) * count
+ 1);
113 coords
= malloc(sizeof(VGfloat
) * count
* 2);
115 cmds
[0] = VG_MOVE_TO_ABS
;
116 coords
[0] = points
[0];
117 coords
[1] = points
[1];
118 for (i
= 1; i
< count
; ++i
) {
119 cmds
[i
] = VG_LINE_TO_ABS
;
120 coords
[2*i
+ 0] = points
[2*i
+ 0];
121 coords
[2*i
+ 1] = points
[2*i
+ 1];
125 cmds
[i
] = VG_CLOSE_PATH
;
129 vgu_append_float_coords(path
, cmds
, i
, coords
, 2*i
);
137 VGUErrorCode
vguRect(VGPath path
,
138 VGfloat x
, VGfloat y
,
139 VGfloat width
, VGfloat height
)
141 static const VGubyte cmds
[] = {VG_MOVE_TO_ABS
,
150 if (path
== VG_INVALID_HANDLE
) {
151 return VGU_BAD_HANDLE_ERROR
;
153 caps
= vgGetPathCapabilities(path
);
154 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
155 return VGU_PATH_CAPABILITY_ERROR
;
157 if (width
<= 0 || height
<= 0) {
158 return VGU_ILLEGAL_ARGUMENT_ERROR
;
167 vgu_append_float_coords(path
, cmds
, 5, coords
, 5);
172 VGUErrorCode
vguRoundRect(VGPath path
,
173 VGfloat x
, VGfloat y
,
179 static const VGubyte cmds
[] = {VG_MOVE_TO_ABS
,
193 if (path
== VG_INVALID_HANDLE
) {
194 return VGU_BAD_HANDLE_ERROR
;
196 caps
= vgGetPathCapabilities(path
);
197 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
198 return VGU_PATH_CAPABILITY_ERROR
;
200 if (width
<= 0 || height
<= 0) {
201 return VGU_ILLEGAL_ARGUMENT_ERROR
;
204 c
[0] = x
+ arcWidth
/2; c
[1] = y
;
206 c
[2] = width
- arcWidth
;
208 c
[3] = arcWidth
/2; c
[4] = arcHeight
/2; c
[5] = 0;
209 c
[6] = arcWidth
/2; c
[7] = arcHeight
/2;
211 c
[8] = height
- arcHeight
;
213 c
[9] = arcWidth
/2; c
[10] = arcHeight
/2; c
[11] = 0;
214 c
[12] = -arcWidth
/2; c
[13] = arcHeight
/2;
216 c
[14] = -(width
- arcWidth
);
218 c
[15] = arcWidth
/2; c
[16] = arcHeight
/2; c
[17] = 0;
219 c
[18] = -arcWidth
/2; c
[19] = -arcHeight
/2;
221 c
[20] = -(height
- arcHeight
);
223 c
[21] = arcWidth
/2; c
[22] = arcHeight
/2; c
[23] = 0;
224 c
[24] = arcWidth
/2; c
[25] = -arcHeight
/2;
226 vgu_append_float_coords(path
, cmds
, 10, c
, 26);
231 VGUErrorCode
vguEllipse(VGPath path
,
232 VGfloat cx
, VGfloat cy
,
236 static const VGubyte cmds
[] = {VG_MOVE_TO_ABS
,
244 if (path
== VG_INVALID_HANDLE
) {
245 return VGU_BAD_HANDLE_ERROR
;
247 caps
= vgGetPathCapabilities(path
);
248 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
249 return VGU_PATH_CAPABILITY_ERROR
;
251 if (width
<= 0 || height
<= 0) {
252 return VGU_ILLEGAL_ARGUMENT_ERROR
;
255 coords
[0] = cx
+ width
/2; coords
[1] = cy
;
257 coords
[2] = width
/2; coords
[3] = height
/2; coords
[4] = 0;
258 coords
[5] = -width
; coords
[6] = 0;
260 coords
[7] = width
/2; coords
[8] = height
/2; coords
[9] = 0;
261 coords
[10] = width
; coords
[11] = 0;
263 vgu_append_float_coords(path
, cmds
, 4, coords
, 11);
268 VGUErrorCode
vguArc(VGPath path
,
269 VGfloat x
, VGfloat y
,
270 VGfloat width
, VGfloat height
,
278 VGfloat last
= startAngle
+ angleExtent
;
281 if (path
== VG_INVALID_HANDLE
) {
282 return VGU_BAD_HANDLE_ERROR
;
284 caps
= vgGetPathCapabilities(path
);
285 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
286 return VGU_PATH_CAPABILITY_ERROR
;
288 if (width
<= 0 || height
<= 0) {
289 return VGU_ILLEGAL_ARGUMENT_ERROR
;
291 if (arcType
!= VGU_ARC_OPEN
&&
292 arcType
!= VGU_ARC_CHORD
&&
293 arcType
!= VGU_ARC_PIE
) {
294 return VGU_ILLEGAL_ARGUMENT_ERROR
;
297 cmds
[c
] = VG_MOVE_TO_ABS
; ++c
;
298 coords
[0] = x
+cos(DEGREES_TO_RADIANS(startAngle
))*width
/2;
299 coords
[1] = y
+sin(DEGREES_TO_RADIANS(startAngle
))*height
/2;
301 debug_printf("start [%f, %f]\n", coords
[0], coords
[1]);
304 if (angleExtent
> 0) {
305 VGfloat angle
= startAngle
+ 180;
306 while (angle
< last
) {
307 cmds
[c
] = VG_SCCWARC_TO_ABS
; ++c
;
308 coords
[i
] = width
/2; coords
[i
+1] = height
/2; coords
[i
+2] = 0;
309 coords
[i
+3] = x
+ cos(DEGREES_TO_RADIANS(angle
))*width
/2;
310 coords
[i
+4] = y
+ sin(DEGREES_TO_RADIANS(angle
))*height
/2;
312 debug_printf("1 [%f, %f]\n", coords
[i
+3],
318 cmds
[c
] = VG_SCCWARC_TO_ABS
; ++c
;
319 coords
[i
] = width
/2; coords
[i
+1] = height
/2; coords
[i
+2] = 0;
320 coords
[i
+3] = x
+cos(DEGREES_TO_RADIANS(last
))*width
/2;
321 coords
[i
+4] = y
+sin(DEGREES_TO_RADIANS(last
))*height
/2;
323 debug_printf("2 [%f, %f]\n", coords
[i
+3],
328 VGfloat angle
= startAngle
- 180;
329 while (angle
> last
) {
330 cmds
[c
] = VG_SCWARC_TO_ABS
; ++c
;
331 coords
[i
] = width
/2; coords
[i
+1] = height
/2; coords
[i
+2] = 0;
332 coords
[i
+3] = x
+ cos(DEGREES_TO_RADIANS(angle
)) * width
/2;
333 coords
[i
+4] = y
+ sin(DEGREES_TO_RADIANS(angle
)) * height
/2;
335 debug_printf("3 [%f, %f]\n", coords
[i
+3],
341 cmds
[c
] = VG_SCWARC_TO_ABS
; ++c
;
342 coords
[i
] = width
/2; coords
[i
+1] = height
/2; coords
[i
+2] = 0;
343 coords
[i
+3] = x
+ cos(DEGREES_TO_RADIANS(last
)) * width
/2;
344 coords
[i
+4] = y
+ sin(DEGREES_TO_RADIANS(last
)) * height
/2;
346 debug_printf("4 [%f, %f]\n", coords
[i
+3],
352 if (arcType
== VGU_ARC_PIE
) {
353 cmds
[c
] = VG_LINE_TO_ABS
; ++c
;
354 coords
[i
] = x
; coords
[i
+ 1] = y
;
357 if (arcType
== VGU_ARC_PIE
|| arcType
== VGU_ARC_CHORD
) {
358 cmds
[c
] = VG_CLOSE_PATH
;
364 vgu_append_float_coords(path
, cmds
, c
, coords
, i
);
369 VGUErrorCode
vguComputeWarpQuadToSquare(VGfloat sx0
, VGfloat sy0
,
370 VGfloat sx1
, VGfloat sy1
,
371 VGfloat sx2
, VGfloat sy2
,
372 VGfloat sx3
, VGfloat sy3
,
377 if (!matrix
|| !is_aligned(matrix
))
378 return VGU_ILLEGAL_ARGUMENT_ERROR
;
380 if (!matrix_quad_to_square(sx0
, sy0
,
385 return VGU_BAD_WARP_ERROR
;
387 if (!matrix_is_invertible(&mat
))
388 return VGU_BAD_WARP_ERROR
;
390 memcpy(matrix
, mat
.m
, sizeof(VGfloat
) * 9);
395 VGUErrorCode
vguComputeWarpSquareToQuad(VGfloat dx0
, VGfloat dy0
,
396 VGfloat dx1
, VGfloat dy1
,
397 VGfloat dx2
, VGfloat dy2
,
398 VGfloat dx3
, VGfloat dy3
,
403 if (!matrix
|| !is_aligned(matrix
))
404 return VGU_ILLEGAL_ARGUMENT_ERROR
;
406 if (!matrix_square_to_quad(dx0
, dy0
,
411 return VGU_BAD_WARP_ERROR
;
413 if (!matrix_is_invertible(&mat
))
414 return VGU_BAD_WARP_ERROR
;
416 memcpy(matrix
, mat
.m
, sizeof(VGfloat
) * 9);
421 VGUErrorCode
vguComputeWarpQuadToQuad(VGfloat dx0
, VGfloat dy0
,
422 VGfloat dx1
, VGfloat dy1
,
423 VGfloat dx2
, VGfloat dy2
,
424 VGfloat dx3
, VGfloat dy3
,
425 VGfloat sx0
, VGfloat sy0
,
426 VGfloat sx1
, VGfloat sy1
,
427 VGfloat sx2
, VGfloat sy2
,
428 VGfloat sx3
, VGfloat sy3
,
433 if (!matrix
|| !is_aligned(matrix
))
434 return VGU_ILLEGAL_ARGUMENT_ERROR
;
436 if (!matrix_quad_to_quad(dx0
, dy0
,
445 return VGU_BAD_WARP_ERROR
;
447 memcpy(matrix
, mat
.m
, sizeof(VGfloat
) * 9);