api_path.c revision d41e694cf78ada8c9258f96995115c9da8437894
190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)/************************************************************************** 290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * 390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Copyright 2009 VMware, Inc. All Rights Reserved. 490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * 590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a 690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * copy of this software and associated documentation files (the 790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * "Software"), to deal in the Software without restriction, including 8f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) * without limitation the rights to use, copy, modify, merge, publish, 990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * distribute, sub license, and/or sell copies of the Software, and to 1090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * permit persons to whom the Software is furnished to do so, subject to 1190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * the following conditions: 125d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) * 1390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * The above copyright notice and this permission notice (including the 1490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * next paragraph) shall be included in all copies or substantial portions 1590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * of the Software. 1690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * 1790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 1846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) * 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) **************************************************************************/ 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "VG/openvg.h" 2890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "vg_context.h" 3090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "handle.h" 3190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "path.h" 3290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "api.h" 3390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "pipe/p_context.h" 3590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 3690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)VGPath vegaCreatePath(VGint pathFormat, 3790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) VGPathDatatype datatype, 3890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) VGfloat scale, VGfloat bias, 3990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) VGint segmentCapacityHint, 4090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) VGint coordCapacityHint, 4190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) VGbitfield capabilities) 4290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){ 4390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) struct vg_context *ctx = vg_current_context(); 4490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 4590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (pathFormat != VG_PATH_FORMAT_STANDARD) { 46868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) vg_set_error(ctx, VG_UNSUPPORTED_PATH_FORMAT_ERROR); 47868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return VG_INVALID_HANDLE; 4890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 4990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (datatype < VG_PATH_DATATYPE_S_8 || 5090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) datatype > VG_PATH_DATATYPE_F) { 5190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 5290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return VG_INVALID_HANDLE; 53868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 5490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (!scale) { 5590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 5690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return VG_INVALID_HANDLE; 5790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 5890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 5990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return path_to_handle(path_create(datatype, scale, bias, 6090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) segmentCapacityHint, coordCapacityHint, 6190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) capabilities)); 6290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 6390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 64f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)void vegaClearPath(VGPath path, VGbitfield capabilities) 65f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles){ 66868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) struct vg_context *ctx = vg_current_context(); 6790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) struct path *p = 0; 6890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 6990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (path == VG_INVALID_HANDLE) { 7090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 7190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 7290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 7390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) p = handle_to_path(path); 7590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) path_clear(p, capabilities); 7690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 7790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 7890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void vegaDestroyPath(VGPath p) 7990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){ 8090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) struct path *path = 0; 8190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) struct vg_context *ctx = vg_current_context(); 8290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) if (p == VG_INVALID_HANDLE) { 8490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 8590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 8690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) } 8790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 8846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) path = handle_to_path(p); 8990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) path_destroy(path); 9090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)} 9190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)void vegaRemovePathCapabilities(VGPath path, 9390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) VGbitfield capabilities) 9490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles){ 9590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) struct vg_context *ctx = vg_current_context(); 9690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) VGbitfield current; 9790dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) struct path *p; 9890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 9946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (path == VG_INVALID_HANDLE) { 10090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 10190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) return; 102 } 103 104 p = handle_to_path(path); 105 current = path_capabilities(p); 106 path_set_capabilities(p, (current & 107 (~(capabilities & VG_PATH_CAPABILITY_ALL)))); 108} 109 110VGbitfield vegaGetPathCapabilities(VGPath path) 111{ 112 struct vg_context *ctx = vg_current_context(); 113 struct path *p = 0; 114 115 if (path == VG_INVALID_HANDLE) { 116 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 117 return 0; 118 } 119 p = handle_to_path(path); 120 return path_capabilities(p); 121} 122 123void vegaAppendPath(VGPath dstPath, VGPath srcPath) 124{ 125 struct vg_context *ctx = vg_current_context(); 126 struct path *src, *dst; 127 128 if (dstPath == VG_INVALID_HANDLE || srcPath == VG_INVALID_HANDLE) { 129 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 130 return; 131 } 132 src = handle_to_path(srcPath); 133 dst = handle_to_path(dstPath); 134 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; 139 } 140 path_append_path(dst, src); 141} 142 143void vegaAppendPathData(VGPath dstPath, 144 VGint numSegments, 145 const VGubyte * pathSegments, 146 const void * pathData) 147{ 148 struct vg_context *ctx = vg_current_context(); 149 struct path *p = 0; 150 VGint i; 151 152 if (dstPath == VG_INVALID_HANDLE) { 153 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 154 return; 155 } 156 if (!pathSegments) { 157 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 158 return; 159 } 160 if (numSegments <= 0) { 161 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 162 return; 163 } 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; 168 } 169 } 170 171 p = handle_to_path(dstPath); 172 173 if (!pathData || !is_aligned_to(pathData, path_datatype_size(p))) { 174 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 175 return; 176 } 177 178 if (!(path_capabilities(p)&VG_PATH_CAPABILITY_APPEND_TO)) { 179 vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); 180 return; 181 } 182 183 path_append_data(p, numSegments, pathSegments, pathData); 184} 185 186void vegaModifyPathCoords(VGPath dstPath, 187 VGint startIndex, 188 VGint numSegments, 189 const void * pathData) 190{ 191 struct vg_context *ctx = vg_current_context(); 192 struct path *p = 0; 193 194 if (dstPath == VG_INVALID_HANDLE) { 195 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 196 return; 197 } 198 if (startIndex < 0 || numSegments <= 0) { 199 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 200 return; 201 } 202 203 p = handle_to_path(dstPath); 204 205 if (!pathData || !is_aligned_to(pathData, path_datatype_size(p))) { 206 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 207 return; 208 } 209 210 if (startIndex + numSegments > path_num_segments(p)) { 211 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 212 return; 213 } 214 if (!(path_capabilities(p)&VG_PATH_CAPABILITY_MODIFY)) { 215 vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); 216 return; 217 } 218 path_modify_coords(p, startIndex, numSegments, pathData); 219} 220 221void vegaTransformPath(VGPath dstPath, VGPath srcPath) 222{ 223 struct vg_context *ctx = vg_current_context(); 224 struct path *src = 0, *dst = 0; 225 226 if (dstPath == VG_INVALID_HANDLE || srcPath == VG_INVALID_HANDLE) { 227 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 228 return; 229 } 230 src = handle_to_path(srcPath); 231 dst = handle_to_path(dstPath); 232 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; 237 } 238 path_transform(dst, src); 239} 240 241VGboolean vegaInterpolatePath(VGPath dstPath, 242 VGPath startPath, 243 VGPath endPath, 244 VGfloat amount) 245{ 246 struct vg_context *ctx = vg_current_context(); 247 struct path *start = 0, *dst = 0, *end = 0; 248 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; 254 } 255 dst = handle_to_path(dstPath); 256 start = handle_to_path(startPath); 257 end = handle_to_path(endPath); 258 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; 264 } 265 266 return path_interpolate(dst, 267 start, end, amount); 268} 269 270VGfloat vegaPathLength(VGPath path, 271 VGint startSegment, 272 VGint numSegments) 273{ 274 struct vg_context *ctx = vg_current_context(); 275 struct path *p = 0; 276 277 if (path == VG_INVALID_HANDLE) { 278 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 279 return -1; 280 } 281 if (startSegment < 0) { 282 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 283 return -1; 284 } 285 if (numSegments <= 0) { 286 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 287 return -1; 288 } 289 p = handle_to_path(path); 290 291 if (!(path_capabilities(p) & VG_PATH_CAPABILITY_PATH_LENGTH)) { 292 vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); 293 return -1; 294 } 295 if (startSegment + numSegments > path_num_segments(p)) { 296 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 297 return -1; 298 } 299 300 return path_length(p, startSegment, numSegments); 301} 302 303void vegaPointAlongPath(VGPath path, 304 VGint startSegment, 305 VGint numSegments, 306 VGfloat distance, 307 VGfloat * x, VGfloat * y, 308 VGfloat * tangentX, 309 VGfloat * tangentY) 310{ 311 struct vg_context *ctx = vg_current_context(); 312 struct path *p = 0; 313 VGbitfield caps; 314 315 if (path == VG_INVALID_HANDLE) { 316 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 317 return; 318 } 319 if (startSegment < 0) { 320 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 321 return; 322 } 323 if (numSegments <= 0) { 324 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 325 return; 326 } 327 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; 332 } 333 334 p = handle_to_path(path); 335 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; 341 } 342 343 if (startSegment + numSegments > path_num_segments(p)) { 344 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 345 return; 346 } 347 348 { 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]; 360 } 361} 362 363void vegaPathBounds(VGPath path, 364 VGfloat * minX, 365 VGfloat * minY, 366 VGfloat * width, 367 VGfloat * height) 368{ 369 struct vg_context *ctx = vg_current_context(); 370 struct path *p = 0; 371 VGbitfield caps; 372 373 if (path == VG_INVALID_HANDLE) { 374 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 375 return; 376 } 377 378 if (!minX || !minY || !width || !height) { 379 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 380 return; 381 } 382 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; 387 } 388 389 p = handle_to_path(path); 390 391 caps = path_capabilities(p); 392 if (!(caps & VG_PATH_CAPABILITY_PATH_BOUNDS)) { 393 vg_set_error(ctx, VG_PATH_CAPABILITY_ERROR); 394 return; 395 } 396 397 path_bounding_rect(p, minX, minY, width, height); 398} 399 400void vegaPathTransformedBounds(VGPath path, 401 VGfloat * minX, 402 VGfloat * minY, 403 VGfloat * width, 404 VGfloat * height) 405{ 406 struct vg_context *ctx = vg_current_context(); 407 struct path *p = 0; 408 VGbitfield caps; 409 410 if (path == VG_INVALID_HANDLE) { 411 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 412 return; 413 } 414 415 if (!minX || !minY || !width || !height) { 416 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 417 return; 418 } 419 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; 424 } 425 426 p = handle_to_path(path); 427 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; 432 } 433 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; 454 } 455#else 456 { 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); 462 } 463#endif 464} 465 466 467void vegaDrawPath(VGPath path, VGbitfield paintModes) 468{ 469 struct vg_context *ctx = vg_current_context(); 470 struct path *p = handle_to_path(path); 471 472 if (path == VG_INVALID_HANDLE) { 473 vg_set_error(ctx, VG_BAD_HANDLE_ERROR); 474 return; 475 } 476 477 if (!(paintModes & (VG_STROKE_PATH | VG_FILL_PATH))) { 478 vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR); 479 return; 480 } 481 482 if (path_is_empty(p)) 483 return; 484 path_render(p, paintModes, 485 &ctx->state.vg.path_user_to_surface_matrix); 486} 487 488