revert between 56095 -> 55830 in arch
[AROS.git] / workbench / libs / mesa / src / gallium / state_trackers / vega / api_path.c
blobab6ce958945d71db883dea2d3308b47dc1a5b27c
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
15 * of the Software.
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"
30 #include "handle.h"
31 #include "path.h"
32 #include "api.h"
34 #include "pipe/p_context.h"
36 VGPath vegaCreatePath(VGint pathFormat,
37 VGPathDatatype datatype,
38 VGfloat scale, VGfloat bias,
39 VGint segmentCapacityHint,
40 VGint coordCapacityHint,
41 VGbitfield capabilities)
43 struct vg_context *ctx = vg_current_context();
45 if (pathFormat != VG_PATH_FORMAT_STANDARD) {
46 vg_set_error(ctx, VG_UNSUPPORTED_PATH_FORMAT_ERROR);
47 return VG_INVALID_HANDLE;
49 if (datatype < VG_PATH_DATATYPE_S_8 ||
50 datatype > VG_PATH_DATATYPE_F) {
51 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
52 return VG_INVALID_HANDLE;
54 if (!scale) {
55 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
56 return VG_INVALID_HANDLE;
59 return path_to_handle(path_create(datatype, scale, bias,
60 segmentCapacityHint, coordCapacityHint,
61 capabilities));
64 void vegaClearPath(VGPath path, VGbitfield capabilities)
66 struct vg_context *ctx = vg_current_context();
67 struct path *p = 0;
69 if (path == VG_INVALID_HANDLE) {
70 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
71 return;
74 p = handle_to_path(path);
75 path_clear(p, capabilities);
78 void vegaDestroyPath(VGPath p)
80 struct path *path = 0;
81 struct vg_context *ctx = vg_current_context();
83 if (p == VG_INVALID_HANDLE) {
84 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
85 return;
88 path = handle_to_path(p);
89 path_destroy(path);
92 void vegaRemovePathCapabilities(VGPath path,
93 VGbitfield capabilities)
95 struct vg_context *ctx = vg_current_context();
96 VGbitfield current;
97 struct path *p;
99 if (path == VG_INVALID_HANDLE) {
100 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
101 return;
104 p = handle_to_path(path);
105 current = path_capabilities(p);
106 path_set_capabilities(p, (current &
107 (~(capabilities & VG_PATH_CAPABILITY_ALL))));
110 VGbitfield vegaGetPathCapabilities(VGPath path)
112 struct vg_context *ctx = vg_current_context();
113 struct path *p = 0;
115 if (path == VG_INVALID_HANDLE) {
116 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
117 return 0;
119 p = handle_to_path(path);
120 return path_capabilities(p);
123 void vegaAppendPath(VGPath dstPath, VGPath srcPath)
125 struct vg_context *ctx = vg_current_context();
126 struct path *src, *dst;
128 if (dstPath == VG_INVALID_HANDLE || srcPath == VG_INVALID_HANDLE) {
129 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
130 return;
132 src = handle_to_path(srcPath);
133 dst = handle_to_path(dstPath);
135 if (!(path_capabilities(src) & VG_PATH_CAPABILITY_APPEND_FROM) ||
136 !(path_capabilities(dst) & VG_PATH_CAPABILITY_APPEND_TO)) {
137 vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
138 return;
140 path_append_path(dst, src);
143 void vegaAppendPathData(VGPath dstPath,
144 VGint numSegments,
145 const VGubyte * pathSegments,
146 const void * pathData)
148 struct vg_context *ctx = vg_current_context();
149 struct path *p = 0;
150 VGint i;
152 if (dstPath == VG_INVALID_HANDLE) {
153 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
154 return;
156 if (!pathSegments) {
157 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
158 return;
160 if (numSegments <= 0) {
161 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
162 return;
164 for (i = 0; i < numSegments; ++i) {
165 if (pathSegments[i] > VG_LCWARC_TO_REL) {
166 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
167 return;
171 p = handle_to_path(dstPath);
173 if (!p || !is_aligned_to(p, path_datatype_size(p))) {
174 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
175 return;
178 if (!(path_capabilities(p)&VG_PATH_CAPABILITY_APPEND_TO)) {
179 vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
180 return;
183 path_append_data(p, numSegments, pathSegments, pathData);
186 void vegaModifyPathCoords(VGPath dstPath,
187 VGint startIndex,
188 VGint numSegments,
189 const void * pathData)
191 struct vg_context *ctx = vg_current_context();
192 struct path *p = 0;
194 if (dstPath == VG_INVALID_HANDLE) {
195 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
196 return;
198 if (startIndex < 0 || numSegments <= 0) {
199 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
200 return;
203 p = handle_to_path(dstPath);
205 if (!pathData || !is_aligned_to(pathData, path_datatype_size(p))) {
206 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
207 return;
210 if (startIndex + numSegments > path_num_segments(p)) {
211 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
212 return;
214 if (!(path_capabilities(p)&VG_PATH_CAPABILITY_MODIFY)) {
215 vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
216 return;
218 path_modify_coords(p, startIndex, numSegments, pathData);
221 void vegaTransformPath(VGPath dstPath, VGPath srcPath)
223 struct vg_context *ctx = vg_current_context();
224 struct path *src = 0, *dst = 0;
226 if (dstPath == VG_INVALID_HANDLE || srcPath == VG_INVALID_HANDLE) {
227 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
228 return;
230 src = handle_to_path(srcPath);
231 dst = handle_to_path(dstPath);
233 if (!(path_capabilities(src) & VG_PATH_CAPABILITY_TRANSFORM_FROM) ||
234 !(path_capabilities(dst) & VG_PATH_CAPABILITY_TRANSFORM_TO)) {
235 vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
236 return;
238 path_transform(dst, src);
241 VGboolean vegaInterpolatePath(VGPath dstPath,
242 VGPath startPath,
243 VGPath endPath,
244 VGfloat amount)
246 struct vg_context *ctx = vg_current_context();
247 struct path *start = 0, *dst = 0, *end = 0;
249 if (dstPath == VG_INVALID_HANDLE ||
250 startPath == VG_INVALID_HANDLE ||
251 endPath == VG_INVALID_HANDLE) {
252 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
253 return VG_FALSE;
255 dst = handle_to_path(dstPath);
256 start = handle_to_path(startPath);
257 end = handle_to_path(endPath);
259 if (!(path_capabilities(dst) & VG_PATH_CAPABILITY_INTERPOLATE_TO) ||
260 !(path_capabilities(start) & VG_PATH_CAPABILITY_INTERPOLATE_FROM) ||
261 !(path_capabilities(end) & VG_PATH_CAPABILITY_INTERPOLATE_FROM)) {
262 vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
263 return VG_FALSE;
266 return path_interpolate(dst,
267 start, end, amount);
270 VGfloat vegaPathLength(VGPath path,
271 VGint startSegment,
272 VGint numSegments)
274 struct vg_context *ctx = vg_current_context();
275 struct path *p = 0;
277 if (path == VG_INVALID_HANDLE) {
278 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
279 return -1;
281 if (startSegment < 0) {
282 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
283 return -1;
285 if (numSegments <= 0) {
286 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
287 return -1;
289 p = handle_to_path(path);
291 if (!(path_capabilities(p) & VG_PATH_CAPABILITY_PATH_LENGTH)) {
292 vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
293 return -1;
295 if (startSegment + numSegments > path_num_segments(p)) {
296 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
297 return -1;
300 return path_length(p, startSegment, numSegments);
303 void vegaPointAlongPath(VGPath path,
304 VGint startSegment,
305 VGint numSegments,
306 VGfloat distance,
307 VGfloat * x, VGfloat * y,
308 VGfloat * tangentX,
309 VGfloat * tangentY)
311 struct vg_context *ctx = vg_current_context();
312 struct path *p = 0;
313 VGbitfield caps;
315 if (path == VG_INVALID_HANDLE) {
316 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
317 return;
319 if (startSegment < 0) {
320 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
321 return;
323 if (numSegments <= 0) {
324 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
325 return;
328 if (!is_aligned(x) || !is_aligned(y) ||
329 !is_aligned(tangentX) || !is_aligned(tangentY)) {
330 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
331 return;
334 p = handle_to_path(path);
336 caps = path_capabilities(p);
337 if (!(caps & VG_PATH_CAPABILITY_POINT_ALONG_PATH) ||
338 !(caps & VG_PATH_CAPABILITY_TANGENT_ALONG_PATH)) {
339 vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
340 return;
343 if (startSegment + numSegments > path_num_segments(p)) {
344 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
345 return;
349 VGfloat point[2], normal[2];
350 path_point(p, startSegment, numSegments, distance,
351 point, normal);
352 if (x)
353 *x = point[0];
354 if (y)
355 *y = point[1];
356 if (tangentX)
357 *tangentX = -normal[1];
358 if (tangentY)
359 *tangentY = normal[0];
363 void vegaPathBounds(VGPath path,
364 VGfloat * minX,
365 VGfloat * minY,
366 VGfloat * width,
367 VGfloat * height)
369 struct vg_context *ctx = vg_current_context();
370 struct path *p = 0;
371 VGbitfield caps;
373 if (path == VG_INVALID_HANDLE) {
374 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
375 return;
378 if (!minX || !minY || !width || !height) {
379 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
380 return;
383 if (!is_aligned(minX) || !is_aligned(minY) ||
384 !is_aligned(width) || !is_aligned(height)) {
385 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
386 return;
389 p = handle_to_path(path);
391 caps = path_capabilities(p);
392 if (!(caps & VG_PATH_CAPABILITY_PATH_BOUNDS)) {
393 vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
394 return;
397 path_bounding_rect(p, minX, minY, width, height);
400 void vegaPathTransformedBounds(VGPath path,
401 VGfloat * minX,
402 VGfloat * minY,
403 VGfloat * width,
404 VGfloat * height)
406 struct vg_context *ctx = vg_current_context();
407 struct path *p = 0;
408 VGbitfield caps;
410 if (path == VG_INVALID_HANDLE) {
411 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
412 return;
415 if (!minX || !minY || !width || !height) {
416 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
417 return;
420 if (!is_aligned(minX) || !is_aligned(minY) ||
421 !is_aligned(width) || !is_aligned(height)) {
422 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
423 return;
426 p = handle_to_path(path);
428 caps = path_capabilities(p);
429 if (!(caps & VG_PATH_CAPABILITY_PATH_TRANSFORMED_BOUNDS)) {
430 vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR);
431 return;
434 #if 0
435 /* faster, but seems to have precision problems... */
436 path_bounding_rect(p, minX, minY, width, height);
437 if (*width > 0 && *height > 0) {
438 VGfloat pts[] = {*minX, *minY,
439 *minX + *width, *minY,
440 *minX + *width, *minY + *height,
441 *minX, *minY + *height};
442 struct matrix *matrix = &ctx->state.vg.path_user_to_surface_matrix;
443 VGfloat maxX, maxY;
444 matrix_map_point(matrix, pts[0], pts[1], pts + 0, pts + 1);
445 matrix_map_point(matrix, pts[2], pts[3], pts + 2, pts + 3);
446 matrix_map_point(matrix, pts[4], pts[5], pts + 4, pts + 5);
447 matrix_map_point(matrix, pts[6], pts[7], pts + 6, pts + 7);
448 *minX = MIN2(pts[0], MIN2(pts[2], MIN2(pts[4], pts[6])));
449 *minY = MIN2(pts[1], MIN2(pts[3], MIN2(pts[5], pts[7])));
450 maxX = MAX2(pts[0], MAX2(pts[2], MAX2(pts[4], pts[6])));
451 maxY = MAX2(pts[1], MAX2(pts[3], MAX2(pts[5], pts[7])));
452 *width = maxX - *minX;
453 *height = maxY - *minY;
455 #else
457 struct path *dst = path_create(VG_PATH_DATATYPE_F, 1.0, 0,
458 0, 0, VG_PATH_CAPABILITY_ALL);
459 path_transform(dst, p);
460 path_bounding_rect(dst, minX, minY, width, height);
461 path_destroy(dst);
463 #endif
467 void vegaDrawPath(VGPath path, VGbitfield paintModes)
469 struct vg_context *ctx = vg_current_context();
470 struct path *p = handle_to_path(path);
472 if (path == VG_INVALID_HANDLE) {
473 vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
474 return;
477 if (!(paintModes & (VG_STROKE_PATH | VG_FILL_PATH))) {
478 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
479 return;
482 if (path_is_empty(p))
483 return;
484 path_render(p, paintModes,
485 &ctx->state.vg.path_user_to_surface_matrix);