Subversion Repositories Kolibri OS

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4358 Serge 1
/**************************************************************************
2
 *
3
 * Copyright 2009 VMware, Inc.  All Rights Reserved.
4
 *
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:
12
 *
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.
16
 *
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.
24
 *
25
 **************************************************************************/
26
 
27
#include "VG/openvg.h"
28
 
29
#include "vg_context.h"
30
#include "handle.h"
31
#include "path.h"
32
#include "api.h"
33
 
34
#include "pipe/p_context.h"
35
 
36
VGPath vegaCreatePath(VGint pathFormat,
37
                      VGPathDatatype datatype,
38
                      VGfloat scale, VGfloat bias,
39
                      VGint segmentCapacityHint,
40
                      VGint coordCapacityHint,
41
                      VGbitfield capabilities)
42
{
43
   struct vg_context *ctx = vg_current_context();
44
 
45
   if (pathFormat != VG_PATH_FORMAT_STANDARD) {
46
      vg_set_error(ctx, VG_UNSUPPORTED_PATH_FORMAT_ERROR);
47
      return VG_INVALID_HANDLE;
48
   }
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;
53
   }
54
   if (!scale) {
55
      vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
56
      return VG_INVALID_HANDLE;
57
   }
58
 
59
   return path_to_handle(path_create(datatype, scale, bias,
60
                                     segmentCapacityHint, coordCapacityHint,
61
                                     capabilities));
62
}
63
 
64
void vegaClearPath(VGPath path, VGbitfield capabilities)
65
{
66
   struct vg_context *ctx = vg_current_context();
67
   struct path *p = 0;
68
 
69
   if (path == VG_INVALID_HANDLE) {
70
      vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
71
      return;
72
   }
73
 
74
   p = handle_to_path(path);
75
   path_clear(p, capabilities);
76
}
77
 
78
void vegaDestroyPath(VGPath p)
79
{
80
   struct path *path = 0;
81
   struct vg_context *ctx = vg_current_context();
82
 
83
   if (p == VG_INVALID_HANDLE) {
84
      vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
85
      return;
86
   }
87
 
88
   path = handle_to_path(p);
89
   path_destroy(path);
90
}
91
 
92
void vegaRemovePathCapabilities(VGPath path,
93
                                VGbitfield capabilities)
94
{
95
   struct vg_context *ctx = vg_current_context();
96
   VGbitfield current;
97
   struct path *p;
98
 
99
   if (path == VG_INVALID_HANDLE) {
100
      vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
101
      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
 
110
VGbitfield 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
 
123
void 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
 
143
void 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 (!p || !is_aligned_to(p, 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
 
186
void 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
 
221
void 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
 
241
VGboolean 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
 
270
VGfloat 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
 
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)
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
 
363
void 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
 
400
void 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
 
467
void 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