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"
29 #include "vg_context.h"
33 #include "pipe/p_context.h"
35 VGPath
vegaCreatePath(VGint pathFormat
,
36 VGPathDatatype datatype
,
37 VGfloat scale
, VGfloat bias
,
38 VGint segmentCapacityHint
,
39 VGint coordCapacityHint
,
40 VGbitfield capabilities
)
42 struct vg_context
*ctx
= vg_current_context();
44 if (pathFormat
!= VG_PATH_FORMAT_STANDARD
) {
45 vg_set_error(ctx
, VG_UNSUPPORTED_PATH_FORMAT_ERROR
);
46 return VG_INVALID_HANDLE
;
48 if (datatype
< VG_PATH_DATATYPE_S_8
||
49 datatype
> VG_PATH_DATATYPE_F
) {
50 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
51 return VG_INVALID_HANDLE
;
54 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
55 return VG_INVALID_HANDLE
;
58 return (VGPath
)path_create(datatype
, scale
, bias
,
59 segmentCapacityHint
, coordCapacityHint
,
63 void vegaClearPath(VGPath path
, VGbitfield capabilities
)
65 struct vg_context
*ctx
= vg_current_context();
68 if (path
== VG_INVALID_HANDLE
) {
69 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
73 p
= (struct path
*)path
;
74 path_clear(p
, capabilities
);
77 void vegaDestroyPath(VGPath p
)
79 struct path
*path
= 0;
80 struct vg_context
*ctx
= vg_current_context();
82 if (p
== VG_INVALID_HANDLE
) {
83 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
87 path
= (struct path
*)p
;
91 void vegaRemovePathCapabilities(VGPath path
,
92 VGbitfield capabilities
)
94 struct vg_context
*ctx
= vg_current_context();
98 if (path
== VG_INVALID_HANDLE
) {
99 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
103 p
= (struct path
*)path
;
104 current
= path_capabilities(p
);
105 path_set_capabilities(p
, (current
&
106 (~(capabilities
& VG_PATH_CAPABILITY_ALL
))));
109 VGbitfield
vegaGetPathCapabilities(VGPath path
)
111 struct vg_context
*ctx
= vg_current_context();
114 if (path
== VG_INVALID_HANDLE
) {
115 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
118 p
= (struct path
*)path
;
119 return path_capabilities(p
);
122 void vegaAppendPath(VGPath dstPath
, VGPath srcPath
)
124 struct vg_context
*ctx
= vg_current_context();
125 struct path
*src
, *dst
;
127 if (dstPath
== VG_INVALID_HANDLE
|| srcPath
== VG_INVALID_HANDLE
) {
128 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
131 src
= (struct path
*)srcPath
;
132 dst
= (struct path
*)dstPath
;
134 if (!(path_capabilities(src
) & VG_PATH_CAPABILITY_APPEND_FROM
) ||
135 !(path_capabilities(dst
) & VG_PATH_CAPABILITY_APPEND_TO
)) {
136 vg_set_error(ctx
, VG_PATH_CAPABILITY_ERROR
);
139 path_append_path(dst
, src
);
142 void vegaAppendPathData(VGPath dstPath
,
144 const VGubyte
* pathSegments
,
145 const void * pathData
)
147 struct vg_context
*ctx
= vg_current_context();
151 if (dstPath
== VG_INVALID_HANDLE
) {
152 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
156 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
159 if (numSegments
<= 0) {
160 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
163 for (i
= 0; i
< numSegments
; ++i
) {
164 if (pathSegments
[i
] > VG_LCWARC_TO_REL
) {
165 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
170 p
= (struct path
*)dstPath
;
172 if (!pathData
|| !is_aligned_to(pathData
, path_datatype_size(p
))) {
173 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
177 if (!(path_capabilities(p
)&VG_PATH_CAPABILITY_APPEND_TO
)) {
178 vg_set_error(ctx
, VG_PATH_CAPABILITY_ERROR
);
182 path_append_data(p
, numSegments
, pathSegments
, pathData
);
185 void vegaModifyPathCoords(VGPath dstPath
,
188 const void * pathData
)
190 struct vg_context
*ctx
= vg_current_context();
193 if (dstPath
== VG_INVALID_HANDLE
) {
194 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
197 if (startIndex
< 0 || numSegments
<= 0) {
198 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
202 p
= (struct path
*)dstPath
;
204 if (!pathData
|| !is_aligned_to(pathData
, path_datatype_size(p
))) {
205 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
209 if (startIndex
+ numSegments
> path_num_segments(p
)) {
210 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
213 if (!(path_capabilities(p
)&VG_PATH_CAPABILITY_MODIFY
)) {
214 vg_set_error(ctx
, VG_PATH_CAPABILITY_ERROR
);
217 path_modify_coords(p
, startIndex
, numSegments
, pathData
);
220 void vegaTransformPath(VGPath dstPath
, VGPath srcPath
)
222 struct vg_context
*ctx
= vg_current_context();
223 struct path
*src
= 0, *dst
= 0;
225 if (dstPath
== VG_INVALID_HANDLE
|| srcPath
== VG_INVALID_HANDLE
) {
226 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
229 src
= (struct path
*)srcPath
;
230 dst
= (struct path
*)dstPath
;
232 if (!(path_capabilities(src
) & VG_PATH_CAPABILITY_TRANSFORM_FROM
) ||
233 !(path_capabilities(dst
) & VG_PATH_CAPABILITY_TRANSFORM_TO
)) {
234 vg_set_error(ctx
, VG_PATH_CAPABILITY_ERROR
);
237 path_transform(dst
, src
);
240 VGboolean
vegaInterpolatePath(VGPath dstPath
,
245 struct vg_context
*ctx
= vg_current_context();
246 struct path
*start
= 0, *dst
= 0, *end
= 0;
248 if (dstPath
== VG_INVALID_HANDLE
||
249 startPath
== VG_INVALID_HANDLE
||
250 endPath
== VG_INVALID_HANDLE
) {
251 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
254 dst
= (struct path
*)dstPath
;
255 start
= (struct path
*)startPath
;
256 end
= (struct path
*)endPath
;
258 if (!(path_capabilities(dst
) & VG_PATH_CAPABILITY_INTERPOLATE_TO
) ||
259 !(path_capabilities(start
) & VG_PATH_CAPABILITY_INTERPOLATE_FROM
) ||
260 !(path_capabilities(end
) & VG_PATH_CAPABILITY_INTERPOLATE_FROM
)) {
261 vg_set_error(ctx
, VG_PATH_CAPABILITY_ERROR
);
265 return path_interpolate(dst
,
269 VGfloat
vegaPathLength(VGPath path
,
273 struct vg_context
*ctx
= vg_current_context();
276 if (path
== VG_INVALID_HANDLE
) {
277 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
280 if (startSegment
< 0) {
281 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
284 if (numSegments
<= 0) {
285 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
288 p
= (struct path
*)path
;
290 if (!(path_capabilities(p
) & VG_PATH_CAPABILITY_PATH_LENGTH
)) {
291 vg_set_error(ctx
, VG_PATH_CAPABILITY_ERROR
);
294 if (startSegment
+ numSegments
> path_num_segments(p
)) {
295 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
299 return path_length(p
, startSegment
, numSegments
);
302 void vegaPointAlongPath(VGPath path
,
306 VGfloat
* x
, VGfloat
* y
,
310 struct vg_context
*ctx
= vg_current_context();
314 if (path
== VG_INVALID_HANDLE
) {
315 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
318 if (startSegment
< 0) {
319 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
322 if (numSegments
<= 0) {
323 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
327 if (!is_aligned(x
) || !is_aligned(y
) ||
328 !is_aligned(tangentX
) || !is_aligned(tangentY
)) {
329 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
333 p
= (struct path
*)path
;
335 caps
= path_capabilities(p
);
336 if (!(caps
& VG_PATH_CAPABILITY_POINT_ALONG_PATH
) ||
337 !(caps
& VG_PATH_CAPABILITY_TANGENT_ALONG_PATH
)) {
338 vg_set_error(ctx
, VG_PATH_CAPABILITY_ERROR
);
342 if (startSegment
+ numSegments
> path_num_segments(p
)) {
343 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
348 VGfloat point
[2], normal
[2];
349 path_point(p
, startSegment
, numSegments
, distance
,
356 *tangentX
= -normal
[1];
358 *tangentY
= normal
[0];
362 void vegaPathBounds(VGPath path
,
368 struct vg_context
*ctx
= vg_current_context();
372 if (path
== VG_INVALID_HANDLE
) {
373 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
377 if (!minX
|| !minY
|| !width
|| !height
) {
378 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
382 if (!is_aligned(minX
) || !is_aligned(minY
) ||
383 !is_aligned(width
) || !is_aligned(height
)) {
384 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
388 p
= (struct path
*)path
;
390 caps
= path_capabilities(p
);
391 if (!(caps
& VG_PATH_CAPABILITY_PATH_BOUNDS
)) {
392 vg_set_error(ctx
, VG_PATH_CAPABILITY_ERROR
);
396 path_bounding_rect(p
, minX
, minY
, width
, height
);
399 void vegaPathTransformedBounds(VGPath path
,
405 struct vg_context
*ctx
= vg_current_context();
409 if (path
== VG_INVALID_HANDLE
) {
410 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
414 if (!minX
|| !minY
|| !width
|| !height
) {
415 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
419 if (!is_aligned(minX
) || !is_aligned(minY
) ||
420 !is_aligned(width
) || !is_aligned(height
)) {
421 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
425 p
= (struct path
*)path
;
427 caps
= path_capabilities(p
);
428 if (!(caps
& VG_PATH_CAPABILITY_PATH_TRANSFORMED_BOUNDS
)) {
429 vg_set_error(ctx
, VG_PATH_CAPABILITY_ERROR
);
434 /* faster, but seems to have precision problems... */
435 path_bounding_rect(p
, minX
, minY
, width
, height
);
436 if (*width
> 0 && *height
> 0) {
437 VGfloat pts
[] = {*minX
, *minY
,
438 *minX
+ *width
, *minY
,
439 *minX
+ *width
, *minY
+ *height
,
440 *minX
, *minY
+ *height
};
441 struct matrix
*matrix
= &ctx
->state
.vg
.path_user_to_surface_matrix
;
443 matrix_map_point(matrix
, pts
[0], pts
[1], pts
+ 0, pts
+ 1);
444 matrix_map_point(matrix
, pts
[2], pts
[3], pts
+ 2, pts
+ 3);
445 matrix_map_point(matrix
, pts
[4], pts
[5], pts
+ 4, pts
+ 5);
446 matrix_map_point(matrix
, pts
[6], pts
[7], pts
+ 6, pts
+ 7);
447 *minX
= MIN2(pts
[0], MIN2(pts
[2], MIN2(pts
[4], pts
[6])));
448 *minY
= MIN2(pts
[1], MIN2(pts
[3], MIN2(pts
[5], pts
[7])));
449 maxX
= MAX2(pts
[0], MAX2(pts
[2], MAX2(pts
[4], pts
[6])));
450 maxY
= MAX2(pts
[1], MAX2(pts
[3], MAX2(pts
[5], pts
[7])));
451 *width
= maxX
- *minX
;
452 *height
= maxY
- *minY
;
456 struct path
*dst
= path_create(VG_PATH_DATATYPE_F
, 1.0, 0,
457 0, 0, VG_PATH_CAPABILITY_ALL
);
458 path_transform(dst
, p
);
459 path_bounding_rect(dst
, minX
, minY
, width
, height
);
466 void vegaDrawPath(VGPath path
, VGbitfield paintModes
)
468 struct vg_context
*ctx
= vg_current_context();
470 if (path
== VG_INVALID_HANDLE
) {
471 vg_set_error(ctx
, VG_BAD_HANDLE_ERROR
);
475 if (!(paintModes
& (VG_STROKE_PATH
| VG_FILL_PATH
))) {
476 vg_set_error(ctx
, VG_ILLEGAL_ARGUMENT_ERROR
);
480 if (path_is_empty((struct path
*)path
))
482 path_render((struct path
*)path
, paintModes
);