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"
41 static void vgu_append_float_coords(VGPath path
,
44 const VGfloat
*coords
,
47 VGubyte common_data
[40 * sizeof(VGfloat
)];
48 struct path
*p
= handle_to_path(path
);
50 vg_float_to_datatype(path_datatype(p
), common_data
, coords
, num_coords
);
51 vgAppendPathData(path
, num_cmds
, cmds
, common_data
);
54 VGUErrorCode
vguLine(VGPath path
,
55 VGfloat x0
, VGfloat y0
,
56 VGfloat x1
, VGfloat y1
)
58 static const VGubyte cmds
[] = {VG_MOVE_TO_ABS
, VG_LINE_TO_ABS
};
62 if (path
== VG_INVALID_HANDLE
) {
63 return VGU_BAD_HANDLE_ERROR
;
65 caps
= vgGetPathCapabilities(path
);
66 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
67 return VGU_PATH_CAPABILITY_ERROR
;
75 vgu_append_float_coords(path
, cmds
, 2, coords
, 4);
80 VGUErrorCode
vguPolygon(VGPath path
,
81 const VGfloat
* points
,
90 if (path
== VG_INVALID_HANDLE
) {
91 return VGU_BAD_HANDLE_ERROR
;
94 if (!points
|| count
<= 0 || !is_aligned(points
)) {
95 return VGU_ILLEGAL_ARGUMENT_ERROR
;
98 caps
= vgGetPathCapabilities(path
);
99 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
100 return VGU_PATH_CAPABILITY_ERROR
;
103 cmds
= malloc(sizeof(VGubyte
) * count
+ 1);
104 coords
= malloc(sizeof(VGfloat
) * count
* 2);
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];
116 cmds
[i
] = VG_CLOSE_PATH
;
120 vgu_append_float_coords(path
, cmds
, i
, coords
, 2*i
);
128 VGUErrorCode
vguRect(VGPath path
,
129 VGfloat x
, VGfloat y
,
130 VGfloat width
, VGfloat height
)
132 static const VGubyte cmds
[] = {VG_MOVE_TO_ABS
,
141 if (path
== VG_INVALID_HANDLE
) {
142 return VGU_BAD_HANDLE_ERROR
;
144 caps
= vgGetPathCapabilities(path
);
145 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
146 return VGU_PATH_CAPABILITY_ERROR
;
148 if (width
<= 0 || height
<= 0) {
149 return VGU_ILLEGAL_ARGUMENT_ERROR
;
158 vgu_append_float_coords(path
, cmds
, 5, coords
, 5);
163 VGUErrorCode
vguRoundRect(VGPath path
,
164 VGfloat x
, VGfloat y
,
170 static const VGubyte cmds
[] = {VG_MOVE_TO_ABS
,
184 if (path
== VG_INVALID_HANDLE
) {
185 return VGU_BAD_HANDLE_ERROR
;
187 caps
= vgGetPathCapabilities(path
);
188 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
189 return VGU_PATH_CAPABILITY_ERROR
;
191 if (width
<= 0 || height
<= 0) {
192 return VGU_ILLEGAL_ARGUMENT_ERROR
;
195 c
[0] = x
+ arcWidth
/2; c
[1] = y
;
197 c
[2] = width
- arcWidth
;
199 c
[3] = arcWidth
/2; c
[4] = arcHeight
/2; c
[5] = 0;
200 c
[6] = arcWidth
/2; c
[7] = arcHeight
/2;
202 c
[8] = height
- arcHeight
;
204 c
[9] = arcWidth
/2; c
[10] = arcHeight
/2; c
[11] = 0;
205 c
[12] = -arcWidth
/2; c
[13] = arcHeight
/2;
207 c
[14] = -(width
- arcWidth
);
209 c
[15] = arcWidth
/2; c
[16] = arcHeight
/2; c
[17] = 0;
210 c
[18] = -arcWidth
/2; c
[19] = -arcHeight
/2;
212 c
[20] = -(height
- arcHeight
);
214 c
[21] = arcWidth
/2; c
[22] = arcHeight
/2; c
[23] = 0;
215 c
[24] = arcWidth
/2; c
[25] = -arcHeight
/2;
217 vgu_append_float_coords(path
, cmds
, 10, c
, 26);
222 VGUErrorCode
vguEllipse(VGPath path
,
223 VGfloat cx
, VGfloat cy
,
227 static const VGubyte cmds
[] = {VG_MOVE_TO_ABS
,
235 if (path
== VG_INVALID_HANDLE
) {
236 return VGU_BAD_HANDLE_ERROR
;
238 caps
= vgGetPathCapabilities(path
);
239 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
240 return VGU_PATH_CAPABILITY_ERROR
;
242 if (width
<= 0 || height
<= 0) {
243 return VGU_ILLEGAL_ARGUMENT_ERROR
;
246 coords
[0] = cx
+ width
/2; coords
[1] = cy
;
248 coords
[2] = width
/2; coords
[3] = height
/2; coords
[4] = 0;
249 coords
[5] = -width
; coords
[6] = 0;
251 coords
[7] = width
/2; coords
[8] = height
/2; coords
[9] = 0;
252 coords
[10] = width
; coords
[11] = 0;
254 vgu_append_float_coords(path
, cmds
, 4, coords
, 11);
259 VGUErrorCode
vguArc(VGPath path
,
260 VGfloat x
, VGfloat y
,
261 VGfloat width
, VGfloat height
,
269 VGfloat last
= startAngle
+ angleExtent
;
272 if (path
== VG_INVALID_HANDLE
) {
273 return VGU_BAD_HANDLE_ERROR
;
275 caps
= vgGetPathCapabilities(path
);
276 if (!(caps
& VG_PATH_CAPABILITY_APPEND_TO
)) {
277 return VGU_PATH_CAPABILITY_ERROR
;
279 if (width
<= 0 || height
<= 0) {
280 return VGU_ILLEGAL_ARGUMENT_ERROR
;
282 if (arcType
!= VGU_ARC_OPEN
&&
283 arcType
!= VGU_ARC_CHORD
&&
284 arcType
!= VGU_ARC_PIE
) {
285 return VGU_ILLEGAL_ARGUMENT_ERROR
;
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;
292 debug_printf("start [%f, %f]\n", coords
[0], coords
[1]);
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;
303 debug_printf("1 [%f, %f]\n", coords
[i
+3],
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;
314 debug_printf("2 [%f, %f]\n", coords
[i
+3],
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;
326 debug_printf("3 [%f, %f]\n", coords
[i
+3],
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;
337 debug_printf("4 [%f, %f]\n", coords
[i
+3],
343 if (arcType
== VGU_ARC_PIE
) {
344 cmds
[c
] = VG_LINE_TO_ABS
; ++c
;
345 coords
[i
] = x
; coords
[i
+ 1] = y
;
348 if (arcType
== VGU_ARC_PIE
|| arcType
== VGU_ARC_CHORD
) {
349 cmds
[c
] = VG_CLOSE_PATH
;
355 vgu_append_float_coords(path
, cmds
, c
, coords
, i
);
360 VGUErrorCode
vguComputeWarpQuadToSquare(VGfloat sx0
, VGfloat sy0
,
361 VGfloat sx1
, VGfloat sy1
,
362 VGfloat sx2
, VGfloat sy2
,
363 VGfloat sx3
, VGfloat sy3
,
368 if (!matrix
|| !is_aligned(matrix
))
369 return VGU_ILLEGAL_ARGUMENT_ERROR
;
371 if (!matrix_quad_to_square(sx0
, sy0
,
376 return VGU_BAD_WARP_ERROR
;
378 if (!matrix_is_invertible(&mat
))
379 return VGU_BAD_WARP_ERROR
;
381 memcpy(matrix
, mat
.m
, sizeof(VGfloat
) * 9);
386 VGUErrorCode
vguComputeWarpSquareToQuad(VGfloat dx0
, VGfloat dy0
,
387 VGfloat dx1
, VGfloat dy1
,
388 VGfloat dx2
, VGfloat dy2
,
389 VGfloat dx3
, VGfloat dy3
,
394 if (!matrix
|| !is_aligned(matrix
))
395 return VGU_ILLEGAL_ARGUMENT_ERROR
;
397 if (!matrix_square_to_quad(dx0
, dy0
,
402 return VGU_BAD_WARP_ERROR
;
404 if (!matrix_is_invertible(&mat
))
405 return VGU_BAD_WARP_ERROR
;
407 memcpy(matrix
, mat
.m
, sizeof(VGfloat
) * 9);
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
,
424 if (!matrix
|| !is_aligned(matrix
))
425 return VGU_ILLEGAL_ARGUMENT_ERROR
;
427 if (!matrix_quad_to_quad(dx0
, dy0
,
436 return VGU_BAD_WARP_ERROR
;
438 memcpy(matrix
, mat
.m
, sizeof(VGfloat
) * 9);