|
1 /*------------------------------------------------------------------------ |
|
2 * |
|
3 * OpenVG 1.1 Reference Implementation |
|
4 * ----------------------------------- |
|
5 * |
|
6 * Copyright (c) 2007 The Khronos Group Inc. |
|
7 * Portions copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
8 * |
|
9 * Permission is hereby granted, free of charge, to any person obtaining a |
|
10 * copy of this software and /or associated documentation files |
|
11 * (the "Materials "), to deal in the Materials without restriction, |
|
12 * including without limitation the rights to use, copy, modify, merge, |
|
13 * publish, distribute, sublicense, and/or sell copies of the Materials, |
|
14 * and to permit persons to whom the Materials are furnished to do so, |
|
15 * subject to the following conditions: |
|
16 * |
|
17 * The above copyright notice and this permission notice shall be included |
|
18 * in all copies or substantial portions of the Materials. |
|
19 * |
|
20 * THE MATERIALS ARE PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, |
|
21 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF |
|
22 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. |
|
23 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
|
24 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR |
|
25 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE MATERIALS OR |
|
26 * THE USE OR OTHER DEALINGS IN THE MATERIALS. |
|
27 * |
|
28 *//** |
|
29 * \file |
|
30 * \brief Implementations of OpenVG API functions. |
|
31 * \note The actual processing is done in Path, Image, Rasterizer and PixelPipe classes. |
|
32 *//*-------------------------------------------------------------------*/ |
|
33 |
|
34 #include "openvg.h" |
|
35 #include "vgext.h" |
|
36 #include "riContext.h" |
|
37 #include "riRasterizer.h" |
|
38 #include "riPixelPipe.h" |
|
39 #include "riPath.h" |
|
40 #include <stdio.h> |
|
41 |
|
42 //============================================================================================== |
|
43 |
|
44 namespace OpenVGRI |
|
45 { |
|
46 |
|
47 /* EGL&OS functions for use in an OpenVG implementation */ |
|
48 // \note To ensure that different EGLs work in parallel, these functions must be implemented. |
|
49 // They may be wrappers if the underlying EGL is more complicated that miniEGL. |
|
50 void* eglvgGetCurrentVGContext(void); |
|
51 bool eglvgIsInUse(void* image); |
|
52 bool eglvgLockSurface(bool read, bool write); |
|
53 bool eglvgUnlockSurface(); |
|
54 void OSAcquireMutex(void); |
|
55 void OSReleaseMutex(void); |
|
56 void eglvgGetImageDescriptor( void* image, Color::Descriptor &desc, int &width, int &height, int &stride ); |
|
57 void* eglvgGetImageData( void* image ); |
|
58 |
|
59 #define RI_NO_RETVAL |
|
60 |
|
61 //this must be the first line in an API function |
|
62 #define RI_GET_CONTEXT(RETVAL) \ |
|
63 OSAcquireMutex(); \ |
|
64 VGContext* context = (VGContext*)eglvgGetCurrentVGContext(); \ |
|
65 if(!context) \ |
|
66 { \ |
|
67 OSReleaseMutex(); \ |
|
68 return RETVAL;\ |
|
69 } |
|
70 |
|
71 #define RI_IF_ERROR(COND, ERRORCODE, RETVAL) \ |
|
72 if(COND) { context->setError(ERRORCODE); OSReleaseMutex(); return RETVAL; } |
|
73 |
|
74 //all API functions must call this as their last operation (also functions that don't return values) |
|
75 //NOTE: don't evaluate anything or read state in RETVAL (it'll be executed after the mutex has been released) |
|
76 #define RI_RETURN(RETVAL) \ |
|
77 { OSReleaseMutex(); \ |
|
78 return RETVAL; } |
|
79 |
|
80 static bool isAligned(const void* ptr, int alignment) |
|
81 { |
|
82 RI_ASSERT(alignment == 1 || alignment == 2 || alignment == 4); |
|
83 if(((RIuintptr)ptr) & (alignment-1)) |
|
84 return false; |
|
85 return true; |
|
86 } |
|
87 |
|
88 static bool isAligned(const void* ptr, VGImageFormat format) |
|
89 { |
|
90 RI_ASSERT(isValidImageFormat(format)); |
|
91 int alignment = Color::formatToDescriptor(format).bitsPerPixel >> 3; |
|
92 if(alignment <= 1) |
|
93 return true; //one bit or byte per pixel |
|
94 return isAligned(ptr, alignment); |
|
95 } |
|
96 |
|
97 bool isValidImageFormat(int f) |
|
98 { |
|
99 if(f < VG_sRGBX_8888 || f > VG_lABGR_8888_PRE) |
|
100 return false; |
|
101 return true; |
|
102 } |
|
103 |
|
104 } //namespace OpenVGRI |
|
105 |
|
106 using namespace OpenVGRI; |
|
107 |
|
108 /*-------------------------------------------------------------------*//*! |
|
109 * \brief |
|
110 * \param |
|
111 * \return |
|
112 * \note |
|
113 *//*-------------------------------------------------------------------*/ |
|
114 |
|
115 void RI_APIENTRY vgFlush(void) |
|
116 { |
|
117 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
118 //the RI doesn't cache anything, so this is a no-op |
|
119 RI_RETURN(RI_NO_RETVAL); |
|
120 } |
|
121 |
|
122 /*-------------------------------------------------------------------*//*! |
|
123 * \brief |
|
124 * \param |
|
125 * \return |
|
126 * \note |
|
127 *//*-------------------------------------------------------------------*/ |
|
128 |
|
129 void RI_APIENTRY vgFinish(void) |
|
130 { |
|
131 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
132 //the RI doesn't cache anything, so this is a no-op |
|
133 RI_RETURN(RI_NO_RETVAL); |
|
134 } |
|
135 |
|
136 /*-------------------------------------------------------------------*//*! |
|
137 * \brief |
|
138 * \param |
|
139 * \return |
|
140 * \note |
|
141 *//*-------------------------------------------------------------------*/ |
|
142 |
|
143 VGErrorCode RI_APIENTRY vgGetError(void) |
|
144 { |
|
145 RI_GET_CONTEXT(VG_NO_CONTEXT_ERROR); |
|
146 VGErrorCode error = context->m_error; |
|
147 context->m_error = VG_NO_ERROR; |
|
148 RI_RETURN(error); |
|
149 } |
|
150 |
|
151 VGErrorCode RI_APIENTRY vgPlatsimGetError(void) |
|
152 { |
|
153 RI_GET_CONTEXT(VG_NO_CONTEXT_ERROR); |
|
154 VGErrorCode error = context->m_error; |
|
155 RI_RETURN(error); |
|
156 } |
|
157 |
|
158 |
|
159 /*-------------------------------------------------------------------*//*! |
|
160 * \brief |
|
161 * \param |
|
162 * \return |
|
163 * \note |
|
164 *//*-------------------------------------------------------------------*/ |
|
165 |
|
166 namespace OpenVGRI |
|
167 { |
|
168 |
|
169 RIfloat inputFloat(VGfloat f) |
|
170 { |
|
171 //this function is used for all floating point input values |
|
172 if(RI_ISNAN(f)) return 0.0f; //convert NaN to zero |
|
173 return RI_CLAMP(f, -RI_FLOAT_MAX, RI_FLOAT_MAX); //clamp +-inf to +-RIfloat max |
|
174 } |
|
175 |
|
176 Vector2 inputVector2(const Vector2& v) |
|
177 { |
|
178 return Vector2(inputFloat(v.x), inputFloat(v.y)); |
|
179 } |
|
180 |
|
181 Color inputColor(const Color& c) |
|
182 { |
|
183 Color r = c; |
|
184 r.r = inputFloat(r.r); |
|
185 r.g = inputFloat(r.g); |
|
186 r.b = inputFloat(r.b); |
|
187 r.a = inputFloat(r.a); |
|
188 return r; |
|
189 } |
|
190 |
|
191 static int inputFloatToInt(VGfloat value) |
|
192 { |
|
193 double v = (double)floor(value); |
|
194 v = v > (double)RI_INT32_MAX ? (double)RI_INT32_MAX : v; |
|
195 v = v < (double)RI_INT32_MIN ? (double)RI_INT32_MIN : v; |
|
196 return (int)v; |
|
197 } |
|
198 |
|
199 static int paramToInt(const void* values, bool floats, int count, int i) |
|
200 { |
|
201 RI_ASSERT(i >= 0); |
|
202 if(i >= count || !values) |
|
203 return 0; |
|
204 if(floats) |
|
205 return inputFloatToInt(((const VGfloat*)values)[i]); |
|
206 return (int)((const VGint*)values)[i]; |
|
207 } |
|
208 |
|
209 static RIfloat paramToFloat(const void* values, bool floats, int count, int i) |
|
210 { |
|
211 RI_ASSERT(i >= 0); |
|
212 if(i >= count || !values) |
|
213 return 0.0f; |
|
214 if(floats) |
|
215 return ((const VGfloat*)values)[i]; |
|
216 return (RIfloat)((const VGint*)values)[i]; |
|
217 } |
|
218 |
|
219 static void floatToParam(void* output, bool outputFloats, int count, int i, VGfloat value) |
|
220 { |
|
221 RI_ASSERT(i >= 0); |
|
222 RI_ASSERT(output); |
|
223 if(i >= count) |
|
224 return; |
|
225 if(outputFloats) |
|
226 ((VGfloat*)output)[i] = value; |
|
227 else |
|
228 ((VGint*)output)[i] = (VGint)inputFloatToInt(value); |
|
229 } |
|
230 |
|
231 static void intToParam(void* output, bool outputFloats, int count, int i, VGint value) |
|
232 { |
|
233 RI_ASSERT(i >= 0); |
|
234 RI_ASSERT(output); |
|
235 if(i >= count) |
|
236 return; |
|
237 if(outputFloats) |
|
238 ((VGfloat*)output)[i] = (VGfloat)value; |
|
239 else |
|
240 ((VGint*)output)[i] = value; |
|
241 } |
|
242 |
|
243 } //namespace OpenVGRI |
|
244 |
|
245 /*-------------------------------------------------------------------*//*! |
|
246 * \brief |
|
247 * \param |
|
248 * \return |
|
249 * \note |
|
250 *//*-------------------------------------------------------------------*/ |
|
251 |
|
252 static void setifv(VGContext* context, VGParamType type, VGint count, const void* values, bool floats) |
|
253 { |
|
254 RI_ASSERT(context); |
|
255 RI_ASSERT(!count || (count && values)); |
|
256 |
|
257 int ivalue = paramToInt(values, floats, count, 0); |
|
258 RIfloat fvalue = paramToFloat(values, floats, count, 0); |
|
259 |
|
260 switch(type) |
|
261 { |
|
262 case VG_MATRIX_MODE: |
|
263 if(count != 1 || ivalue < VG_MATRIX_PATH_USER_TO_SURFACE || ivalue > VG_MATRIX_GLYPH_USER_TO_SURFACE) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
264 context->m_matrixMode = (VGMatrixMode)ivalue; |
|
265 break; |
|
266 |
|
267 case VG_FILL_RULE: |
|
268 if(count != 1 || ivalue < VG_EVEN_ODD || ivalue > VG_NON_ZERO) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
269 context->m_fillRule = (VGFillRule)ivalue; |
|
270 break; |
|
271 |
|
272 case VG_IMAGE_QUALITY: |
|
273 if(count != 1 || !(ivalue == VG_IMAGE_QUALITY_NONANTIALIASED || ivalue == VG_IMAGE_QUALITY_FASTER || ivalue == VG_IMAGE_QUALITY_BETTER)) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
274 context->m_imageQuality = (VGImageQuality)ivalue; |
|
275 break; |
|
276 |
|
277 case VG_RENDERING_QUALITY: |
|
278 if(count != 1 || !(ivalue == VG_RENDERING_QUALITY_NONANTIALIASED || ivalue == VG_RENDERING_QUALITY_FASTER || ivalue == VG_RENDERING_QUALITY_BETTER)) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
279 context->m_renderingQuality = (VGRenderingQuality)ivalue; |
|
280 break; |
|
281 |
|
282 case VG_BLEND_MODE: |
|
283 if(count != 1 || ivalue < VG_BLEND_SRC || ivalue > VG_BLEND_ADDITIVE) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
284 context->m_blendMode = (VGBlendMode)ivalue; |
|
285 break; |
|
286 |
|
287 case VG_IMAGE_MODE: |
|
288 if(count != 1 || ivalue < VG_DRAW_IMAGE_NORMAL || ivalue > VG_DRAW_IMAGE_STENCIL) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
289 context->m_imageMode = (VGImageMode)ivalue; |
|
290 break; |
|
291 |
|
292 case VG_SCISSOR_RECTS: |
|
293 { |
|
294 if(count & 3) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } //count must be a multiple of four |
|
295 try |
|
296 { |
|
297 Array<OpenVGRI::Rectangle> scissor; |
|
298 for(int i=0;i<RI_INT_MIN(count, RI_MAX_SCISSOR_RECTANGLES*4);i+=4) |
|
299 { |
|
300 OpenVGRI::Rectangle s; |
|
301 s.x = paramToInt(values, floats, count, i+0); |
|
302 s.y = paramToInt(values, floats, count, i+1); |
|
303 s.width = paramToInt(values, floats, count, i+2); |
|
304 s.height = paramToInt(values, floats, count, i+3); |
|
305 scissor.push_back(s); //throws bad_alloc |
|
306 } |
|
307 context->m_scissor.swap(scissor); //replace context data |
|
308 } |
|
309 catch(std::bad_alloc) |
|
310 { |
|
311 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
312 } |
|
313 break; |
|
314 } |
|
315 |
|
316 case VG_COLOR_TRANSFORM: |
|
317 if(count != 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
318 context->m_colorTransform = ivalue ? VG_TRUE : VG_FALSE; |
|
319 break; |
|
320 |
|
321 case VG_COLOR_TRANSFORM_VALUES: |
|
322 if(count != 8 || !values) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
323 { |
|
324 for(int i=0;i<8;i++) |
|
325 { |
|
326 context->m_inputColorTransformValues[i] = paramToFloat(values, floats, count, i); |
|
327 context->m_colorTransformValues[i] = inputFloat(context->m_inputColorTransformValues[i]); |
|
328 } |
|
329 } |
|
330 break; |
|
331 |
|
332 case VG_STROKE_LINE_WIDTH: |
|
333 if(count != 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
334 context->m_inputStrokeLineWidth = fvalue; |
|
335 context->m_strokeLineWidth = inputFloat(fvalue); |
|
336 break; |
|
337 |
|
338 case VG_STROKE_CAP_STYLE: |
|
339 if(count != 1 || ivalue < VG_CAP_BUTT || ivalue > VG_CAP_SQUARE) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
340 context->m_strokeCapStyle = (VGCapStyle)ivalue; |
|
341 break; |
|
342 |
|
343 case VG_STROKE_JOIN_STYLE: |
|
344 if(count != 1 || ivalue < VG_JOIN_MITER || ivalue > VG_JOIN_BEVEL) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
345 context->m_strokeJoinStyle = (VGJoinStyle)ivalue; |
|
346 break; |
|
347 |
|
348 case VG_STROKE_MITER_LIMIT: |
|
349 if(count != 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
350 context->m_inputStrokeMiterLimit = fvalue; |
|
351 context->m_strokeMiterLimit = inputFloat(fvalue); |
|
352 break; |
|
353 |
|
354 case VG_STROKE_DASH_PATTERN: |
|
355 { |
|
356 try |
|
357 { |
|
358 Array<RIfloat> inputStrokeDashPattern; |
|
359 Array<RIfloat> strokeDashPattern; |
|
360 for(int i=0;i<RI_INT_MIN(count, RI_MAX_DASH_COUNT);i++) |
|
361 { |
|
362 RIfloat v = paramToFloat(values, floats, count, i); |
|
363 inputStrokeDashPattern.push_back(v); //throws bad_alloc |
|
364 strokeDashPattern.push_back(inputFloat(v)); //throws bad_alloc |
|
365 } |
|
366 context->m_inputStrokeDashPattern.swap(inputStrokeDashPattern); //replace context data |
|
367 context->m_strokeDashPattern.swap(strokeDashPattern); //replace context data |
|
368 } |
|
369 catch(std::bad_alloc) |
|
370 { |
|
371 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
372 } |
|
373 break; |
|
374 } |
|
375 |
|
376 case VG_STROKE_DASH_PHASE: |
|
377 if(count != 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
378 context->m_inputStrokeDashPhase = fvalue; |
|
379 context->m_strokeDashPhase = inputFloat(fvalue); |
|
380 break; |
|
381 |
|
382 case VG_STROKE_DASH_PHASE_RESET: |
|
383 if(count != 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
384 context->m_strokeDashPhaseReset = ivalue ? VG_TRUE : VG_FALSE; |
|
385 break; |
|
386 |
|
387 case VG_TILE_FILL_COLOR: |
|
388 if(count != 4 || !values) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
389 context->m_inputTileFillColor.set(paramToFloat(values, floats, count, 0), |
|
390 paramToFloat(values, floats, count, 1), |
|
391 paramToFloat(values, floats, count, 2), |
|
392 paramToFloat(values, floats, count, 3), |
|
393 Color::sRGBA); |
|
394 context->m_tileFillColor = inputColor(context->m_inputTileFillColor); |
|
395 break; |
|
396 |
|
397 case VG_GLYPH_ORIGIN: |
|
398 if(count != 2 || !values) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
399 context->m_inputGlyphOrigin.x = paramToFloat(values, floats, count, 0); |
|
400 context->m_inputGlyphOrigin.y = paramToFloat(values, floats, count, 1); |
|
401 context->m_glyphOrigin = inputVector2(context->m_inputGlyphOrigin); |
|
402 break; |
|
403 |
|
404 case VG_CLEAR_COLOR: |
|
405 if(count != 4 || !values) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
406 context->m_inputClearColor.set(paramToFloat(values, floats, count, 0), |
|
407 paramToFloat(values, floats, count, 1), |
|
408 paramToFloat(values, floats, count, 2), |
|
409 paramToFloat(values, floats, count, 3), |
|
410 Color::sRGBA); |
|
411 context->m_clearColor = inputColor(context->m_inputClearColor); |
|
412 break; |
|
413 |
|
414 case VG_MASKING: |
|
415 if(count != 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
416 context->m_masking = ivalue ? VG_TRUE : VG_FALSE; |
|
417 break; |
|
418 |
|
419 case VG_SCISSORING: |
|
420 if(count != 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
421 context->m_scissoring = ivalue ? VG_TRUE : VG_FALSE; |
|
422 break; |
|
423 |
|
424 case VG_PIXEL_LAYOUT: |
|
425 if(count != 1 || ivalue < VG_PIXEL_LAYOUT_UNKNOWN || ivalue > VG_PIXEL_LAYOUT_BGR_HORIZONTAL) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
426 context->m_pixelLayout = (VGPixelLayout)ivalue; |
|
427 break; |
|
428 |
|
429 case VG_SCREEN_LAYOUT: |
|
430 if(count != 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
431 break; //setting read-only values has no effect |
|
432 |
|
433 case VG_FILTER_FORMAT_LINEAR: |
|
434 if(count != 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
435 context->m_filterFormatLinear = ivalue ? VG_TRUE : VG_FALSE; |
|
436 break; |
|
437 |
|
438 case VG_FILTER_FORMAT_PREMULTIPLIED: |
|
439 if(count != 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
440 context->m_filterFormatPremultiplied = ivalue ? VG_TRUE : VG_FALSE; |
|
441 break; |
|
442 |
|
443 case VG_FILTER_CHANNEL_MASK: |
|
444 if(count != 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
445 //undefined bits are ignored |
|
446 context->m_filterChannelMask = (VGbitfield)ivalue; |
|
447 break; |
|
448 |
|
449 case VG_MAX_SCISSOR_RECTS: |
|
450 case VG_MAX_DASH_COUNT: |
|
451 case VG_MAX_KERNEL_SIZE: |
|
452 case VG_MAX_SEPARABLE_KERNEL_SIZE: |
|
453 case VG_MAX_COLOR_RAMP_STOPS: |
|
454 case VG_MAX_IMAGE_WIDTH: |
|
455 case VG_MAX_IMAGE_HEIGHT: |
|
456 case VG_MAX_IMAGE_PIXELS: |
|
457 case VG_MAX_IMAGE_BYTES: |
|
458 case VG_MAX_FLOAT: |
|
459 case VG_MAX_GAUSSIAN_STD_DEVIATION: |
|
460 if(count != 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
461 break; //setting read-only values has no effect |
|
462 |
|
463 default: |
|
464 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
465 break; |
|
466 } |
|
467 } |
|
468 |
|
469 /*-------------------------------------------------------------------*//*! |
|
470 * \brief |
|
471 * \param |
|
472 * \return |
|
473 * \note |
|
474 *//*-------------------------------------------------------------------*/ |
|
475 |
|
476 void RI_APIENTRY vgSetf(VGParamType type, VGfloat value) |
|
477 { |
|
478 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
479 RI_IF_ERROR(type == VG_SCISSOR_RECTS || type == VG_STROKE_DASH_PATTERN || type == VG_TILE_FILL_COLOR || |
|
480 type == VG_CLEAR_COLOR, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //vector type value |
|
481 VGfloat values[1] = {value}; |
|
482 setifv(context, type, 1, values, true); |
|
483 RI_RETURN(RI_NO_RETVAL); |
|
484 } |
|
485 |
|
486 /*-------------------------------------------------------------------*//*! |
|
487 * \brief |
|
488 * \param |
|
489 * \return |
|
490 * \note |
|
491 *//*-------------------------------------------------------------------*/ |
|
492 |
|
493 void RI_APIENTRY vgSeti(VGParamType type, VGint value) |
|
494 { |
|
495 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
496 RI_IF_ERROR(type == VG_SCISSOR_RECTS || type == VG_STROKE_DASH_PATTERN || type == VG_TILE_FILL_COLOR || |
|
497 type == VG_CLEAR_COLOR, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //vector type value |
|
498 VGint values[1] = {value}; |
|
499 setifv(context, type, 1, values, false); |
|
500 RI_RETURN(RI_NO_RETVAL); |
|
501 } |
|
502 |
|
503 /*-------------------------------------------------------------------*//*! |
|
504 * \brief |
|
505 * \param |
|
506 * \return |
|
507 * \note |
|
508 *//*-------------------------------------------------------------------*/ |
|
509 |
|
510 void RI_APIENTRY vgSetiv(VGParamType type, VGint count, const VGint * values) |
|
511 { |
|
512 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
513 RI_IF_ERROR(count < 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
514 RI_IF_ERROR((!values && count > 0) || (values && !isAligned(values,4)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
515 setifv(context, type, count, values, false); |
|
516 RI_RETURN(RI_NO_RETVAL); |
|
517 } |
|
518 |
|
519 /*-------------------------------------------------------------------*//*! |
|
520 * \brief |
|
521 * \param |
|
522 * \return |
|
523 * \note |
|
524 *//*-------------------------------------------------------------------*/ |
|
525 |
|
526 void RI_APIENTRY vgSetfv(VGParamType type, VGint count, const VGfloat * values) |
|
527 { |
|
528 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
529 RI_IF_ERROR(count < 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
530 RI_IF_ERROR((!values && count > 0) || (values && !isAligned(values,4)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
531 setifv(context, type, count, values, true); |
|
532 RI_RETURN(RI_NO_RETVAL); |
|
533 } |
|
534 |
|
535 /*-------------------------------------------------------------------*//*! |
|
536 * \brief |
|
537 * \param |
|
538 * \return |
|
539 * \note |
|
540 *//*-------------------------------------------------------------------*/ |
|
541 |
|
542 static void getifv(VGContext* context, VGParamType type, VGint count, void* values, bool floats) |
|
543 { |
|
544 switch(type) |
|
545 { |
|
546 case VG_MATRIX_MODE: |
|
547 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
548 intToParam(values, floats, count, 0, context->m_matrixMode); |
|
549 break; |
|
550 |
|
551 case VG_FILL_RULE: |
|
552 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
553 intToParam(values, floats, count, 0, context->m_fillRule); |
|
554 break; |
|
555 |
|
556 case VG_IMAGE_QUALITY: |
|
557 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
558 intToParam(values, floats, count, 0, context->m_imageQuality); |
|
559 break; |
|
560 |
|
561 case VG_RENDERING_QUALITY: |
|
562 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
563 intToParam(values, floats, count, 0, context->m_renderingQuality); |
|
564 break; |
|
565 |
|
566 case VG_BLEND_MODE: |
|
567 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
568 intToParam(values, floats, count, 0, context->m_blendMode); |
|
569 break; |
|
570 |
|
571 case VG_IMAGE_MODE: |
|
572 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
573 intToParam(values, floats, count, 0, context->m_imageMode); |
|
574 break; |
|
575 |
|
576 case VG_SCISSOR_RECTS: |
|
577 { |
|
578 if(count > context->m_scissor.size()*4) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
579 for(int i=0;i<context->m_scissor.size();i++) |
|
580 { |
|
581 intToParam(values, floats, count, i*4+0, context->m_scissor[i].x); |
|
582 intToParam(values, floats, count, i*4+1, context->m_scissor[i].y); |
|
583 intToParam(values, floats, count, i*4+2, context->m_scissor[i].width); |
|
584 intToParam(values, floats, count, i*4+3, context->m_scissor[i].height); |
|
585 } |
|
586 break; |
|
587 } |
|
588 |
|
589 case VG_COLOR_TRANSFORM: |
|
590 if(count != 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
591 intToParam(values, floats, count, 0, context->m_colorTransform); |
|
592 break; |
|
593 |
|
594 case VG_COLOR_TRANSFORM_VALUES: |
|
595 if(count > 8) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
596 { |
|
597 for(int i=0;i<count;i++) |
|
598 { |
|
599 floatToParam(values, floats, count, i, context->m_inputColorTransformValues[i]); |
|
600 } |
|
601 } |
|
602 break; |
|
603 |
|
604 case VG_STROKE_LINE_WIDTH: |
|
605 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
606 floatToParam(values, floats, count, 0, context->m_inputStrokeLineWidth); |
|
607 break; |
|
608 |
|
609 case VG_STROKE_CAP_STYLE: |
|
610 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
611 intToParam(values, floats, count, 0, context->m_strokeCapStyle); |
|
612 break; |
|
613 |
|
614 case VG_STROKE_JOIN_STYLE: |
|
615 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
616 intToParam(values, floats, count, 0, context->m_strokeJoinStyle); |
|
617 break; |
|
618 |
|
619 case VG_STROKE_MITER_LIMIT: |
|
620 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
621 floatToParam(values, floats, count, 0, context->m_inputStrokeMiterLimit); |
|
622 break; |
|
623 |
|
624 case VG_STROKE_DASH_PATTERN: |
|
625 { |
|
626 if(count > context->m_inputStrokeDashPattern.size()) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
627 for(int i=0;i<context->m_inputStrokeDashPattern.size();i++) |
|
628 floatToParam(values, floats, count, i, context->m_inputStrokeDashPattern[i]); |
|
629 break; |
|
630 } |
|
631 |
|
632 case VG_STROKE_DASH_PHASE: |
|
633 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
634 floatToParam(values, floats, count, 0, context->m_inputStrokeDashPhase); |
|
635 break; |
|
636 |
|
637 case VG_STROKE_DASH_PHASE_RESET: |
|
638 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
639 intToParam(values, floats, count, 0, context->m_strokeDashPhaseReset); |
|
640 break; |
|
641 |
|
642 case VG_TILE_FILL_COLOR: |
|
643 if(count > 4) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
644 floatToParam(values, floats, count, 0, context->m_inputTileFillColor.r); |
|
645 floatToParam(values, floats, count, 1, context->m_inputTileFillColor.g); |
|
646 floatToParam(values, floats, count, 2, context->m_inputTileFillColor.b); |
|
647 floatToParam(values, floats, count, 3, context->m_inputTileFillColor.a); |
|
648 break; |
|
649 |
|
650 case VG_CLEAR_COLOR: |
|
651 if(count > 4) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
652 floatToParam(values, floats, count, 0, context->m_inputClearColor.r); |
|
653 floatToParam(values, floats, count, 1, context->m_inputClearColor.g); |
|
654 floatToParam(values, floats, count, 2, context->m_inputClearColor.b); |
|
655 floatToParam(values, floats, count, 3, context->m_inputClearColor.a); |
|
656 break; |
|
657 |
|
658 case VG_GLYPH_ORIGIN: |
|
659 if(count > 2) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
660 floatToParam(values, floats, count, 0, context->m_inputGlyphOrigin.x); |
|
661 floatToParam(values, floats, count, 1, context->m_inputGlyphOrigin.y); |
|
662 break; |
|
663 |
|
664 case VG_MASKING: |
|
665 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
666 intToParam(values, floats, count, 0, context->m_masking); |
|
667 break; |
|
668 |
|
669 case VG_SCISSORING: |
|
670 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
671 intToParam(values, floats, count, 0, context->m_scissoring); |
|
672 break; |
|
673 |
|
674 case VG_PIXEL_LAYOUT: |
|
675 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
676 intToParam(values, floats, count, 0, context->m_pixelLayout); |
|
677 break; |
|
678 |
|
679 case VG_SCREEN_LAYOUT: |
|
680 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
681 intToParam(values, floats, count, 0, VG_PIXEL_LAYOUT_UNKNOWN); |
|
682 break; |
|
683 |
|
684 case VG_FILTER_FORMAT_LINEAR: |
|
685 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
686 intToParam(values, floats, count, 0, context->m_filterFormatLinear); |
|
687 break; |
|
688 |
|
689 case VG_FILTER_FORMAT_PREMULTIPLIED: |
|
690 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
691 intToParam(values, floats, count, 0, context->m_filterFormatPremultiplied); |
|
692 break; |
|
693 |
|
694 case VG_FILTER_CHANNEL_MASK: |
|
695 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
696 intToParam(values, floats, count, 0, context->m_filterChannelMask); |
|
697 break; |
|
698 |
|
699 case VG_MAX_SCISSOR_RECTS: |
|
700 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
701 intToParam(values, floats, count, 0, RI_MAX_SCISSOR_RECTANGLES); |
|
702 break; |
|
703 |
|
704 case VG_MAX_DASH_COUNT: |
|
705 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
706 intToParam(values, floats, count, 0, RI_MAX_DASH_COUNT); |
|
707 break; |
|
708 |
|
709 case VG_MAX_KERNEL_SIZE: |
|
710 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
711 intToParam(values, floats, count, 0, RI_MAX_KERNEL_SIZE); |
|
712 break; |
|
713 |
|
714 case VG_MAX_SEPARABLE_KERNEL_SIZE: |
|
715 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
716 intToParam(values, floats, count, 0, RI_MAX_SEPARABLE_KERNEL_SIZE); |
|
717 break; |
|
718 |
|
719 case VG_MAX_COLOR_RAMP_STOPS: |
|
720 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
721 intToParam(values, floats, count, 0, RI_MAX_COLOR_RAMP_STOPS); |
|
722 break; |
|
723 |
|
724 case VG_MAX_IMAGE_WIDTH: |
|
725 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
726 intToParam(values, floats, count, 0, RI_MAX_IMAGE_WIDTH); |
|
727 break; |
|
728 |
|
729 case VG_MAX_IMAGE_HEIGHT: |
|
730 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
731 intToParam(values, floats, count, 0, RI_MAX_IMAGE_HEIGHT); |
|
732 break; |
|
733 |
|
734 case VG_MAX_IMAGE_PIXELS: |
|
735 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
736 intToParam(values, floats, count, 0, RI_MAX_IMAGE_PIXELS); |
|
737 break; |
|
738 |
|
739 case VG_MAX_IMAGE_BYTES: |
|
740 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
741 intToParam(values, floats, count, 0, RI_MAX_IMAGE_BYTES); |
|
742 break; |
|
743 |
|
744 case VG_MAX_FLOAT: |
|
745 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
746 floatToParam(values, floats, count, 0, RI_FLOAT_MAX); |
|
747 break; |
|
748 |
|
749 case VG_MAX_GAUSSIAN_STD_DEVIATION: |
|
750 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
751 floatToParam(values, floats, count, 0, RI_MAX_GAUSSIAN_STD_DEVIATION); |
|
752 break; |
|
753 |
|
754 default: |
|
755 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
756 break; |
|
757 } |
|
758 } |
|
759 |
|
760 /*-------------------------------------------------------------------*//*! |
|
761 * \brief |
|
762 * \param |
|
763 * \return |
|
764 * \note |
|
765 *//*-------------------------------------------------------------------*/ |
|
766 |
|
767 VGfloat RI_APIENTRY vgGetf(VGParamType type) |
|
768 { |
|
769 RI_GET_CONTEXT(0.0f); |
|
770 RI_IF_ERROR(type == VG_SCISSOR_RECTS || type == VG_STROKE_DASH_PATTERN || type == VG_TILE_FILL_COLOR || |
|
771 type == VG_CLEAR_COLOR, VG_ILLEGAL_ARGUMENT_ERROR, 0.0f); //vector type value |
|
772 RIfloat ret = 0.0f; |
|
773 getifv(context, type, 1, &ret, true); |
|
774 RI_RETURN(ret); |
|
775 } |
|
776 |
|
777 /*-------------------------------------------------------------------*//*! |
|
778 * \brief |
|
779 * \param |
|
780 * \return |
|
781 * \note |
|
782 *//*-------------------------------------------------------------------*/ |
|
783 |
|
784 VGint RI_APIENTRY vgGeti(VGParamType type) |
|
785 { |
|
786 RI_GET_CONTEXT(0); |
|
787 RI_IF_ERROR(type == VG_SCISSOR_RECTS || type == VG_STROKE_DASH_PATTERN || type == VG_TILE_FILL_COLOR || |
|
788 type == VG_CLEAR_COLOR, VG_ILLEGAL_ARGUMENT_ERROR, 0); //vector type value |
|
789 VGint ret = 0; |
|
790 getifv(context, type, 1, &ret, false); |
|
791 RI_RETURN(ret); |
|
792 } |
|
793 |
|
794 /*-------------------------------------------------------------------*//*! |
|
795 * \brief |
|
796 * \param |
|
797 * \return |
|
798 * \note |
|
799 *//*-------------------------------------------------------------------*/ |
|
800 |
|
801 void RI_APIENTRY vgGetiv(VGParamType type, VGint count, VGint * values) |
|
802 { |
|
803 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
804 RI_IF_ERROR(count <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
805 RI_IF_ERROR(!values || !isAligned(values,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
806 getifv(context, type, count, values, false); |
|
807 RI_RETURN(RI_NO_RETVAL); |
|
808 } |
|
809 |
|
810 /*-------------------------------------------------------------------*//*! |
|
811 * \brief |
|
812 * \param |
|
813 * \return |
|
814 * \note |
|
815 *//*-------------------------------------------------------------------*/ |
|
816 |
|
817 void RI_APIENTRY vgGetfv(VGParamType type, VGint count, VGfloat * values) |
|
818 { |
|
819 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
820 RI_IF_ERROR(count <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
821 RI_IF_ERROR(!values || !isAligned(values,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
822 getifv(context, type, count, values, true); |
|
823 RI_RETURN(RI_NO_RETVAL); |
|
824 } |
|
825 |
|
826 /*-------------------------------------------------------------------*//*! |
|
827 * \brief |
|
828 * \param |
|
829 * \return |
|
830 * \note |
|
831 *//*-------------------------------------------------------------------*/ |
|
832 |
|
833 VGint RI_APIENTRY vgGetVectorSize(VGParamType type) |
|
834 { |
|
835 RI_GET_CONTEXT(0); |
|
836 VGint ret = 0; |
|
837 switch(type) |
|
838 { |
|
839 case VG_MATRIX_MODE: |
|
840 case VG_FILL_RULE: |
|
841 case VG_IMAGE_QUALITY: |
|
842 case VG_RENDERING_QUALITY: |
|
843 case VG_BLEND_MODE: |
|
844 case VG_IMAGE_MODE: |
|
845 ret = 1; |
|
846 break; |
|
847 |
|
848 case VG_SCISSOR_RECTS: |
|
849 ret = 4*context->m_scissor.size(); |
|
850 break; |
|
851 |
|
852 case VG_COLOR_TRANSFORM: |
|
853 ret = 1; |
|
854 break; |
|
855 |
|
856 case VG_COLOR_TRANSFORM_VALUES: |
|
857 ret = 8; |
|
858 break; |
|
859 |
|
860 case VG_STROKE_LINE_WIDTH: |
|
861 case VG_STROKE_CAP_STYLE: |
|
862 case VG_STROKE_JOIN_STYLE: |
|
863 case VG_STROKE_MITER_LIMIT: |
|
864 ret = 1; |
|
865 break; |
|
866 |
|
867 case VG_STROKE_DASH_PATTERN: |
|
868 ret = context->m_inputStrokeDashPattern.size(); |
|
869 break; |
|
870 |
|
871 case VG_STROKE_DASH_PHASE: |
|
872 case VG_STROKE_DASH_PHASE_RESET: |
|
873 ret = 1; |
|
874 break; |
|
875 |
|
876 case VG_TILE_FILL_COLOR: |
|
877 case VG_CLEAR_COLOR: |
|
878 ret = 4; |
|
879 break; |
|
880 |
|
881 case VG_GLYPH_ORIGIN: |
|
882 ret = 2; |
|
883 break; |
|
884 |
|
885 case VG_MASKING: |
|
886 case VG_SCISSORING: |
|
887 case VG_PIXEL_LAYOUT: |
|
888 case VG_SCREEN_LAYOUT: |
|
889 case VG_FILTER_FORMAT_LINEAR: |
|
890 case VG_FILTER_FORMAT_PREMULTIPLIED: |
|
891 case VG_FILTER_CHANNEL_MASK: |
|
892 case VG_MAX_SCISSOR_RECTS: |
|
893 case VG_MAX_DASH_COUNT: |
|
894 case VG_MAX_KERNEL_SIZE: |
|
895 case VG_MAX_SEPARABLE_KERNEL_SIZE: |
|
896 case VG_MAX_COLOR_RAMP_STOPS: |
|
897 case VG_MAX_IMAGE_WIDTH: |
|
898 case VG_MAX_IMAGE_HEIGHT: |
|
899 case VG_MAX_IMAGE_PIXELS: |
|
900 case VG_MAX_IMAGE_BYTES: |
|
901 case VG_MAX_FLOAT: |
|
902 case VG_MAX_GAUSSIAN_STD_DEVIATION: |
|
903 ret = 1; |
|
904 break; |
|
905 |
|
906 default: |
|
907 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
908 break; |
|
909 } |
|
910 RI_RETURN(ret); |
|
911 } |
|
912 |
|
913 /*-------------------------------------------------------------------*//*! |
|
914 * \brief |
|
915 * \param |
|
916 * \return |
|
917 * \note |
|
918 *//*-------------------------------------------------------------------*/ |
|
919 |
|
920 static void setPaintParameterifv(VGContext* context, Paint* paint, VGPaintParamType paramType, VGint count, const void* values, bool floats) |
|
921 { |
|
922 RI_ASSERT(context); |
|
923 RI_ASSERT(paint); |
|
924 |
|
925 int ivalue = paramToInt(values, floats, count, 0); |
|
926 |
|
927 switch(paramType) |
|
928 { |
|
929 case VG_PAINT_TYPE: |
|
930 if(count != 1 || ivalue < VG_PAINT_TYPE_COLOR || ivalue > VG_PAINT_TYPE_PATTERN) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
931 paint->m_paintType = (VGPaintType)ivalue; |
|
932 break; |
|
933 |
|
934 case VG_PAINT_COLOR: |
|
935 RI_TRACE("\n***** Setting solid color to paint.\n"); |
|
936 RI_TRACE("** ptr: %x\n", (int)paint); |
|
937 if(count != 4) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
938 paint->m_inputPaintColor.set(paramToFloat(values, floats, count, 0), |
|
939 paramToFloat(values, floats, count, 1), |
|
940 paramToFloat(values, floats, count, 2), |
|
941 paramToFloat(values, floats, count, 3), |
|
942 Color::sRGBA); |
|
943 RI_TRACE("** input solid color: [%.3f %.3f %.3f %.4f]\n", paint->m_inputPaintColor.r, paint->m_inputPaintColor.g, paint->m_inputPaintColor.b, paint->m_inputPaintColor.a); |
|
944 paint->setColor(inputColor(paint->m_inputPaintColor)); |
|
945 RI_TRACE("** -> [%.3f %.3f %.3f %.3f]\n", paint->m_paintColor.r, paint->m_paintColor.g, paint->m_paintColor.b, paint->m_paintColor.a); |
|
946 break; |
|
947 |
|
948 case VG_PAINT_COLOR_RAMP_SPREAD_MODE: |
|
949 if(count != 1 || ivalue < VG_COLOR_RAMP_SPREAD_PAD || ivalue > VG_COLOR_RAMP_SPREAD_REFLECT) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
950 paint->m_colorRampSpreadMode = (VGColorRampSpreadMode)ivalue; |
|
951 break; |
|
952 |
|
953 case VG_PAINT_COLOR_RAMP_STOPS: |
|
954 { |
|
955 int numStops = count/5; |
|
956 if(count != numStops*5) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } //count must be a multiple of five |
|
957 try |
|
958 { |
|
959 Array<Paint::GradientStop> colorRampStops; |
|
960 Array<Paint::GradientStop> inputColorRampStops; |
|
961 RIfloat prevOffset = -RI_FLOAT_MAX; |
|
962 bool valid = true; |
|
963 for(int i=0;i<RI_INT_MIN(numStops, RI_MAX_COLOR_RAMP_STOPS);i++) //NOTE: ignores the final stop if there is not enough parameters |
|
964 { |
|
965 Paint::GradientStop gs; |
|
966 gs.offset = paramToFloat(values, floats, count, i*5); |
|
967 gs.color.set(paramToFloat(values, floats, count, i*5+1), |
|
968 paramToFloat(values, floats, count, i*5+2), |
|
969 paramToFloat(values, floats, count, i*5+3), |
|
970 paramToFloat(values, floats, count, i*5+4), |
|
971 Color::sRGBA); |
|
972 inputColorRampStops.push_back(gs); |
|
973 |
|
974 if(gs.offset < prevOffset) |
|
975 valid = false; //decreasing sequence, ignore it |
|
976 |
|
977 if(gs.offset >= 0.0f && gs.offset <= 1.0f) |
|
978 { |
|
979 gs.color.clamp(); |
|
980 |
|
981 if(!colorRampStops.size() && gs.offset > 0.0f) |
|
982 { //the first valid stop is not at 0, replicate the first one |
|
983 RIfloat tmp = gs.offset; |
|
984 gs.offset = 0.0f; |
|
985 colorRampStops.push_back(gs); //throws bad_alloc |
|
986 gs.offset = tmp; |
|
987 } |
|
988 colorRampStops.push_back(gs); //throws bad_alloc |
|
989 } |
|
990 prevOffset = gs.offset; |
|
991 } |
|
992 if(valid && colorRampStops.size() && colorRampStops[colorRampStops.size()-1].offset < 1.0f) |
|
993 { //there is at least one stop, but the last one is not at 1, replicate the last one |
|
994 Paint::GradientStop gs = colorRampStops[colorRampStops.size()-1]; |
|
995 gs.offset = 1.0f; |
|
996 colorRampStops.push_back(gs); //throws bad_alloc |
|
997 } |
|
998 if(!valid || !colorRampStops.size()) |
|
999 { //there are no valid stops, add implicit stops |
|
1000 colorRampStops.clear(); |
|
1001 Paint::GradientStop gs; |
|
1002 gs.offset = 0.0f; |
|
1003 gs.color.set(0,0,0,1,Color::sRGBA); |
|
1004 colorRampStops.push_back(gs); //throws bad_alloc |
|
1005 gs.offset = 1.0f; |
|
1006 gs.color.set(1,1,1,1,Color::sRGBA); |
|
1007 colorRampStops.push_back(gs); //throws bad_alloc |
|
1008 } |
|
1009 RI_ASSERT(colorRampStops.size() >= 2 && colorRampStops.size() <= RI_MAX_COLOR_RAMP_STOPS); |
|
1010 //paint->m_colorRampStops.swap(colorRampStops); //set paint array |
|
1011 //paint->m_inputColorRampStops.swap(inputColorRampStops); //set paint array |
|
1012 paint->setGradientStops(inputColorRampStops, colorRampStops); |
|
1013 //paint->generateLUT(); |
|
1014 } |
|
1015 catch(std::bad_alloc) |
|
1016 { |
|
1017 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
1018 } |
|
1019 break; |
|
1020 } |
|
1021 |
|
1022 case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: |
|
1023 if(count != 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1024 paint->m_colorRampPremultiplied = ivalue ? VG_TRUE : VG_FALSE; |
|
1025 break; |
|
1026 |
|
1027 case VG_PAINT_LINEAR_GRADIENT: |
|
1028 if(count != 4) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1029 paint->m_inputLinearGradientPoint0.set(paramToFloat(values, floats, count, 0), |
|
1030 paramToFloat(values, floats, count, 1)); |
|
1031 paint->m_inputLinearGradientPoint1.set(paramToFloat(values, floats, count, 2), |
|
1032 paramToFloat(values, floats, count, 3)); |
|
1033 paint->setLinearGradient( |
|
1034 inputVector2(paint->m_inputLinearGradientPoint0), |
|
1035 inputVector2(paint->m_inputLinearGradientPoint1)); |
|
1036 |
|
1037 break; |
|
1038 |
|
1039 case VG_PAINT_RADIAL_GRADIENT: |
|
1040 if(count != 5) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1041 paint->m_inputRadialGradientCenter.set(paramToFloat(values, floats, count, 0), |
|
1042 paramToFloat(values, floats, count, 1)); |
|
1043 paint->m_inputRadialGradientFocalPoint.set(paramToFloat(values, floats, count, 2), |
|
1044 paramToFloat(values, floats, count, 3)); |
|
1045 paint->m_inputRadialGradientRadius = paramToFloat(values, floats, count, 4); |
|
1046 paint->setRadialGradient( |
|
1047 inputVector2(paint->m_inputRadialGradientCenter), |
|
1048 inputVector2(paint->m_inputRadialGradientFocalPoint), |
|
1049 inputFloat(paint->m_inputRadialGradientRadius)); |
|
1050 //paint->m_radialGradientCenter = inputVector2(paint->m_inputRadialGradientCenter); |
|
1051 //paint->m_radialGradientFocalPoint = inputVector2(paint->m_inputRadialGradientFocalPoint); |
|
1052 //paint->m_radialGradientRadius = inputFloat(paint->m_inputRadialGradientRadius); |
|
1053 break; |
|
1054 |
|
1055 case VG_PAINT_PATTERN_TILING_MODE: |
|
1056 if(count != 1 || ivalue < VG_TILE_FILL || ivalue > VG_TILE_REFLECT) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1057 paint->m_patternTilingMode = (VGTilingMode)ivalue; |
|
1058 break; |
|
1059 |
|
1060 default: |
|
1061 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1062 break; |
|
1063 } |
|
1064 } |
|
1065 |
|
1066 /*-------------------------------------------------------------------*//*! |
|
1067 * \brief |
|
1068 * \param |
|
1069 * \return |
|
1070 * \note |
|
1071 *//*-------------------------------------------------------------------*/ |
|
1072 |
|
1073 void RI_APIENTRY vgSetParameterf(VGHandle object, VGint paramType, VGfloat value) |
|
1074 { |
|
1075 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1076 bool isImage = context->isValidImage(object); |
|
1077 bool isPath = context->isValidPath(object); |
|
1078 bool isPaint = context->isValidPaint(object); |
|
1079 bool isMaskLayer = context->isValidMaskLayer(object); |
|
1080 bool isFont = context->isValidFont(object); |
|
1081 RI_IF_ERROR(!isImage && !isPath && !isPaint && !isMaskLayer && !isFont, VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid object handle |
|
1082 RI_IF_ERROR(paramType == VG_PAINT_COLOR || paramType == VG_PAINT_COLOR_RAMP_STOPS || paramType == VG_PAINT_LINEAR_GRADIENT || |
|
1083 paramType == VG_PAINT_RADIAL_GRADIENT, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //vector valued parameter |
|
1084 VGfloat values[1] = {value}; |
|
1085 if(isImage) |
|
1086 { //read only, the function does nothing |
|
1087 RI_ASSERT(!isPath && !isPaint && !isMaskLayer && !isFont); |
|
1088 if(paramType < VG_IMAGE_FORMAT || paramType > VG_IMAGE_HEIGHT) |
|
1089 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1090 } |
|
1091 else if(isPath) |
|
1092 { //read only, the function does nothing |
|
1093 RI_ASSERT(!isImage && !isPaint && !isMaskLayer && !isFont); |
|
1094 if(paramType < VG_PATH_FORMAT || paramType > VG_PATH_NUM_COORDS) |
|
1095 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1096 } |
|
1097 else if(isPaint) |
|
1098 { |
|
1099 RI_ASSERT(!isImage && !isPath && !isMaskLayer && !isFont); |
|
1100 setPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, 1, values, true); |
|
1101 } |
|
1102 else if(isMaskLayer) |
|
1103 { |
|
1104 RI_ASSERT(!isImage && !isPath && !isPaint && !isFont); |
|
1105 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1106 } |
|
1107 else |
|
1108 { //read only, the function does nothing |
|
1109 RI_ASSERT(!isImage && !isPath && !isPaint && !isMaskLayer && isFont); |
|
1110 if (paramType != VG_FONT_NUM_GLYPHS) |
|
1111 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1112 } |
|
1113 RI_RETURN(RI_NO_RETVAL); |
|
1114 } |
|
1115 |
|
1116 /*-------------------------------------------------------------------*//*! |
|
1117 * \brief |
|
1118 * \param |
|
1119 * \return |
|
1120 * \note |
|
1121 *//*-------------------------------------------------------------------*/ |
|
1122 |
|
1123 void RI_APIENTRY vgSetParameteri(VGHandle object, VGint paramType, VGint value) |
|
1124 { |
|
1125 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1126 bool isImage = context->isValidImage(object); |
|
1127 bool isPath = context->isValidPath(object); |
|
1128 bool isPaint = context->isValidPaint(object); |
|
1129 bool isMaskLayer = context->isValidMaskLayer(object); |
|
1130 bool isFont = context->isValidFont(object); |
|
1131 RI_IF_ERROR(!isImage && !isPath && !isPaint && !isMaskLayer && !isFont, VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid object handle |
|
1132 RI_IF_ERROR(paramType == VG_PAINT_COLOR || paramType == VG_PAINT_COLOR_RAMP_STOPS || paramType == VG_PAINT_LINEAR_GRADIENT || |
|
1133 paramType == VG_PAINT_RADIAL_GRADIENT, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //vector valued parameter |
|
1134 VGint values[1] = {value}; |
|
1135 if(isImage) |
|
1136 { //read only, the function does nothing |
|
1137 RI_ASSERT(!isPath && !isPaint && !isMaskLayer && !isFont); |
|
1138 if(paramType < VG_IMAGE_FORMAT || paramType > VG_IMAGE_HEIGHT) |
|
1139 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1140 } |
|
1141 else if(isPath) |
|
1142 { //read only, the function does nothing |
|
1143 RI_ASSERT(!isImage && !isPaint && !isMaskLayer && !isFont); |
|
1144 if(paramType < VG_PATH_FORMAT || paramType > VG_PATH_NUM_COORDS) |
|
1145 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1146 } |
|
1147 else if(isPaint) |
|
1148 { |
|
1149 RI_ASSERT(!isImage && !isPath && !isMaskLayer && !isFont); |
|
1150 setPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, 1, values, false); |
|
1151 } |
|
1152 else if(isMaskLayer) |
|
1153 { |
|
1154 RI_ASSERT(!isImage && !isPath && !isPaint && !isFont); |
|
1155 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1156 } |
|
1157 else |
|
1158 { //read only, the function does nothing |
|
1159 RI_ASSERT(!isImage && !isPath && !isPaint && !isMaskLayer && isFont); |
|
1160 if (paramType != VG_FONT_NUM_GLYPHS) |
|
1161 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1162 } |
|
1163 RI_RETURN(RI_NO_RETVAL); |
|
1164 } |
|
1165 |
|
1166 /*-------------------------------------------------------------------*//*! |
|
1167 * \brief |
|
1168 * \param |
|
1169 * \return |
|
1170 * \note |
|
1171 *//*-------------------------------------------------------------------*/ |
|
1172 |
|
1173 void RI_APIENTRY vgSetParameterfv(VGHandle object, VGint paramType, VGint count, const VGfloat * values) |
|
1174 { |
|
1175 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1176 RI_IF_ERROR(count < 0 || (!values && count > 0) || (values && !isAligned(values,4)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
1177 bool isImage = context->isValidImage(object); |
|
1178 bool isPath = context->isValidPath(object); |
|
1179 bool isPaint = context->isValidPaint(object); |
|
1180 bool isMaskLayer = context->isValidMaskLayer(object); |
|
1181 bool isFont = context->isValidFont(object); |
|
1182 RI_IF_ERROR(!isImage && !isPath && !isPaint && !isMaskLayer && !isFont, VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid object handle |
|
1183 if(isImage) |
|
1184 { //read only, the function does nothing |
|
1185 RI_ASSERT(!isPath && !isPaint && !isMaskLayer && !isFont); |
|
1186 if(paramType < VG_IMAGE_FORMAT || paramType > VG_IMAGE_HEIGHT) |
|
1187 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1188 } |
|
1189 else if(isPath) |
|
1190 { //read only, the function does nothing |
|
1191 RI_ASSERT(!isImage && !isPaint && !isMaskLayer && !isFont); |
|
1192 if(paramType < VG_PATH_FORMAT || paramType > VG_PATH_NUM_COORDS) |
|
1193 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1194 } |
|
1195 else if(isPaint) |
|
1196 { |
|
1197 RI_ASSERT(!isImage && !isPath && !isMaskLayer && !isFont); |
|
1198 setPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, count, values, true); |
|
1199 } |
|
1200 else if(isMaskLayer) |
|
1201 { |
|
1202 RI_ASSERT(!isImage && !isPath && !isPaint && !isFont); |
|
1203 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1204 } |
|
1205 else |
|
1206 { //read only, the function does nothing |
|
1207 RI_ASSERT(!isImage && !isPath && !isPaint && !isMaskLayer && isFont); |
|
1208 if (paramType != VG_FONT_NUM_GLYPHS) |
|
1209 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1210 } |
|
1211 RI_RETURN(RI_NO_RETVAL); |
|
1212 } |
|
1213 |
|
1214 /*-------------------------------------------------------------------*//*! |
|
1215 * \brief |
|
1216 * \param |
|
1217 * \return |
|
1218 * \note |
|
1219 *//*-------------------------------------------------------------------*/ |
|
1220 |
|
1221 void RI_APIENTRY vgSetParameteriv(VGHandle object, VGint paramType, VGint count, const VGint * values) |
|
1222 { |
|
1223 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1224 RI_IF_ERROR(count < 0 || (!values && count > 0) || (values && !isAligned(values,4)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
1225 bool isImage = context->isValidImage(object); |
|
1226 bool isPath = context->isValidPath(object); |
|
1227 bool isPaint = context->isValidPaint(object); |
|
1228 bool isMaskLayer = context->isValidMaskLayer(object); |
|
1229 bool isFont = context->isValidFont(object); |
|
1230 RI_IF_ERROR(!isImage && !isPath && !isPaint && !isMaskLayer && !isFont, VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid object handle |
|
1231 if(isImage) |
|
1232 { //read only, the function does nothing |
|
1233 RI_ASSERT(!isPath && !isPaint && !isMaskLayer && !isFont); |
|
1234 if(paramType < VG_IMAGE_FORMAT || paramType > VG_IMAGE_HEIGHT) |
|
1235 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1236 } |
|
1237 else if(isPath) |
|
1238 { //read only, the function does nothing |
|
1239 RI_ASSERT(!isImage && !isPaint && !isMaskLayer && !isFont); |
|
1240 if(paramType < VG_PATH_FORMAT || paramType > VG_PATH_NUM_COORDS) |
|
1241 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1242 } |
|
1243 else if(isPaint) |
|
1244 { |
|
1245 RI_ASSERT(!isImage && !isPath && !isMaskLayer && !isFont); |
|
1246 setPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, count, values, false); |
|
1247 } |
|
1248 else if(isMaskLayer) |
|
1249 { |
|
1250 RI_ASSERT(!isImage && !isPath && !isPaint && !isFont); |
|
1251 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1252 } |
|
1253 else |
|
1254 { //read only, the function does nothing |
|
1255 RI_ASSERT(!isImage && !isPath && !isPaint && !isMaskLayer && isFont); |
|
1256 if (paramType != VG_FONT_NUM_GLYPHS) |
|
1257 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1258 } |
|
1259 RI_RETURN(RI_NO_RETVAL); |
|
1260 } |
|
1261 |
|
1262 /*-------------------------------------------------------------------*//*! |
|
1263 * \brief |
|
1264 * \param |
|
1265 * \return |
|
1266 * \note |
|
1267 *//*-------------------------------------------------------------------*/ |
|
1268 |
|
1269 static void getPaintParameterifv(VGContext* context, Paint* paint, VGPaintParamType type, VGint count, void* values, bool floats) |
|
1270 { |
|
1271 switch(type) |
|
1272 { |
|
1273 case VG_PAINT_TYPE: |
|
1274 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1275 intToParam(values, floats, count, 0, paint->m_paintType); |
|
1276 break; |
|
1277 |
|
1278 case VG_PAINT_COLOR: |
|
1279 if(count > 4) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1280 floatToParam(values, floats, count, 0, paint->m_inputPaintColor.r); |
|
1281 floatToParam(values, floats, count, 1, paint->m_inputPaintColor.g); |
|
1282 floatToParam(values, floats, count, 2, paint->m_inputPaintColor.b); |
|
1283 floatToParam(values, floats, count, 3, paint->m_inputPaintColor.a); |
|
1284 break; |
|
1285 |
|
1286 case VG_PAINT_COLOR_RAMP_SPREAD_MODE: |
|
1287 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1288 intToParam(values, floats, count, 0, paint->m_colorRampSpreadMode); |
|
1289 break; |
|
1290 |
|
1291 case VG_PAINT_COLOR_RAMP_STOPS: |
|
1292 { |
|
1293 if(count > paint->m_inputColorRampStops.size()*5) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1294 int j = 0; |
|
1295 for(int i=0;i<paint->m_inputColorRampStops.size();i++) |
|
1296 { |
|
1297 floatToParam(values, floats, count, j++, paint->m_inputColorRampStops[i].offset); |
|
1298 floatToParam(values, floats, count, j++, paint->m_inputColorRampStops[i].color.r); |
|
1299 floatToParam(values, floats, count, j++, paint->m_inputColorRampStops[i].color.g); |
|
1300 floatToParam(values, floats, count, j++, paint->m_inputColorRampStops[i].color.b); |
|
1301 floatToParam(values, floats, count, j++, paint->m_inputColorRampStops[i].color.a); |
|
1302 } |
|
1303 break; |
|
1304 } |
|
1305 |
|
1306 case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: |
|
1307 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1308 intToParam(values, floats, count, 0, paint->m_colorRampPremultiplied); |
|
1309 break; |
|
1310 |
|
1311 case VG_PAINT_LINEAR_GRADIENT: |
|
1312 if(count > 4) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1313 floatToParam(values, floats, count, 0, paint->m_inputLinearGradientPoint0.x); |
|
1314 floatToParam(values, floats, count, 1, paint->m_inputLinearGradientPoint0.y); |
|
1315 floatToParam(values, floats, count, 2, paint->m_inputLinearGradientPoint1.x); |
|
1316 floatToParam(values, floats, count, 3, paint->m_inputLinearGradientPoint1.y); |
|
1317 break; |
|
1318 |
|
1319 case VG_PAINT_RADIAL_GRADIENT: |
|
1320 if(count > 5) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1321 floatToParam(values, floats, count, 0, paint->m_inputRadialGradientCenter.x); |
|
1322 floatToParam(values, floats, count, 1, paint->m_inputRadialGradientCenter.y); |
|
1323 floatToParam(values, floats, count, 2, paint->m_inputRadialGradientFocalPoint.x); |
|
1324 floatToParam(values, floats, count, 3, paint->m_inputRadialGradientFocalPoint.y); |
|
1325 floatToParam(values, floats, count, 4, paint->m_inputRadialGradientRadius); |
|
1326 break; |
|
1327 |
|
1328 case VG_PAINT_PATTERN_TILING_MODE: |
|
1329 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1330 intToParam(values, floats, count, 0, paint->m_patternTilingMode); |
|
1331 break; |
|
1332 |
|
1333 default: |
|
1334 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1335 break; |
|
1336 } |
|
1337 } |
|
1338 |
|
1339 /*-------------------------------------------------------------------*//*! |
|
1340 * \brief |
|
1341 * \param |
|
1342 * \return |
|
1343 * \note |
|
1344 *//*-------------------------------------------------------------------*/ |
|
1345 |
|
1346 static void getPathParameterifv(VGContext* context, Path* path, VGPathParamType type, VGint count, void* values, bool floats) |
|
1347 { |
|
1348 switch(type) |
|
1349 { |
|
1350 case VG_PATH_FORMAT: |
|
1351 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1352 intToParam(values, floats, count, 0, path->getFormat()); |
|
1353 break; |
|
1354 |
|
1355 case VG_PATH_DATATYPE: |
|
1356 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1357 intToParam(values, floats, count, 0, path->getDatatype()); |
|
1358 break; |
|
1359 |
|
1360 case VG_PATH_SCALE: |
|
1361 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1362 floatToParam(values, floats, count, 0, path->getScale()); |
|
1363 break; |
|
1364 |
|
1365 case VG_PATH_BIAS: |
|
1366 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1367 floatToParam(values, floats, count, 0, path->getBias()); |
|
1368 break; |
|
1369 |
|
1370 case VG_PATH_NUM_SEGMENTS: |
|
1371 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1372 intToParam(values, floats, count, 0, path->getNumSegments()); |
|
1373 break; |
|
1374 |
|
1375 case VG_PATH_NUM_COORDS: |
|
1376 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1377 intToParam(values, floats, count, 0, path->getNumCoordinates()); |
|
1378 break; |
|
1379 |
|
1380 default: |
|
1381 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1382 break; |
|
1383 } |
|
1384 } |
|
1385 |
|
1386 /*-------------------------------------------------------------------*//*! |
|
1387 * \brief |
|
1388 * \param |
|
1389 * \return |
|
1390 * \note |
|
1391 *//*-------------------------------------------------------------------*/ |
|
1392 |
|
1393 static void getImageParameterifv(VGContext* context, Image* image, VGImageParamType type, VGint count, void* values, bool floats) |
|
1394 { |
|
1395 switch(type) |
|
1396 { |
|
1397 case VG_IMAGE_FORMAT: |
|
1398 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1399 RI_ASSERT(isValidImageFormat(image->getDescriptor().vgFormat)); |
|
1400 intToParam(values, floats, count, 0, image->getDescriptor().vgFormat); |
|
1401 break; |
|
1402 |
|
1403 case VG_IMAGE_WIDTH: |
|
1404 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1405 intToParam(values, floats, count, 0, image->getWidth()); |
|
1406 break; |
|
1407 |
|
1408 case VG_IMAGE_HEIGHT: |
|
1409 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1410 intToParam(values, floats, count, 0, image->getHeight()); |
|
1411 break; |
|
1412 |
|
1413 default: |
|
1414 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1415 break; |
|
1416 } |
|
1417 } |
|
1418 |
|
1419 /*-------------------------------------------------------------------*//*! |
|
1420 * \brief |
|
1421 * \param |
|
1422 * \return |
|
1423 * \note |
|
1424 *//*-------------------------------------------------------------------*/ |
|
1425 |
|
1426 static void getFontParameterifv(VGContext* context, Font* font, VGFontParamType type, VGint count, void* values, bool floats) |
|
1427 { |
|
1428 switch(type) |
|
1429 { |
|
1430 case VG_FONT_NUM_GLYPHS: |
|
1431 if(count > 1) { context->setError(VG_ILLEGAL_ARGUMENT_ERROR); return; } |
|
1432 intToParam(values, floats, count, 0, font->getNumGlyphs()); |
|
1433 break; |
|
1434 |
|
1435 default: |
|
1436 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid VGParamType |
|
1437 break; |
|
1438 } |
|
1439 } |
|
1440 |
|
1441 /*-------------------------------------------------------------------*//*! |
|
1442 * \brief |
|
1443 * \param |
|
1444 * \return |
|
1445 * \note |
|
1446 *//*-------------------------------------------------------------------*/ |
|
1447 |
|
1448 VGfloat RI_APIENTRY vgGetParameterf(VGHandle object, VGint paramType) |
|
1449 { |
|
1450 RI_GET_CONTEXT(0.0f); |
|
1451 RI_IF_ERROR(paramType == VG_PAINT_COLOR || paramType == VG_PAINT_COLOR_RAMP_STOPS || paramType == VG_PAINT_LINEAR_GRADIENT || |
|
1452 paramType == VG_PAINT_RADIAL_GRADIENT, VG_ILLEGAL_ARGUMENT_ERROR, 0.0f); //vector valued parameter |
|
1453 bool isImage = context->isValidImage(object); |
|
1454 bool isPath = context->isValidPath(object); |
|
1455 bool isPaint = context->isValidPaint(object); |
|
1456 bool isFont = context->isValidFont(object); |
|
1457 RI_IF_ERROR(!isImage && !isPath && !isPaint && !isFont, VG_BAD_HANDLE_ERROR, 0.0f); //invalid object handle |
|
1458 VGfloat ret = 0.0f; |
|
1459 if(isImage) |
|
1460 { |
|
1461 RI_ASSERT(!isPath && !isPaint && !isFont); |
|
1462 getImageParameterifv(context, (Image*)object, (VGImageParamType)paramType, 1, &ret, true); |
|
1463 } |
|
1464 else if(isPath) |
|
1465 { |
|
1466 RI_ASSERT(!isImage && !isPaint && !isFont); |
|
1467 getPathParameterifv(context, (Path*)object, (VGPathParamType)paramType, 1, &ret, true); |
|
1468 } |
|
1469 else if(isPaint) |
|
1470 { |
|
1471 RI_ASSERT(!isImage && !isPath && !isFont); |
|
1472 getPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, 1, &ret, true); |
|
1473 } |
|
1474 else |
|
1475 { |
|
1476 RI_ASSERT(!isImage && !isPath && !isPaint && isFont); |
|
1477 getFontParameterifv(context, (Font*)object, (VGFontParamType)paramType, 1, &ret, true); |
|
1478 } |
|
1479 RI_RETURN(ret); |
|
1480 } |
|
1481 |
|
1482 /*-------------------------------------------------------------------*//*! |
|
1483 * \brief |
|
1484 * \param |
|
1485 * \return |
|
1486 * \note |
|
1487 *//*-------------------------------------------------------------------*/ |
|
1488 |
|
1489 VGint RI_APIENTRY vgGetParameteri(VGHandle object, VGint paramType) |
|
1490 { |
|
1491 RI_GET_CONTEXT(0); |
|
1492 RI_IF_ERROR(paramType == VG_PAINT_COLOR || paramType == VG_PAINT_COLOR_RAMP_STOPS || paramType == VG_PAINT_LINEAR_GRADIENT || |
|
1493 paramType == VG_PAINT_RADIAL_GRADIENT, VG_ILLEGAL_ARGUMENT_ERROR, 0); //vector valued parameter |
|
1494 bool isImage = context->isValidImage(object); |
|
1495 bool isPath = context->isValidPath(object); |
|
1496 bool isPaint = context->isValidPaint(object); |
|
1497 bool isFont = context->isValidFont(object); |
|
1498 RI_IF_ERROR(!isImage && !isPath && !isPaint && !isFont, VG_BAD_HANDLE_ERROR, 0); //invalid object handle |
|
1499 VGint ret = 0; |
|
1500 if(isImage) |
|
1501 { |
|
1502 RI_ASSERT(!isPath && !isPaint && !isFont); |
|
1503 getImageParameterifv(context, (Image*)object, (VGImageParamType)paramType, 1, &ret, false); |
|
1504 } |
|
1505 else if(isPath) |
|
1506 { |
|
1507 RI_ASSERT(!isImage && !isPaint && !isFont); |
|
1508 getPathParameterifv(context, (Path*)object, (VGPathParamType)paramType, 1, &ret, false); |
|
1509 } |
|
1510 else if(isPaint) |
|
1511 { |
|
1512 RI_ASSERT(!isImage && !isPath && !isFont); |
|
1513 getPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, 1, &ret, false); |
|
1514 } |
|
1515 else |
|
1516 { |
|
1517 RI_ASSERT(!isImage && !isPath && !isPaint && isFont); |
|
1518 getFontParameterifv(context, (Font*)object, (VGFontParamType)paramType, 1, &ret, false); |
|
1519 } |
|
1520 RI_RETURN(ret); |
|
1521 } |
|
1522 |
|
1523 /*-------------------------------------------------------------------*//*! |
|
1524 * \brief |
|
1525 * \param |
|
1526 * \return |
|
1527 * \note |
|
1528 *//*-------------------------------------------------------------------*/ |
|
1529 |
|
1530 void RI_APIENTRY vgGetParameterfv(VGHandle object, VGint paramType, VGint count, VGfloat * values) |
|
1531 { |
|
1532 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1533 RI_IF_ERROR(count <= 0 || !values || !isAligned(values,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
1534 bool isImage = context->isValidImage(object); |
|
1535 bool isPath = context->isValidPath(object); |
|
1536 bool isPaint = context->isValidPaint(object); |
|
1537 bool isFont = context->isValidFont(object); |
|
1538 RI_IF_ERROR(!isImage && !isPath && !isPaint && !isFont, VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid object handle |
|
1539 if(isImage) |
|
1540 { |
|
1541 RI_ASSERT(!isPath && !isPaint && !isFont); |
|
1542 getImageParameterifv(context, (Image*)object, (VGImageParamType)paramType, count, values, true); |
|
1543 } |
|
1544 else if(isPath) |
|
1545 { |
|
1546 RI_ASSERT(!isImage && !isPaint && !isFont); |
|
1547 getPathParameterifv(context, (Path*)object, (VGPathParamType)paramType, count, values, true); |
|
1548 } |
|
1549 else if(isPaint) |
|
1550 { |
|
1551 RI_ASSERT(!isImage && !isPath && !isFont); |
|
1552 getPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, count, values, true); |
|
1553 } |
|
1554 else |
|
1555 { |
|
1556 RI_ASSERT(!isImage && !isPath && !isPaint && isFont); |
|
1557 getFontParameterifv(context, (Font*)object, (VGFontParamType)paramType, count, values, true); |
|
1558 } |
|
1559 RI_RETURN(RI_NO_RETVAL); |
|
1560 } |
|
1561 |
|
1562 /*-------------------------------------------------------------------*//*! |
|
1563 * \brief |
|
1564 * \param |
|
1565 * \return |
|
1566 * \note |
|
1567 *//*-------------------------------------------------------------------*/ |
|
1568 |
|
1569 void RI_APIENTRY vgGetParameteriv(VGHandle object, VGint paramType, VGint count, VGint * values) |
|
1570 { |
|
1571 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1572 RI_IF_ERROR(count <= 0 || !values || !isAligned(values,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
1573 bool isImage = context->isValidImage(object); |
|
1574 bool isPath = context->isValidPath(object); |
|
1575 bool isPaint = context->isValidPaint(object); |
|
1576 bool isFont = context->isValidFont(object); |
|
1577 RI_IF_ERROR(!isImage && !isPath && !isPaint && !isFont, VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid object handle |
|
1578 if(isImage) |
|
1579 { |
|
1580 RI_ASSERT(!isPath && !isPaint && !isFont); |
|
1581 getImageParameterifv(context, (Image*)object, (VGImageParamType)paramType, count, values, false); |
|
1582 } |
|
1583 else if(isPath) |
|
1584 { |
|
1585 RI_ASSERT(!isImage && !isPaint && !isFont); |
|
1586 getPathParameterifv(context, (Path*)object, (VGPathParamType)paramType, count, values, false); |
|
1587 } |
|
1588 else if(isPaint) |
|
1589 { |
|
1590 RI_ASSERT(!isImage && !isPath && !isFont); |
|
1591 getPaintParameterifv(context, (Paint*)object, (VGPaintParamType)paramType, count, values, false); |
|
1592 } |
|
1593 else |
|
1594 { |
|
1595 RI_ASSERT(!isImage && !isPath && !isPaint && isFont); |
|
1596 getFontParameterifv(context, (Font*)object, (VGFontParamType)paramType, count, values, false); |
|
1597 } |
|
1598 RI_RETURN(RI_NO_RETVAL); |
|
1599 } |
|
1600 |
|
1601 /*-------------------------------------------------------------------*//*! |
|
1602 * \brief |
|
1603 * \param |
|
1604 * \return |
|
1605 * \note |
|
1606 *//*-------------------------------------------------------------------*/ |
|
1607 |
|
1608 VGint RI_APIENTRY vgGetParameterVectorSize(VGHandle object, VGint paramType) |
|
1609 { |
|
1610 RI_GET_CONTEXT(0); |
|
1611 bool isImage = context->isValidImage(object); |
|
1612 bool isPath = context->isValidPath(object); |
|
1613 bool isPaint = context->isValidPaint(object); |
|
1614 bool isFont = context->isValidFont(object); |
|
1615 RI_IF_ERROR(!isImage && !isPath && !isPaint && !isFont, VG_BAD_HANDLE_ERROR, 0); //invalid object handle |
|
1616 int ret = 0; |
|
1617 if(isImage) |
|
1618 { |
|
1619 RI_ASSERT(!isPath && !isPaint && !isFont); |
|
1620 switch(paramType) |
|
1621 { |
|
1622 case VG_IMAGE_FORMAT: |
|
1623 case VG_IMAGE_WIDTH: |
|
1624 case VG_IMAGE_HEIGHT: |
|
1625 ret = 1; |
|
1626 break; |
|
1627 |
|
1628 default: |
|
1629 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid paramType |
|
1630 break; |
|
1631 } |
|
1632 } |
|
1633 else if(isPath) |
|
1634 { |
|
1635 RI_ASSERT(!isImage && !isPaint && !isFont); |
|
1636 switch(paramType) |
|
1637 { |
|
1638 case VG_PATH_FORMAT: |
|
1639 case VG_PATH_DATATYPE: |
|
1640 case VG_PATH_SCALE: |
|
1641 case VG_PATH_BIAS: |
|
1642 case VG_PATH_NUM_SEGMENTS: |
|
1643 case VG_PATH_NUM_COORDS: |
|
1644 ret = 1; |
|
1645 break; |
|
1646 |
|
1647 default: |
|
1648 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid paramType |
|
1649 break; |
|
1650 } |
|
1651 } |
|
1652 else if(isPaint) |
|
1653 { |
|
1654 RI_ASSERT(!isImage && !isPath && !isFont); |
|
1655 switch(paramType) |
|
1656 { |
|
1657 case VG_PAINT_TYPE: |
|
1658 case VG_PAINT_COLOR_RAMP_SPREAD_MODE: |
|
1659 case VG_PAINT_PATTERN_TILING_MODE: |
|
1660 ret = 1; |
|
1661 break; |
|
1662 |
|
1663 case VG_PAINT_COLOR: |
|
1664 case VG_PAINT_LINEAR_GRADIENT: |
|
1665 ret = 4; |
|
1666 break; |
|
1667 |
|
1668 case VG_PAINT_COLOR_RAMP_STOPS: |
|
1669 ret = ((Paint*)object)->m_inputColorRampStops.size() * 5; |
|
1670 break; |
|
1671 |
|
1672 case VG_PAINT_COLOR_RAMP_PREMULTIPLIED: |
|
1673 ret = 1; |
|
1674 break; |
|
1675 |
|
1676 case VG_PAINT_RADIAL_GRADIENT: |
|
1677 ret = 5; |
|
1678 break; |
|
1679 |
|
1680 default: |
|
1681 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid paramType |
|
1682 break; |
|
1683 } |
|
1684 } |
|
1685 else |
|
1686 { |
|
1687 RI_ASSERT(!isImage && !isPath && !isPaint && isFont); |
|
1688 switch(paramType) |
|
1689 { |
|
1690 case VG_FONT_NUM_GLYPHS: |
|
1691 ret = 1; |
|
1692 break; |
|
1693 |
|
1694 default: |
|
1695 context->setError(VG_ILLEGAL_ARGUMENT_ERROR); //invalid paramType |
|
1696 break; |
|
1697 } |
|
1698 } |
|
1699 RI_RETURN(ret); |
|
1700 } |
|
1701 |
|
1702 /*-------------------------------------------------------------------*//*! |
|
1703 * \brief |
|
1704 * \param |
|
1705 * \return |
|
1706 * \note |
|
1707 *//*-------------------------------------------------------------------*/ |
|
1708 |
|
1709 static Matrix3x3* getCurrentMatrix(VGContext* context) |
|
1710 { |
|
1711 RI_ASSERT(context); |
|
1712 switch(context->m_matrixMode) |
|
1713 { |
|
1714 case VG_MATRIX_PATH_USER_TO_SURFACE: |
|
1715 return &context->m_pathUserToSurface; |
|
1716 |
|
1717 case VG_MATRIX_IMAGE_USER_TO_SURFACE: |
|
1718 return &context->m_imageUserToSurface; |
|
1719 |
|
1720 case VG_MATRIX_FILL_PAINT_TO_USER: |
|
1721 return &context->m_fillPaintToUser; |
|
1722 |
|
1723 case VG_MATRIX_STROKE_PAINT_TO_USER: |
|
1724 return &context->m_strokePaintToUser; |
|
1725 |
|
1726 default: |
|
1727 RI_ASSERT(context->m_matrixMode == VG_MATRIX_GLYPH_USER_TO_SURFACE); |
|
1728 return &context->m_glyphUserToSurface; |
|
1729 } |
|
1730 } |
|
1731 |
|
1732 /*-------------------------------------------------------------------*//*! |
|
1733 * \brief |
|
1734 * \param |
|
1735 * \return |
|
1736 * \note |
|
1737 *//*-------------------------------------------------------------------*/ |
|
1738 |
|
1739 void RI_APIENTRY vgLoadIdentity(void) |
|
1740 { |
|
1741 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1742 Matrix3x3* d = getCurrentMatrix(context); |
|
1743 d->identity(); |
|
1744 RI_RETURN(RI_NO_RETVAL); |
|
1745 } |
|
1746 |
|
1747 /*-------------------------------------------------------------------*//*! |
|
1748 * \brief |
|
1749 * \param |
|
1750 * \return |
|
1751 * \note |
|
1752 *//*-------------------------------------------------------------------*/ |
|
1753 |
|
1754 void RI_APIENTRY vgLoadMatrix(const VGfloat * m) |
|
1755 { |
|
1756 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1757 RI_IF_ERROR(!m || !isAligned(m,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
1758 Matrix3x3* d = getCurrentMatrix(context); |
|
1759 d->set(inputFloat(m[0]), inputFloat(m[3]), inputFloat(m[6]), |
|
1760 inputFloat(m[1]), inputFloat(m[4]), inputFloat(m[7]), |
|
1761 inputFloat(m[2]), inputFloat(m[5]), inputFloat(m[8])); |
|
1762 if(context->m_matrixMode != VG_MATRIX_IMAGE_USER_TO_SURFACE) |
|
1763 { |
|
1764 (*d)[2].set(0,0,1); |
|
1765 } |
|
1766 RI_RETURN(RI_NO_RETVAL); |
|
1767 } |
|
1768 |
|
1769 /*-------------------------------------------------------------------*//*! |
|
1770 * \brief |
|
1771 * \param |
|
1772 * \return |
|
1773 * \note |
|
1774 *//*-------------------------------------------------------------------*/ |
|
1775 |
|
1776 void RI_APIENTRY vgGetMatrix(VGfloat * m) |
|
1777 { |
|
1778 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1779 RI_IF_ERROR(!m || !isAligned(m,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
1780 Matrix3x3* d = getCurrentMatrix(context); |
|
1781 m[0] = (*d)[0][0]; |
|
1782 m[1] = (*d)[1][0]; |
|
1783 m[2] = (*d)[2][0]; |
|
1784 m[3] = (*d)[0][1]; |
|
1785 m[4] = (*d)[1][1]; |
|
1786 m[5] = (*d)[2][1]; |
|
1787 m[6] = (*d)[0][2]; |
|
1788 m[7] = (*d)[1][2]; |
|
1789 m[8] = (*d)[2][2]; |
|
1790 RI_RETURN(RI_NO_RETVAL); |
|
1791 } |
|
1792 |
|
1793 /*-------------------------------------------------------------------*//*! |
|
1794 * \brief |
|
1795 * \param |
|
1796 * \return |
|
1797 * \note |
|
1798 *//*-------------------------------------------------------------------*/ |
|
1799 |
|
1800 void RI_APIENTRY vgMultMatrix(const VGfloat * m) |
|
1801 { |
|
1802 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1803 RI_IF_ERROR(!m || !isAligned(m,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
1804 Matrix3x3 n(inputFloat(m[0]), inputFloat(m[3]), inputFloat(m[6]), |
|
1805 inputFloat(m[1]), inputFloat(m[4]), inputFloat(m[7]), |
|
1806 inputFloat(m[2]), inputFloat(m[5]), inputFloat(m[8])); |
|
1807 if(context->m_matrixMode != VG_MATRIX_IMAGE_USER_TO_SURFACE) |
|
1808 n[2].set(0,0,1); |
|
1809 |
|
1810 Matrix3x3* d = getCurrentMatrix(context); |
|
1811 *d *= n; |
|
1812 |
|
1813 d->validate(); |
|
1814 //d->assertValid(); |
|
1815 |
|
1816 if(context->m_matrixMode != VG_MATRIX_IMAGE_USER_TO_SURFACE) |
|
1817 { |
|
1818 (*d)[2].set(0,0,1); //force affinity |
|
1819 } |
|
1820 RI_RETURN(RI_NO_RETVAL); |
|
1821 } |
|
1822 |
|
1823 /*-------------------------------------------------------------------*//*! |
|
1824 * \brief |
|
1825 * \param |
|
1826 * \return |
|
1827 * \note |
|
1828 *//*-------------------------------------------------------------------*/ |
|
1829 |
|
1830 void RI_APIENTRY vgTranslate(VGfloat tx, VGfloat ty) |
|
1831 { |
|
1832 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1833 Matrix3x3 n(1, 0, inputFloat(tx), |
|
1834 0, 1, inputFloat(ty), |
|
1835 0, 0, 1 ); |
|
1836 Matrix3x3* d = getCurrentMatrix(context); |
|
1837 *d *= n; |
|
1838 |
|
1839 d->validate(); |
|
1840 //d->assertValid(); |
|
1841 |
|
1842 if(context->m_matrixMode != VG_MATRIX_IMAGE_USER_TO_SURFACE) |
|
1843 { |
|
1844 (*d)[2].set(0,0,1); //force affinity |
|
1845 } |
|
1846 RI_RETURN(RI_NO_RETVAL); |
|
1847 } |
|
1848 |
|
1849 /*-------------------------------------------------------------------*//*! |
|
1850 * \brief |
|
1851 * \param |
|
1852 * \return |
|
1853 * \note |
|
1854 *//*-------------------------------------------------------------------*/ |
|
1855 |
|
1856 void RI_APIENTRY vgScale(VGfloat sx, VGfloat sy) |
|
1857 { |
|
1858 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1859 Matrix3x3 n(inputFloat(sx), 0, 0, |
|
1860 0, inputFloat(sy), 0, |
|
1861 0, 0, 1 ); |
|
1862 Matrix3x3* d = getCurrentMatrix(context); |
|
1863 *d *= n; |
|
1864 |
|
1865 d->validate(); |
|
1866 //d->assertValid(); |
|
1867 |
|
1868 if(context->m_matrixMode != VG_MATRIX_IMAGE_USER_TO_SURFACE) |
|
1869 { |
|
1870 (*d)[2].set(0,0,1); //force affinity |
|
1871 } |
|
1872 RI_RETURN(RI_NO_RETVAL); |
|
1873 } |
|
1874 |
|
1875 /*-------------------------------------------------------------------*//*! |
|
1876 * \brief |
|
1877 * \param |
|
1878 * \return |
|
1879 * \note |
|
1880 *//*-------------------------------------------------------------------*/ |
|
1881 |
|
1882 void RI_APIENTRY vgShear(VGfloat shx, VGfloat shy) |
|
1883 { |
|
1884 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1885 Matrix3x3 n(1, inputFloat(shx), 0, |
|
1886 inputFloat(shy), 1, 0, |
|
1887 0, 0, 1); |
|
1888 Matrix3x3* d = getCurrentMatrix(context); |
|
1889 *d *= n; |
|
1890 |
|
1891 d->validate(); |
|
1892 //d->assertValid(); |
|
1893 |
|
1894 if(context->m_matrixMode != VG_MATRIX_IMAGE_USER_TO_SURFACE) |
|
1895 { |
|
1896 (*d)[2].set(0,0,1); //force affinity |
|
1897 } |
|
1898 RI_RETURN(RI_NO_RETVAL); |
|
1899 } |
|
1900 |
|
1901 /*-------------------------------------------------------------------*//*! |
|
1902 * \brief |
|
1903 * \param |
|
1904 * \return |
|
1905 * \note |
|
1906 *//*-------------------------------------------------------------------*/ |
|
1907 |
|
1908 void RI_APIENTRY vgRotate(VGfloat angle) |
|
1909 { |
|
1910 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1911 RIfloat a = RI_DEG_TO_RAD(inputFloat(angle)); |
|
1912 Matrix3x3 n((RIfloat)cos(a), -(RIfloat)sin(a), 0, |
|
1913 (RIfloat)sin(a), (RIfloat)cos(a), 0, |
|
1914 0, 0, 1 ); |
|
1915 Matrix3x3* d = getCurrentMatrix(context); |
|
1916 *d *= n; |
|
1917 |
|
1918 d->validate(); |
|
1919 //d->assertValid(); |
|
1920 |
|
1921 if(context->m_matrixMode != VG_MATRIX_IMAGE_USER_TO_SURFACE) |
|
1922 { |
|
1923 (*d)[2].set(0,0,1); //force affinity |
|
1924 } |
|
1925 RI_RETURN(RI_NO_RETVAL); |
|
1926 } |
|
1927 |
|
1928 /*-------------------------------------------------------------------*//*! |
|
1929 * \brief |
|
1930 * \param |
|
1931 * \return |
|
1932 * \note |
|
1933 *//*-------------------------------------------------------------------*/ |
|
1934 |
|
1935 void RI_APIENTRY vgMask(VGHandle mask, VGMaskOperation operation, VGint x, VGint y, VGint width, VGint height) |
|
1936 { |
|
1937 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1938 const bool isImage = context->isValidImage(mask); |
|
1939 const bool isMaskLayer = context->isValidMaskLayer(mask); |
|
1940 const bool needInput = (operation != VG_CLEAR_MASK) && (operation != VG_FILL_MASK); |
|
1941 RI_IF_ERROR(operation != VG_CLEAR_MASK && operation != VG_FILL_MASK && !isImage && !isMaskLayer, VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); |
|
1942 RI_IF_ERROR(operation != VG_CLEAR_MASK && operation != VG_FILL_MASK && isImage && eglvgIsInUse((Image*)mask), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
1943 RI_IF_ERROR(operation < VG_CLEAR_MASK || operation > VG_SUBTRACT_MASK, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
1944 RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
1945 Drawable* drawable = context->getCurrentDrawable(); |
|
1946 RI_IF_ERROR(isMaskLayer && drawable->getNumSamples() != ((Surface*)mask)->getNumSamples(), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
1947 if(!drawable || !drawable->getMaskBuffer()) |
|
1948 { |
|
1949 RI_RETURN(RI_NO_RETVAL); //no EGL surface is current at the moment or context has no mask buffer |
|
1950 } |
|
1951 |
|
1952 if(isImage) |
|
1953 drawable->getMaskBuffer()->mask(context->getBlitter(), (Image*)mask, operation, x, y, width, height); |
|
1954 else |
|
1955 { |
|
1956 RI_ASSERT(!isMaskLayer ? !needInput : true); |
|
1957 drawable->getMaskBuffer()->mask(context->getBlitter(), (!mask || !needInput) ? NULL : ((Surface*)mask)->getImage(), operation, x, y, width, height); |
|
1958 } |
|
1959 |
|
1960 RI_RETURN(RI_NO_RETVAL); |
|
1961 } |
|
1962 |
|
1963 void RI_APIENTRY vgRenderToMask(VGPath path, VGbitfield paintModes, VGMaskOperation operation) |
|
1964 { |
|
1965 Path* iPath = (Path*)path; |
|
1966 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
1967 RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid path handle |
|
1968 RI_IF_ERROR(!paintModes || (paintModes & ~(VG_FILL_PATH | VG_STROKE_PATH)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //invalid paint mode |
|
1969 RI_IF_ERROR(operation < VG_CLEAR_MASK || operation > VG_SUBTRACT_MASK, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
1970 Drawable* curr = context->getCurrentDrawable(); |
|
1971 const Surface* mask = curr->getMaskBuffer(); |
|
1972 if(!curr || !curr->getMaskBuffer()) |
|
1973 { |
|
1974 RI_RETURN(RI_NO_RETVAL); //no EGL surface is current at the moment or context has no mask buffer |
|
1975 } |
|
1976 |
|
1977 if(operation == VG_CLEAR_MASK || operation == VG_FILL_MASK) |
|
1978 { |
|
1979 //RI_ASSERT(false); // should call fill! |
|
1980 Image* dummy = NULL; |
|
1981 curr->getMaskBuffer()->mask(context->getBlitter(), dummy, operation, 0, 0, curr->getWidth(), curr->getHeight()); |
|
1982 RI_RETURN(RI_NO_RETVAL); |
|
1983 } |
|
1984 |
|
1985 try |
|
1986 { |
|
1987 // Create a temporary image to render the path on for some mask operations. |
|
1988 // \todo tero: There are optimizations that can do all the mask operations in one pass, but it |
|
1989 // takes too much time to implement them now. |
|
1990 Drawable *tmpDrawable = NULL; |
|
1991 |
|
1992 try |
|
1993 { |
|
1994 if (operation == VG_INTERSECT_MASK) |
|
1995 { |
|
1996 tmpDrawable = RI_NEW(Drawable, (Color::formatToDescriptor(VG_A_8), curr->getWidth(), curr->getHeight(), 1, 0)); |
|
1997 } |
|
1998 } catch (std::bad_alloc e) |
|
1999 { |
|
2000 throw e; |
|
2001 } |
|
2002 |
|
2003 //Drawable drawable(Color::formatToDescriptor(VG_A_8), curr->getWidth(), curr->getHeight(), curr->getNumSamples(), 1); //TODO 0 mask bits (mask buffer is not used) |
|
2004 |
|
2005 Rasterizer& rasterizer = context->m_rasterizer; |
|
2006 rasterizer.clear(); |
|
2007 |
|
2008 rasterizer.setScissoring(context->m_scissoring ? true : false); |
|
2009 if(context->m_scissoring) |
|
2010 rasterizer.setScissor(context->m_scissor); //throws bad_alloc |
|
2011 |
|
2012 PixelPipe& pixelPipe = context->m_pixelPipe; |
|
2013 |
|
2014 // \hack If the mask operation is intersect, we render normally to tempbuffer! |
|
2015 if (!tmpDrawable) |
|
2016 pixelPipe.setRenderToMask(true); |
|
2017 else |
|
2018 pixelPipe.setRenderToMask(false); |
|
2019 |
|
2020 bool skipFill = false; |
|
2021 |
|
2022 if (operation == VG_SET_MASK) |
|
2023 { |
|
2024 Surface *maskSurface = curr->getMaskBuffer(); |
|
2025 maskSurface->clear(Color(), 0, 0, maskSurface->getWidth(), maskSurface->getHeight()); |
|
2026 skipFill = true; |
|
2027 } |
|
2028 |
|
2029 skipFill = skipFill && (paintModes & VG_STROKE_PATH); |
|
2030 |
|
2031 pixelPipe.setMaskOperation(operation); |
|
2032 pixelPipe.setDrawable(tmpDrawable ? tmpDrawable : curr); |
|
2033 pixelPipe.setImage(NULL, VG_DRAW_IMAGE_NORMAL); |
|
2034 pixelPipe.setMask(false); |
|
2035 pixelPipe.setPaint(NULL); //use default paint (solid color alpha = 1) |
|
2036 pixelPipe.setBlendMode(VG_BLEND_SRC_OVER); //write solid color * coverage to dest |
|
2037 bool aa = context->m_renderingQuality == VG_RENDERING_QUALITY_NONANTIALIASED ? false : true; |
|
2038 rasterizer.setAntiAliasing(aa); |
|
2039 |
|
2040 Matrix3x3 userToSurface = context->m_pathUserToSurface; |
|
2041 userToSurface[2].set(0,0,1); //force affinity |
|
2042 |
|
2043 if((paintModes & VG_FILL_PATH) && (!skipFill)) |
|
2044 { |
|
2045 rasterizer.clear(); |
|
2046 rasterizer.setup(0, 0, mask->getWidth(), mask->getHeight(), context->m_fillRule, &pixelPipe); |
|
2047 pixelPipe.prepareSpanUniforms(aa); |
|
2048 iPath->fill(userToSurface, rasterizer); //throws bad_alloc |
|
2049 rasterizer.fill(); //throws bad_alloc |
|
2050 //curr->getMaskBuffer()->mask(drawable.getColorBuffer(), operation, 0, 0, drawable.getWidth(), drawable.getHeight()); |
|
2051 if (tmpDrawable) |
|
2052 { |
|
2053 RI_ASSERT(operation == VG_INTERSECT_MASK); |
|
2054 curr->getMaskBuffer()->mask(context->getBlitter(), tmpDrawable->getColorBuffer()->getImage(), operation, 0, 0, tmpDrawable->getWidth(), tmpDrawable->getHeight()); |
|
2055 |
|
2056 if (paintModes & VG_STROKE_PATH) |
|
2057 { |
|
2058 Surface* tmpSurf = tmpDrawable->getColorBuffer(); |
|
2059 tmpSurf->clear(Color(), 0, 0, |
|
2060 tmpSurf->getWidth(), tmpSurf->getHeight()); |
|
2061 } |
|
2062 else |
|
2063 { |
|
2064 RI_DELETE(tmpDrawable); |
|
2065 tmpDrawable = NULL; |
|
2066 } |
|
2067 } |
|
2068 |
|
2069 } |
|
2070 |
|
2071 if((paintModes & VG_STROKE_PATH) && context->m_strokeLineWidth > 0.0f) |
|
2072 { |
|
2073 pixelPipe.prepareSpanUniforms(aa); |
|
2074 rasterizer.clear(); |
|
2075 rasterizer.setup(0, 0, mask->getWidth(), mask->getHeight(), VG_NON_ZERO, &pixelPipe); |
|
2076 |
|
2077 iPath->stroke(userToSurface, rasterizer, context->m_strokeDashPattern, context->m_strokeDashPhase, context->m_strokeDashPhaseReset ? true : false, |
|
2078 context->m_strokeLineWidth, context->m_strokeCapStyle, context->m_strokeJoinStyle, RI_MAX(context->m_strokeMiterLimit, 1.0f)); //throws bad_alloc |
|
2079 rasterizer.fill(); //throws bad_alloc |
|
2080 //curr->getMaskBuffer()->mask(drawable.getColorBuffer(), operation, 0, 0, drawable.getWidth(), drawable.getHeight()); |
|
2081 |
|
2082 if (tmpDrawable) |
|
2083 { |
|
2084 RI_ASSERT(operation == VG_INTERSECT_MASK); |
|
2085 curr->getMaskBuffer()->mask(context->getBlitter(), tmpDrawable->getColorBuffer()->getImage(), operation, 0, 0, tmpDrawable->getWidth(), tmpDrawable->getHeight()); |
|
2086 RI_DELETE(tmpDrawable); |
|
2087 tmpDrawable = NULL; |
|
2088 } |
|
2089 } |
|
2090 RI_ASSERT(!tmpDrawable); |
|
2091 |
|
2092 } |
|
2093 catch(std::bad_alloc) |
|
2094 { |
|
2095 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2096 } |
|
2097 RI_RETURN(RI_NO_RETVAL); |
|
2098 } |
|
2099 |
|
2100 /*-------------------------------------------------------------------*//*! |
|
2101 * \brief |
|
2102 * \param |
|
2103 * \return |
|
2104 * \note |
|
2105 *//*-------------------------------------------------------------------*/ |
|
2106 |
|
2107 VGMaskLayer RI_APIENTRY vgCreateMaskLayer(VGint width, VGint height) |
|
2108 { |
|
2109 RI_GET_CONTEXT(VG_INVALID_HANDLE); |
|
2110 RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE); |
|
2111 RI_IF_ERROR(width > RI_MAX_IMAGE_WIDTH || height > RI_MAX_IMAGE_HEIGHT || width*height > RI_MAX_IMAGE_PIXELS || |
|
2112 width*height > RI_MAX_IMAGE_BYTES, VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE); |
|
2113 Drawable* curr = context->getCurrentDrawable(); |
|
2114 if(!curr || !curr->getMaskBuffer()) |
|
2115 RI_RETURN(VG_INVALID_HANDLE); //no current drawing surface |
|
2116 |
|
2117 Surface* layer = NULL; |
|
2118 try |
|
2119 { |
|
2120 layer = RI_NEW(Surface, (Color::formatToDescriptor(VG_A_8), width, height, curr->getNumSamples())); //throws bad_alloc |
|
2121 RI_ASSERT(layer); |
|
2122 context->m_maskLayerManager->addResource(layer, context); //throws bad_alloc |
|
2123 layer->clear(Color(1,1,1,1,Color::sRGBA), 0, 0, width, height); |
|
2124 RI_RETURN((VGMaskLayer)layer); |
|
2125 } |
|
2126 catch(std::bad_alloc) |
|
2127 { |
|
2128 RI_DELETE(layer); |
|
2129 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2130 RI_RETURN(VG_INVALID_HANDLE); |
|
2131 } |
|
2132 } |
|
2133 |
|
2134 /*-------------------------------------------------------------------*//*! |
|
2135 * \brief |
|
2136 * \param |
|
2137 * \return |
|
2138 * \note |
|
2139 *//*-------------------------------------------------------------------*/ |
|
2140 |
|
2141 void RI_APIENTRY vgDestroyMaskLayer(VGMaskLayer maskLayer) |
|
2142 { |
|
2143 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2144 RI_IF_ERROR(!context->isValidMaskLayer(maskLayer), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid handle |
|
2145 |
|
2146 context->m_maskLayerManager->removeResource((Surface*)maskLayer); |
|
2147 RI_RETURN(RI_NO_RETVAL); |
|
2148 } |
|
2149 |
|
2150 /*-------------------------------------------------------------------*//*! |
|
2151 * \brief |
|
2152 * \param |
|
2153 * \return |
|
2154 * \note |
|
2155 *//*-------------------------------------------------------------------*/ |
|
2156 |
|
2157 void RI_APIENTRY vgFillMaskLayer(VGMaskLayer maskLayer, VGint x, VGint y, VGint width, VGint height, VGfloat value) |
|
2158 { |
|
2159 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2160 RI_IF_ERROR(!context->isValidMaskLayer(maskLayer), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid handle |
|
2161 RI_IF_ERROR(value < 0.0f || value > 1.0f, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
2162 Surface* layer = (Surface*)maskLayer; |
|
2163 RI_IF_ERROR(width <= 0 || height <= 0 || x < 0 || y < 0 || x > layer->getWidth()-width || y > layer->getHeight()-height, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
2164 layer->clear(Color(1,1,1,value,Color::sRGBA), x, y, width, height); |
|
2165 RI_RETURN(RI_NO_RETVAL); |
|
2166 } |
|
2167 |
|
2168 /*-------------------------------------------------------------------*//*! |
|
2169 * \brief |
|
2170 * \param |
|
2171 * \return |
|
2172 * \note |
|
2173 *//*-------------------------------------------------------------------*/ |
|
2174 |
|
2175 void RI_APIENTRY vgCopyMask(VGMaskLayer maskLayer, VGint dx, VGint dy, VGint sx, VGint sy, VGint width, VGint height) |
|
2176 { |
|
2177 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2178 RI_IF_ERROR(!context->isValidMaskLayer(maskLayer), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid handle |
|
2179 Drawable* drawable = context->getCurrentDrawable(); |
|
2180 if(!drawable || !drawable->getMaskBuffer()) |
|
2181 { |
|
2182 RI_RETURN(RI_NO_RETVAL); //no EGL surface is current at the moment or context has no mask buffer |
|
2183 } |
|
2184 Surface* layer = (Surface*)maskLayer; |
|
2185 RI_IF_ERROR(width <= 0 || height <= 0 || drawable->getNumSamples() != layer->getNumSamples(), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
2186 try |
|
2187 { //copy drawing surface mask to mask layer |
|
2188 // \note Removed support for msaa |
|
2189 layer->m_image->blit(context, drawable->getMaskBuffer()->getImage(), sx, sy, dx, dy, width, height); |
|
2190 //layer->blit(drawable->getMaskBuffer(), sx, sy, dx, dy, width, height); //throws bad_alloc |
|
2191 } |
|
2192 catch(std::bad_alloc) |
|
2193 { |
|
2194 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2195 } |
|
2196 RI_RETURN(RI_NO_RETVAL); |
|
2197 } |
|
2198 |
|
2199 /*-------------------------------------------------------------------*//*! |
|
2200 * \brief |
|
2201 * \param |
|
2202 * \return |
|
2203 * \note |
|
2204 *//*-------------------------------------------------------------------*/ |
|
2205 |
|
2206 void RI_APIENTRY vgClear(VGint x, VGint y, VGint width, VGint height) |
|
2207 { |
|
2208 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2209 RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
2210 Drawable* drawable = context->getCurrentDrawable(); |
|
2211 if(!drawable) |
|
2212 { |
|
2213 RI_RETURN(RI_NO_RETVAL); //no EGL surface is current at the moment |
|
2214 } |
|
2215 |
|
2216 try |
|
2217 { |
|
2218 if(context->m_scissoring) |
|
2219 drawable->getColorBuffer()->clear(context->m_clearColor, x, y, width, height, &context->m_scissor); //throws bad_alloc |
|
2220 else |
|
2221 drawable->getColorBuffer()->clear(context->m_clearColor, x, y, width, height); |
|
2222 } |
|
2223 catch(std::bad_alloc) |
|
2224 { |
|
2225 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2226 } |
|
2227 RI_RETURN(RI_NO_RETVAL); |
|
2228 } |
|
2229 |
|
2230 /*-------------------------------------------------------------------*//*! |
|
2231 * \brief |
|
2232 * \param |
|
2233 * \return |
|
2234 * \note |
|
2235 *//*-------------------------------------------------------------------*/ |
|
2236 |
|
2237 VGPath RI_APIENTRY vgCreatePath(VGint pathFormat, VGPathDatatype datatype, VGfloat scale, VGfloat bias, VGint segmentCapacityHint, VGint coordCapacityHint, VGbitfield capabilities) |
|
2238 { |
|
2239 RI_GET_CONTEXT(VG_INVALID_HANDLE); |
|
2240 RI_IF_ERROR(pathFormat != VG_PATH_FORMAT_STANDARD, VG_UNSUPPORTED_PATH_FORMAT_ERROR, VG_INVALID_HANDLE); |
|
2241 RI_IF_ERROR(datatype < VG_PATH_DATATYPE_S_8 || datatype > VG_PATH_DATATYPE_F, VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE); |
|
2242 RIfloat s = inputFloat(scale); |
|
2243 RIfloat b = inputFloat(bias); |
|
2244 RI_IF_ERROR(s == 0.0f, VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE); |
|
2245 capabilities &= VG_PATH_CAPABILITY_ALL; //undefined bits are ignored |
|
2246 |
|
2247 Path* path = NULL; |
|
2248 try |
|
2249 { |
|
2250 path = RI_NEW(Path, (pathFormat, datatype, s, b, segmentCapacityHint, coordCapacityHint, capabilities)); //throws bad_alloc |
|
2251 RI_ASSERT(path); |
|
2252 context->m_pathManager->addResource(path, context); //throws bad_alloc |
|
2253 RI_RETURN((VGPath)path); |
|
2254 } |
|
2255 catch(std::bad_alloc) |
|
2256 { |
|
2257 RI_DELETE(path); |
|
2258 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2259 RI_RETURN(VG_INVALID_HANDLE); |
|
2260 } |
|
2261 } |
|
2262 |
|
2263 /*-------------------------------------------------------------------*//*! |
|
2264 * \brief |
|
2265 * \param |
|
2266 * \return |
|
2267 * \note |
|
2268 *//*-------------------------------------------------------------------*/ |
|
2269 |
|
2270 void RI_APIENTRY vgClearPath(VGPath path, VGbitfield capabilities) |
|
2271 { |
|
2272 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2273 RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid path handle |
|
2274 capabilities &= VG_PATH_CAPABILITY_ALL; //undefined bits are ignored |
|
2275 ((Path*)path)->clear(capabilities); |
|
2276 RI_RETURN(RI_NO_RETVAL); |
|
2277 } |
|
2278 |
|
2279 /*-------------------------------------------------------------------*//*! |
|
2280 * \brief |
|
2281 * \param |
|
2282 * \return |
|
2283 * \note |
|
2284 *//*-------------------------------------------------------------------*/ |
|
2285 |
|
2286 void RI_APIENTRY vgDestroyPath(VGPath path) |
|
2287 { |
|
2288 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2289 RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid path handle |
|
2290 |
|
2291 context->m_pathManager->removeResource((Path*)path); |
|
2292 |
|
2293 RI_RETURN(RI_NO_RETVAL); |
|
2294 } |
|
2295 |
|
2296 /*-------------------------------------------------------------------*//*! |
|
2297 * \brief |
|
2298 * \param |
|
2299 * \return |
|
2300 * \note |
|
2301 *//*-------------------------------------------------------------------*/ |
|
2302 |
|
2303 void RI_APIENTRY vgRemovePathCapabilities(VGPath path, VGbitfield capabilities) |
|
2304 { |
|
2305 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2306 RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid path handle |
|
2307 capabilities &= VG_PATH_CAPABILITY_ALL; //undefined bits are ignored |
|
2308 |
|
2309 VGbitfield caps = ((Path*)path)->getCapabilities(); |
|
2310 caps &= ~capabilities; |
|
2311 ((Path*)path)->setCapabilities(caps); |
|
2312 RI_RETURN(RI_NO_RETVAL); |
|
2313 } |
|
2314 |
|
2315 /*-------------------------------------------------------------------*//*! |
|
2316 * \brief |
|
2317 * \param |
|
2318 * \return |
|
2319 * \note |
|
2320 *//*-------------------------------------------------------------------*/ |
|
2321 |
|
2322 VGbitfield RI_APIENTRY vgGetPathCapabilities(VGPath path) |
|
2323 { |
|
2324 RI_GET_CONTEXT(0); |
|
2325 RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, 0); //invalid path handle |
|
2326 VGbitfield ret = ((Path*)path)->getCapabilities(); |
|
2327 RI_RETURN(ret); |
|
2328 } |
|
2329 |
|
2330 /*-------------------------------------------------------------------*//*! |
|
2331 * \brief |
|
2332 * \param |
|
2333 * \return |
|
2334 * \note |
|
2335 *//*-------------------------------------------------------------------*/ |
|
2336 |
|
2337 void RI_APIENTRY vgAppendPathData(VGPath dstPath, VGint numSegments, const VGubyte * pathSegments, const void * pathData) |
|
2338 { |
|
2339 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2340 RI_IF_ERROR(!context->isValidPath(dstPath), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid path handle |
|
2341 Path* p = (Path*)dstPath; |
|
2342 RI_IF_ERROR(!(p->getCapabilities() & VG_PATH_CAPABILITY_APPEND_TO), VG_PATH_CAPABILITY_ERROR, RI_NO_RETVAL); //no append cap |
|
2343 RI_IF_ERROR(numSegments <= 0 || !pathSegments || !pathData, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //no segments or data |
|
2344 RI_IF_ERROR((p->getDatatype() == VG_PATH_DATATYPE_S_16 && !isAligned(pathData,2)) || |
|
2345 ((p->getDatatype() == VG_PATH_DATATYPE_S_32 || p->getDatatype() == VG_PATH_DATATYPE_F) && !isAligned(pathData,4)), |
|
2346 VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //invalid alignment |
|
2347 for(int i=0;i<numSegments;i++) |
|
2348 { |
|
2349 VGPathSegment c = (VGPathSegment)(pathSegments[i] & 0x1e); |
|
2350 RI_IF_ERROR(c < VG_CLOSE_PATH || c > VG_LCWARC_TO, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //invalid segment |
|
2351 RI_IF_ERROR(c & ~0x1f, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //reserved bits are nonzero |
|
2352 } |
|
2353 |
|
2354 try |
|
2355 { |
|
2356 p->appendData((const RIuint8*)pathSegments, numSegments, (const RIuint8*)pathData); //throws bad_alloc |
|
2357 } |
|
2358 catch(std::bad_alloc) |
|
2359 { |
|
2360 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2361 } |
|
2362 RI_RETURN(RI_NO_RETVAL); |
|
2363 } |
|
2364 |
|
2365 /*-------------------------------------------------------------------*//*! |
|
2366 * \brief |
|
2367 * \param |
|
2368 * \return |
|
2369 * \note |
|
2370 *//*-------------------------------------------------------------------*/ |
|
2371 |
|
2372 void RI_APIENTRY vgModifyPathCoords(VGPath dstPath, VGint startIndex, VGint numSegments, const void * pathData) |
|
2373 { |
|
2374 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2375 RI_IF_ERROR(!context->isValidPath(dstPath), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid path handle |
|
2376 Path* p = (Path*)dstPath; |
|
2377 RI_IF_ERROR(!(p->getCapabilities() & VG_PATH_CAPABILITY_MODIFY), VG_PATH_CAPABILITY_ERROR, RI_NO_RETVAL); //no modify cap |
|
2378 RI_IF_ERROR(!pathData || startIndex < 0 || numSegments <= 0 || RI_INT_ADDSATURATE(startIndex, numSegments) > p->getNumSegments(), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //no segments |
|
2379 RI_IF_ERROR((p->getDatatype() == VG_PATH_DATATYPE_S_16 && !isAligned(pathData,2)) || |
|
2380 ((p->getDatatype() == VG_PATH_DATATYPE_S_32 || p->getDatatype() == VG_PATH_DATATYPE_F) && !isAligned(pathData,4)), |
|
2381 VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //invalid alignment |
|
2382 p->modifyCoords(startIndex, numSegments, (const RIuint8*)pathData); |
|
2383 RI_RETURN(RI_NO_RETVAL); |
|
2384 } |
|
2385 |
|
2386 /*-------------------------------------------------------------------*//*! |
|
2387 * \brief |
|
2388 * \param |
|
2389 * \return |
|
2390 * \note |
|
2391 *//*-------------------------------------------------------------------*/ |
|
2392 |
|
2393 void RI_APIENTRY vgAppendPath(VGPath dstPath, VGPath srcPath) |
|
2394 { |
|
2395 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2396 RI_IF_ERROR(!context->isValidPath(dstPath) || !context->isValidPath(srcPath), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid path handle |
|
2397 RI_IF_ERROR(!(((Path*)dstPath)->getCapabilities() & VG_PATH_CAPABILITY_APPEND_TO) || |
|
2398 !(((Path*)srcPath)->getCapabilities() & VG_PATH_CAPABILITY_APPEND_FROM), VG_PATH_CAPABILITY_ERROR, RI_NO_RETVAL); //invalid caps |
|
2399 |
|
2400 try |
|
2401 { |
|
2402 ((Path*)dstPath)->append((Path*)srcPath); //throws bad_alloc |
|
2403 } |
|
2404 catch(std::bad_alloc) |
|
2405 { |
|
2406 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2407 } |
|
2408 RI_RETURN(RI_NO_RETVAL); |
|
2409 } |
|
2410 |
|
2411 /*-------------------------------------------------------------------*//*! |
|
2412 * \brief |
|
2413 * \param |
|
2414 * \return |
|
2415 * \note |
|
2416 *//*-------------------------------------------------------------------*/ |
|
2417 |
|
2418 void RI_APIENTRY vgTransformPath(VGPath dstPath, VGPath srcPath) |
|
2419 { |
|
2420 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2421 RI_IF_ERROR(!context->isValidPath(dstPath) || !context->isValidPath(srcPath), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid path handle |
|
2422 RI_IF_ERROR(!(((Path*)dstPath)->getCapabilities() & VG_PATH_CAPABILITY_TRANSFORM_TO) || |
|
2423 !(((Path*)srcPath)->getCapabilities() & VG_PATH_CAPABILITY_TRANSFORM_FROM), VG_PATH_CAPABILITY_ERROR, RI_NO_RETVAL); //invalid caps |
|
2424 try |
|
2425 { |
|
2426 ((Path*)dstPath)->transform((Path*)srcPath, context->m_pathUserToSurface); //throws bad_alloc |
|
2427 } |
|
2428 catch(std::bad_alloc) |
|
2429 { |
|
2430 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2431 } |
|
2432 RI_RETURN(RI_NO_RETVAL); |
|
2433 } |
|
2434 |
|
2435 /*-------------------------------------------------------------------*//*! |
|
2436 * \brief |
|
2437 * \param |
|
2438 * \return |
|
2439 * \note |
|
2440 *//*-------------------------------------------------------------------*/ |
|
2441 |
|
2442 static bool drawPath(VGContext* context, VGPath path, const Matrix3x3& userToSurfaceMatrix, VGbitfield paintModes) |
|
2443 { |
|
2444 Path* iPath = (Path*)path; |
|
2445 //set up rendering surface and mask buffer |
|
2446 Drawable* drawable = context->getCurrentDrawable(); |
|
2447 if(!drawable) |
|
2448 return false; //no EGL surface is current at the moment |
|
2449 |
|
2450 Rasterizer& rasterizer = context->m_rasterizer; |
|
2451 rasterizer.clear(); |
|
2452 |
|
2453 if(context->m_scissoring) |
|
2454 { |
|
2455 rasterizer.setScissor(context->m_scissor); //throws bad_alloc |
|
2456 } |
|
2457 rasterizer.setScissoring(context->m_scissoring ? true : false); |
|
2458 |
|
2459 PixelPipe& pixelPipe = context->m_pixelPipe; |
|
2460 pixelPipe.setRenderToMask(false); |
|
2461 pixelPipe.setDrawable(drawable); |
|
2462 pixelPipe.setImage(NULL, VG_DRAW_IMAGE_NORMAL); |
|
2463 pixelPipe.setMask(context->m_masking ? true : false); |
|
2464 pixelPipe.setBlendMode(context->m_blendMode); |
|
2465 pixelPipe.setTileFillColor(context->m_tileFillColor); |
|
2466 pixelPipe.setImageQuality(context->m_imageQuality); |
|
2467 pixelPipe.setColorTransform(context->m_colorTransform ? true : false, context->m_colorTransformValues); |
|
2468 bool aa = context->m_renderingQuality == VG_RENDERING_QUALITY_NONANTIALIASED ? false : true; |
|
2469 rasterizer.setAntiAliasing(aa); |
|
2470 |
|
2471 Matrix3x3 userToSurface = userToSurfaceMatrix; |
|
2472 userToSurface[2].set(0,0,1); //force affinity |
|
2473 |
|
2474 if(paintModes & VG_FILL_PATH) |
|
2475 { |
|
2476 // \todo Reorganize so that pipe.setpaint handles/requires the matrix setup? |
|
2477 pixelPipe.setPaint((Paint*)context->m_fillPaint); |
|
2478 |
|
2479 Matrix3x3 paintToSurfaceMatrix = userToSurface * context->m_fillPaintToUser; |
|
2480 Matrix3x3 surfaceToPaintMatrix = paintToSurfaceMatrix; |
|
2481 if(surfaceToPaintMatrix.invert()) |
|
2482 { |
|
2483 surfaceToPaintMatrix[2].set(0,0,1); //force affinity |
|
2484 pixelPipe.setSurfaceToPaintMatrix(surfaceToPaintMatrix); |
|
2485 pixelPipe.prepareSpanUniforms(aa); |
|
2486 |
|
2487 rasterizer.clear(); |
|
2488 rasterizer.setup(0, 0, drawable->getWidth(), drawable->getHeight(), context->m_fillRule, &pixelPipe); |
|
2489 iPath->fill(userToSurface, rasterizer); //throws bad_alloc |
|
2490 rasterizer.fill(); //throws bad_alloc |
|
2491 } |
|
2492 } |
|
2493 |
|
2494 if(paintModes & VG_STROKE_PATH && context->m_strokeLineWidth > 0.0f) |
|
2495 { |
|
2496 pixelPipe.setPaint((Paint*)context->m_strokePaint); |
|
2497 |
|
2498 Matrix3x3 paintToSurfaceMatrix = userToSurface * context->m_strokePaintToUser; |
|
2499 Matrix3x3 surfaceToPaintMatrix = paintToSurfaceMatrix; |
|
2500 if(surfaceToPaintMatrix.invert()) |
|
2501 { |
|
2502 surfaceToPaintMatrix[2].set(0,0,1); //force affinity |
|
2503 pixelPipe.setSurfaceToPaintMatrix(surfaceToPaintMatrix); |
|
2504 pixelPipe.prepareSpanUniforms(aa); |
|
2505 |
|
2506 rasterizer.clear(); |
|
2507 rasterizer.setup(0, 0, drawable->getWidth(), drawable->getHeight(), VG_NON_ZERO, &pixelPipe); |
|
2508 iPath->stroke(userToSurface, rasterizer, context->m_strokeDashPattern, context->m_strokeDashPhase, context->m_strokeDashPhaseReset ? true : false, |
|
2509 context->m_strokeLineWidth, context->m_strokeCapStyle, context->m_strokeJoinStyle, RI_MAX(context->m_strokeMiterLimit, 1.0f)); //throws bad_alloc |
|
2510 rasterizer.fill(); //throws bad_alloc |
|
2511 |
|
2512 } |
|
2513 } |
|
2514 return true; |
|
2515 } |
|
2516 |
|
2517 void RI_APIENTRY vgDrawPath(VGPath path, VGbitfield paintModes) |
|
2518 { |
|
2519 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2520 RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid path handle |
|
2521 RI_IF_ERROR(!paintModes || (paintModes & ~(VG_FILL_PATH | VG_STROKE_PATH)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //invalid paint mode |
|
2522 |
|
2523 try |
|
2524 { |
|
2525 eglvgLockSurface(0, 1); |
|
2526 if(!drawPath(context, path, context->m_pathUserToSurface, paintModes)) |
|
2527 { |
|
2528 eglvgUnlockSurface(); |
|
2529 RI_RETURN(RI_NO_RETVAL); |
|
2530 } |
|
2531 eglvgUnlockSurface(); |
|
2532 } |
|
2533 catch(std::bad_alloc) |
|
2534 { |
|
2535 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2536 } |
|
2537 RI_RETURN(RI_NO_RETVAL); |
|
2538 } |
|
2539 |
|
2540 /*-------------------------------------------------------------------*//*! |
|
2541 * \brief |
|
2542 * \param |
|
2543 * \return |
|
2544 * \note |
|
2545 *//*-------------------------------------------------------------------*/ |
|
2546 |
|
2547 VGfloat RI_APIENTRY vgPathLength(VGPath path, VGint startSegment, VGint numSegments) |
|
2548 { |
|
2549 RI_GET_CONTEXT(-1.0f); |
|
2550 RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, -1.0f); //invalid path handle |
|
2551 Path* p = (Path*)path; |
|
2552 RI_IF_ERROR(!(p->getCapabilities() & VG_PATH_CAPABILITY_PATH_LENGTH), VG_PATH_CAPABILITY_ERROR, -1.0f); //invalid caps |
|
2553 RI_IF_ERROR(startSegment < 0 || numSegments <= 0 || RI_INT_ADDSATURATE(startSegment, numSegments) > p->getNumSegments(), VG_ILLEGAL_ARGUMENT_ERROR, -1.0f); |
|
2554 RIfloat pathLength = -1.0f; |
|
2555 try |
|
2556 { |
|
2557 pathLength = p->getPathLength(startSegment, numSegments); //throws bad_alloc |
|
2558 } |
|
2559 catch(std::bad_alloc) |
|
2560 { |
|
2561 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2562 } |
|
2563 RI_RETURN(pathLength); |
|
2564 } |
|
2565 |
|
2566 /*-------------------------------------------------------------------*//*! |
|
2567 * \brief |
|
2568 * \param |
|
2569 * \return |
|
2570 * \note |
|
2571 *//*-------------------------------------------------------------------*/ |
|
2572 |
|
2573 void RI_APIENTRY vgPointAlongPath(VGPath path, VGint startSegment, VGint numSegments, VGfloat distance, VGfloat * x, VGfloat * y, VGfloat * tangentX, VGfloat * tangentY) |
|
2574 { |
|
2575 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2576 RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid path handle |
|
2577 Path* p = (Path*)path; |
|
2578 RI_IF_ERROR((x && y && !(p->getCapabilities() & VG_PATH_CAPABILITY_POINT_ALONG_PATH)) || |
|
2579 (tangentX && tangentY && !(p->getCapabilities() & VG_PATH_CAPABILITY_TANGENT_ALONG_PATH)), VG_PATH_CAPABILITY_ERROR, RI_NO_RETVAL); //invalid caps |
|
2580 RI_IF_ERROR(startSegment < 0 || numSegments <= 0 || RI_INT_ADDSATURATE(startSegment, numSegments) > p->getNumSegments(), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
2581 RI_IF_ERROR(!isAligned(x,4) || !isAligned(y,4) || !isAligned(tangentX,4) || !isAligned(tangentY,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
2582 try |
|
2583 { |
|
2584 Vector2 point, tangent; |
|
2585 p->getPointAlong(startSegment, numSegments, distance, point, tangent); //throws bad_alloc |
|
2586 if(x && y) |
|
2587 { |
|
2588 *x = point.x; |
|
2589 *y = point.y; |
|
2590 } |
|
2591 if(tangentX && tangentY) |
|
2592 { |
|
2593 tangent.normalize(); |
|
2594 *tangentX = tangent.x; |
|
2595 *tangentY = tangent.y; |
|
2596 } |
|
2597 } |
|
2598 catch(std::bad_alloc) |
|
2599 { |
|
2600 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2601 } |
|
2602 RI_RETURN(RI_NO_RETVAL); |
|
2603 } |
|
2604 |
|
2605 /*-------------------------------------------------------------------*//*! |
|
2606 * \brief |
|
2607 * \param |
|
2608 * \return |
|
2609 * \note |
|
2610 *//*-------------------------------------------------------------------*/ |
|
2611 |
|
2612 void RI_APIENTRY vgPathBounds(VGPath path, VGfloat * minx, VGfloat * miny, VGfloat * width, VGfloat * height) |
|
2613 { |
|
2614 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2615 RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid path handle |
|
2616 RI_IF_ERROR(!(((Path*)path)->getCapabilities() & VG_PATH_CAPABILITY_PATH_BOUNDS), VG_PATH_CAPABILITY_ERROR, RI_NO_RETVAL); //invalid caps |
|
2617 RI_IF_ERROR(!minx || !miny || !width || !height, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
2618 RI_IF_ERROR(!isAligned(minx,4) || !isAligned(miny,4) || !isAligned(width,4) || !isAligned(height,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
2619 try |
|
2620 { |
|
2621 RIfloat pminx,pminy,pmaxx,pmaxy; |
|
2622 ((Path*)path)->getPathBounds(pminx, pminy, pmaxx, pmaxy); //throws bad_alloc |
|
2623 *minx = pminx; |
|
2624 *miny = pminy; |
|
2625 *width = pmaxx - pminx; |
|
2626 *height = pmaxy - pminy; |
|
2627 } |
|
2628 catch(std::bad_alloc) |
|
2629 { |
|
2630 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2631 } |
|
2632 RI_RETURN(RI_NO_RETVAL); |
|
2633 } |
|
2634 |
|
2635 /*-------------------------------------------------------------------*//*! |
|
2636 * \brief |
|
2637 * \param |
|
2638 * \return |
|
2639 * \note |
|
2640 *//*-------------------------------------------------------------------*/ |
|
2641 |
|
2642 void RI_APIENTRY vgPathTransformedBounds(VGPath path, VGfloat * minx, VGfloat * miny, VGfloat * width, VGfloat * height) |
|
2643 { |
|
2644 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2645 RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid path handle |
|
2646 RI_IF_ERROR(!(((Path*)path)->getCapabilities() & VG_PATH_CAPABILITY_PATH_TRANSFORMED_BOUNDS), VG_PATH_CAPABILITY_ERROR, RI_NO_RETVAL); //invalid caps |
|
2647 RI_IF_ERROR(!minx || !miny || !width || !height, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
2648 RI_IF_ERROR(!isAligned(minx,4) || !isAligned(miny,4) || !isAligned(width,4) || !isAligned(height,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
2649 try |
|
2650 { |
|
2651 RIfloat pminx, pminy, pmaxx, pmaxy; |
|
2652 ((Path*)path)->getPathTransformedBounds(context->m_pathUserToSurface, pminx, pminy, pmaxx, pmaxy); //throws bad_alloc |
|
2653 *minx = pminx; |
|
2654 *miny = pminy; |
|
2655 *width = pmaxx - pminx; |
|
2656 *height = pmaxy - pminy; |
|
2657 } |
|
2658 catch(std::bad_alloc) |
|
2659 { |
|
2660 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2661 } |
|
2662 RI_RETURN(RI_NO_RETVAL); |
|
2663 } |
|
2664 |
|
2665 /*-------------------------------------------------------------------*//*! |
|
2666 * \brief |
|
2667 * \param |
|
2668 * \return |
|
2669 * \note |
|
2670 *//*-------------------------------------------------------------------*/ |
|
2671 |
|
2672 VGboolean RI_APIENTRY vgInterpolatePath(VGPath dstPath, VGPath startPath, VGPath endPath, VGfloat amount) |
|
2673 { |
|
2674 RI_GET_CONTEXT(VG_FALSE); |
|
2675 RI_IF_ERROR(!context->isValidPath(dstPath) || !context->isValidPath(startPath) || !context->isValidPath(endPath), VG_BAD_HANDLE_ERROR, VG_FALSE); //invalid path handle |
|
2676 RI_IF_ERROR(!(((Path*)dstPath)->getCapabilities() & VG_PATH_CAPABILITY_INTERPOLATE_TO) || |
|
2677 !(((Path*)startPath)->getCapabilities() & VG_PATH_CAPABILITY_INTERPOLATE_FROM) || |
|
2678 !(((Path*)endPath)->getCapabilities() & VG_PATH_CAPABILITY_INTERPOLATE_FROM), VG_PATH_CAPABILITY_ERROR, VG_FALSE); //invalid caps |
|
2679 VGboolean ret = VG_FALSE; |
|
2680 try |
|
2681 { |
|
2682 if(((Path*)dstPath)->interpolate((const Path*)startPath, (const Path*)endPath, inputFloat(amount))) //throws bad_alloc |
|
2683 ret = VG_TRUE; |
|
2684 } |
|
2685 catch(std::bad_alloc) |
|
2686 { |
|
2687 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2688 } |
|
2689 RI_RETURN(ret); |
|
2690 } |
|
2691 |
|
2692 /*-------------------------------------------------------------------*//*! |
|
2693 * \brief |
|
2694 * \param |
|
2695 * \return |
|
2696 * \note |
|
2697 *//*-------------------------------------------------------------------*/ |
|
2698 |
|
2699 VGPaint RI_APIENTRY vgCreatePaint(void) |
|
2700 { |
|
2701 RI_GET_CONTEXT(VG_INVALID_HANDLE); |
|
2702 Paint* paint = NULL; |
|
2703 RI_TRACE("\n***** vgCreatePaint\n"); |
|
2704 try |
|
2705 { |
|
2706 paint = RI_NEW(Paint, ()); //throws bad_alloc |
|
2707 RI_ASSERT(paint); |
|
2708 context->m_paintManager->addResource(paint, context); //throws bad_alloc |
|
2709 RI_TRACE("===== vgCreatePaint: Created paint obj: %x\n", (int)paint); |
|
2710 RI_RETURN((VGPaint)paint); |
|
2711 } |
|
2712 catch(std::bad_alloc) |
|
2713 { |
|
2714 RI_DELETE(paint); |
|
2715 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2716 RI_RETURN(VG_INVALID_HANDLE); |
|
2717 } |
|
2718 } |
|
2719 |
|
2720 /*-------------------------------------------------------------------*//*! |
|
2721 * \brief |
|
2722 * \param |
|
2723 * \return |
|
2724 * \note |
|
2725 *//*-------------------------------------------------------------------*/ |
|
2726 |
|
2727 void RI_APIENTRY vgDestroyPaint(VGPaint paint) |
|
2728 { |
|
2729 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2730 RI_IF_ERROR(!context->isValidPaint(paint), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid paint handle |
|
2731 |
|
2732 context->m_paintManager->removeResource((Paint*)paint); |
|
2733 |
|
2734 RI_RETURN(RI_NO_RETVAL); |
|
2735 } |
|
2736 |
|
2737 /*-------------------------------------------------------------------*//*! |
|
2738 * \brief |
|
2739 * \param |
|
2740 * \return |
|
2741 * \note |
|
2742 *//*-------------------------------------------------------------------*/ |
|
2743 |
|
2744 void RI_APIENTRY vgSetPaint(VGPaint paint, VGbitfield paintModes) |
|
2745 { |
|
2746 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2747 RI_TRACE("\n***** vgSetPaint: %x mode: %d\n", (int)paint, (int)paintModes); |
|
2748 RI_IF_ERROR(paint && !context->isValidPaint(paint), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid paint handle |
|
2749 RI_IF_ERROR(!paintModes || paintModes & ~(VG_FILL_PATH | VG_STROKE_PATH), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //invalid paint mode |
|
2750 |
|
2751 context->releasePaint(paintModes); |
|
2752 |
|
2753 if(paintModes & VG_FILL_PATH) |
|
2754 { |
|
2755 if(paint) |
|
2756 ((Paint*)paint)->addReference(); |
|
2757 context->m_fillPaint = paint; |
|
2758 } |
|
2759 if(paintModes & VG_STROKE_PATH) |
|
2760 { |
|
2761 if(paint) |
|
2762 ((Paint*)paint)->addReference(); |
|
2763 context->m_strokePaint = paint; |
|
2764 } |
|
2765 RI_RETURN(RI_NO_RETVAL); |
|
2766 } |
|
2767 |
|
2768 /*-------------------------------------------------------------------*//*! |
|
2769 * \brief |
|
2770 * \param |
|
2771 * \return |
|
2772 * \note |
|
2773 *//*-------------------------------------------------------------------*/ |
|
2774 |
|
2775 void RI_APIENTRY vgSetColor(VGPaint paint, VGuint rgba) |
|
2776 { |
|
2777 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2778 RI_TRACE("\n***** vgSetColor: %x, rgba: %x\n", paint, rgba); |
|
2779 RI_IF_ERROR(!context->isValidPaint(paint), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid paint handle |
|
2780 Paint* p = (Paint*)paint; |
|
2781 p->m_inputPaintColor.unpack(rgba, Color::formatToDescriptor(VG_sRGBA_8888)); |
|
2782 p->setColor(inputColor(p->m_inputPaintColor)); |
|
2783 RI_TRACE("** -> [%.3f %.3f %.3f %.3f]\n", p->m_paintColor.r, p->m_paintColor.g, p->m_paintColor.b, p->m_paintColor.a); |
|
2784 // p->m_paintColor = inputColor(p->m_inputPaintColor); |
|
2785 // p->m_paintColor.clamp(); |
|
2786 // p->m_paintColor.premultiply(); |
|
2787 RI_RETURN(RI_NO_RETVAL); |
|
2788 } |
|
2789 |
|
2790 /*-------------------------------------------------------------------*//*! |
|
2791 * \brief |
|
2792 * \param |
|
2793 * \return |
|
2794 * \note |
|
2795 *//*-------------------------------------------------------------------*/ |
|
2796 |
|
2797 VGuint RI_APIENTRY vgGetColor(VGPaint paint) |
|
2798 { |
|
2799 RI_GET_CONTEXT(0); |
|
2800 RI_IF_ERROR(!context->isValidPaint(paint), VG_BAD_HANDLE_ERROR, 0); //invalid paint handle |
|
2801 Color tempColor = ((Paint*)paint)->m_inputPaintColor; |
|
2802 tempColor.clamp(); |
|
2803 unsigned int ret = tempColor.pack(Color::formatToDescriptor(VG_sRGBA_8888)); |
|
2804 RI_RETURN(ret); |
|
2805 } |
|
2806 |
|
2807 /*-------------------------------------------------------------------*//*! |
|
2808 * \brief |
|
2809 * \param |
|
2810 * \return |
|
2811 * \note |
|
2812 *//*-------------------------------------------------------------------*/ |
|
2813 |
|
2814 VGPaint RI_APIENTRY vgGetPaint(VGPaintMode paintMode) |
|
2815 { |
|
2816 RI_GET_CONTEXT(VG_INVALID_HANDLE); |
|
2817 RI_IF_ERROR(paintMode != VG_FILL_PATH && paintMode != VG_STROKE_PATH, VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE); //invalid paint mode |
|
2818 |
|
2819 if(paintMode == VG_FILL_PATH) |
|
2820 { |
|
2821 RI_RETURN(context->m_fillPaint); |
|
2822 } |
|
2823 RI_RETURN(context->m_strokePaint); |
|
2824 } |
|
2825 |
|
2826 /*-------------------------------------------------------------------*//*! |
|
2827 * \brief |
|
2828 * \param |
|
2829 * \return |
|
2830 * \note |
|
2831 *//*-------------------------------------------------------------------*/ |
|
2832 |
|
2833 void RI_APIENTRY vgPaintPattern(VGPaint paint, VGImage image) |
|
2834 { |
|
2835 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2836 RI_IF_ERROR(!context->isValidPaint(paint) || (image != VG_INVALID_HANDLE && !context->isValidImage(image)), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid handle |
|
2837 Image* img = (Image*)image; |
|
2838 Paint* pnt = (Paint*)paint; |
|
2839 RI_IF_ERROR(image != VG_INVALID_HANDLE && eglvgIsInUse(img), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
2840 Image* pattern = pnt->m_pattern; |
|
2841 if(pattern) |
|
2842 { |
|
2843 pattern->removeInUse(); |
|
2844 if(!pattern->removeReference()) |
|
2845 RI_DELETE(pattern); |
|
2846 } |
|
2847 pnt->m_pattern = img; |
|
2848 |
|
2849 if(img) |
|
2850 { |
|
2851 img->addReference(); |
|
2852 img->addInUse(); |
|
2853 } |
|
2854 RI_RETURN(RI_NO_RETVAL); |
|
2855 } |
|
2856 |
|
2857 /*-------------------------------------------------------------------*//*! |
|
2858 * \brief |
|
2859 * \param |
|
2860 * \return |
|
2861 * \note |
|
2862 *//*-------------------------------------------------------------------*/ |
|
2863 |
|
2864 VGImage RI_APIENTRY vgCreateImage(VGImageFormat format, VGint width, VGint height, VGbitfield allowedQuality) |
|
2865 { |
|
2866 RI_GET_CONTEXT(VG_INVALID_HANDLE); |
|
2867 RI_IF_ERROR(!isValidImageFormat(format), VG_UNSUPPORTED_IMAGE_FORMAT_ERROR, VG_INVALID_HANDLE); |
|
2868 RI_IF_ERROR(width <= 0 || height <= 0 || !allowedQuality || |
|
2869 (allowedQuality & ~(VG_IMAGE_QUALITY_NONANTIALIASED | VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_BETTER)), VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE); |
|
2870 RI_IF_ERROR(width > RI_MAX_IMAGE_WIDTH || height > RI_MAX_IMAGE_HEIGHT || width*height > RI_MAX_IMAGE_PIXELS || |
|
2871 ((width*Color::formatToDescriptor(format).bitsPerPixel+7)/8)*height > RI_MAX_IMAGE_BYTES, VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE); |
|
2872 |
|
2873 Image* image = NULL; |
|
2874 try |
|
2875 { |
|
2876 image = RI_NEW(Image, (Color::formatToDescriptor(format), width, height, allowedQuality)); //throws bad_alloc |
|
2877 RI_ASSERT(image); |
|
2878 context->m_imageManager->addResource(image, context); //throws bad_alloc |
|
2879 RI_RETURN((VGImage)image); |
|
2880 } |
|
2881 catch(std::bad_alloc) |
|
2882 { |
|
2883 RI_DELETE(image); |
|
2884 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
2885 RI_RETURN(VG_INVALID_HANDLE); |
|
2886 } |
|
2887 } |
|
2888 |
|
2889 /*-------------------------------------------------------------------*//*! |
|
2890 * \brief |
|
2891 * \param |
|
2892 * \return |
|
2893 * \note |
|
2894 *//*-------------------------------------------------------------------*/ |
|
2895 |
|
2896 void RI_APIENTRY vgDestroyImage(VGImage image) |
|
2897 { |
|
2898 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2899 RI_IF_ERROR(!context->isValidImage(image), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid image handle |
|
2900 |
|
2901 context->m_imageManager->removeResource((Image*)image); |
|
2902 |
|
2903 RI_RETURN(RI_NO_RETVAL); |
|
2904 } |
|
2905 |
|
2906 /*-------------------------------------------------------------------*//*! |
|
2907 * \brief |
|
2908 * \param |
|
2909 * \return |
|
2910 * \note |
|
2911 *//*-------------------------------------------------------------------*/ |
|
2912 |
|
2913 void RI_APIENTRY vgClearImage(VGImage image, VGint x, VGint y, VGint width, VGint height) |
|
2914 { |
|
2915 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2916 RI_IF_ERROR(!context->isValidImage(image), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); |
|
2917 Image* img = (Image*)image; |
|
2918 RI_IF_ERROR(eglvgIsInUse(img), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
2919 RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
2920 eglvgLockSurface(0, 1); |
|
2921 img->clear(context->m_clearColor, x, y, width, height); |
|
2922 eglvgUnlockSurface(); |
|
2923 RI_RETURN(RI_NO_RETVAL); |
|
2924 } |
|
2925 |
|
2926 /*-------------------------------------------------------------------*//*! |
|
2927 * \brief |
|
2928 * \param |
|
2929 * \return |
|
2930 * \note |
|
2931 *//*-------------------------------------------------------------------*/ |
|
2932 |
|
2933 void RI_APIENTRY vgImageSubData(VGImage image, const void * data, VGint dataStride, VGImageFormat dataFormat, VGint x, VGint y, VGint width, VGint height) |
|
2934 { |
|
2935 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2936 RI_IF_ERROR(!context->isValidImage(image), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); |
|
2937 Image* img = (Image*)image; |
|
2938 RI_IF_ERROR(eglvgIsInUse(img), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
2939 RI_IF_ERROR(!isValidImageFormat(dataFormat), VG_UNSUPPORTED_IMAGE_FORMAT_ERROR, RI_NO_RETVAL); |
|
2940 RI_IF_ERROR(!data || !isAligned(data, dataFormat) || width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
2941 { |
|
2942 Image input(Color::formatToDescriptor(dataFormat), width, height, dataStride, const_cast<RIuint8*>((const RIuint8*)data)); |
|
2943 input.addReference(); |
|
2944 try |
|
2945 { |
|
2946 img->blit(context, &input, 0, 0, x, y, width, height); //throws bad_alloc |
|
2947 } |
|
2948 catch(std::bad_alloc) |
|
2949 { |
|
2950 } |
|
2951 input.removeReference(); |
|
2952 } |
|
2953 RI_RETURN(RI_NO_RETVAL); |
|
2954 } |
|
2955 |
|
2956 /*-------------------------------------------------------------------*//*! |
|
2957 * \brief |
|
2958 * \param |
|
2959 * \return |
|
2960 * \note |
|
2961 *//*-------------------------------------------------------------------*/ |
|
2962 |
|
2963 void RI_APIENTRY vgGetImageSubData(VGImage image, void * data, VGint dataStride, VGImageFormat dataFormat, VGint x, VGint y, VGint width, VGint height) |
|
2964 { |
|
2965 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
2966 RI_IF_ERROR(!context->isValidImage(image), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); |
|
2967 Image* img = (Image*)image; |
|
2968 RI_IF_ERROR(eglvgIsInUse(img), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
2969 RI_IF_ERROR(!isValidImageFormat(dataFormat), VG_UNSUPPORTED_IMAGE_FORMAT_ERROR, RI_NO_RETVAL); |
|
2970 RI_IF_ERROR(!data || !isAligned(data, dataFormat) || width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
2971 { |
|
2972 Image output(Color::formatToDescriptor(dataFormat), width, height, dataStride, (RIuint8*)data); |
|
2973 output.addReference(); |
|
2974 try |
|
2975 { |
|
2976 output.blit(context, img, x, y, 0, 0, width, height); //throws bad_alloc |
|
2977 } |
|
2978 catch(std::bad_alloc) |
|
2979 { |
|
2980 } |
|
2981 output.removeReference(); |
|
2982 } |
|
2983 RI_RETURN(RI_NO_RETVAL); |
|
2984 } |
|
2985 |
|
2986 /*-------------------------------------------------------------------*//*! |
|
2987 * \brief |
|
2988 * \param |
|
2989 * \return |
|
2990 * \note |
|
2991 *//*-------------------------------------------------------------------*/ |
|
2992 |
|
2993 VGImage RI_APIENTRY vgChildImage(VGImage parent, VGint x, VGint y, VGint width, VGint height) |
|
2994 { |
|
2995 RI_GET_CONTEXT(VG_INVALID_HANDLE); |
|
2996 RI_IF_ERROR(!context->isValidImage(parent), VG_BAD_HANDLE_ERROR, VG_INVALID_HANDLE); |
|
2997 Image* p = (Image*)parent; |
|
2998 RI_IF_ERROR(eglvgIsInUse((Image*)parent), VG_IMAGE_IN_USE_ERROR, VG_INVALID_HANDLE); |
|
2999 RI_IF_ERROR(x < 0 || x >= p->getWidth() || y < 0 || y >= p->getHeight() || |
|
3000 width <= 0 || height <= 0 || RI_INT_ADDSATURATE(x, width) > p->getWidth() || RI_INT_ADDSATURATE(y, height) > p->getHeight(), VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE); |
|
3001 |
|
3002 Image* child = NULL; |
|
3003 try |
|
3004 { |
|
3005 child = RI_NEW(Image, (p, x, y, width, height)); //throws bad_alloc |
|
3006 RI_ASSERT(child); |
|
3007 context->m_imageManager->addResource(child, context); //throws bad_alloc |
|
3008 RI_RETURN((VGImage)child); |
|
3009 } |
|
3010 catch(std::bad_alloc) |
|
3011 { |
|
3012 RI_DELETE(child); |
|
3013 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
3014 RI_RETURN(VG_INVALID_HANDLE); |
|
3015 } |
|
3016 } |
|
3017 |
|
3018 /*-------------------------------------------------------------------*//*! |
|
3019 * \brief |
|
3020 * \param |
|
3021 * \return |
|
3022 * \note |
|
3023 *//*-------------------------------------------------------------------*/ |
|
3024 |
|
3025 VGImage RI_APIENTRY vgGetParent(VGImage image) |
|
3026 { |
|
3027 RI_GET_CONTEXT(VG_INVALID_HANDLE); |
|
3028 RI_IF_ERROR(!context->isValidImage(image), VG_BAD_HANDLE_ERROR, VG_INVALID_HANDLE); |
|
3029 VGImage ret = image; //if image has no ancestors, image is returned. |
|
3030 |
|
3031 //The vgGetParent function returns the closest valid ancestor (i.e., one that has not been the target of a vgDestroyImage call) |
|
3032 // of the given image. |
|
3033 Image* im = ((Image*)image)->getParent(); |
|
3034 for(;im;im = im->getParent()) |
|
3035 { |
|
3036 if(context->isValidImage((VGImage)im)) |
|
3037 { //the parent is valid and alive |
|
3038 ret = (VGImage)im; |
|
3039 break; |
|
3040 } |
|
3041 } |
|
3042 RI_RETURN(ret); |
|
3043 } |
|
3044 |
|
3045 /*-------------------------------------------------------------------*//*! |
|
3046 * \brief |
|
3047 * \param |
|
3048 * \return |
|
3049 * \note |
|
3050 *//*-------------------------------------------------------------------*/ |
|
3051 |
|
3052 void RI_APIENTRY vgCopyImage(VGImage dst, VGint dx, VGint dy, VGImage src, VGint sx, VGint sy, VGint width, VGint height, VGboolean dither) |
|
3053 { |
|
3054 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3055 RI_IF_ERROR(!context->isValidImage(dst) || !context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); |
|
3056 RI_IF_ERROR(eglvgIsInUse((Image*)dst) || eglvgIsInUse((Image*)src), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
3057 RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3058 try |
|
3059 { |
|
3060 ((Image*)dst)->blit(context, (Image*)src, sx, sy, dx, dy, width, height, NULL, dither ? true : false); //throws bad_alloc |
|
3061 } |
|
3062 catch(std::bad_alloc) |
|
3063 { |
|
3064 } |
|
3065 RI_RETURN(RI_NO_RETVAL); |
|
3066 } |
|
3067 |
|
3068 |
|
3069 /*-------------------------------------------------------------------*//*! |
|
3070 * \brief |
|
3071 * \param |
|
3072 * \return |
|
3073 * \note |
|
3074 *//*-------------------------------------------------------------------*/ |
|
3075 |
|
3076 static bool drawImage(VGContext* context, VGImage image, const Matrix3x3& userToSurfaceMatrix) |
|
3077 { |
|
3078 Drawable* drawable = context->getCurrentDrawable(); |
|
3079 if(!drawable) |
|
3080 return false; //no EGL surface is current at the moment |
|
3081 |
|
3082 Image* img = (Image*)image; |
|
3083 //transform image corners into the surface space |
|
3084 Vector3 p0(0, 0, 1); |
|
3085 Vector3 p1(0, (RIfloat)img->getHeight(), 1); |
|
3086 Vector3 p2((RIfloat)img->getWidth(), (RIfloat)img->getHeight(), 1); |
|
3087 Vector3 p3((RIfloat)img->getWidth(), 0, 1); |
|
3088 p0 = userToSurfaceMatrix * p0; |
|
3089 p1 = userToSurfaceMatrix * p1; |
|
3090 p2 = userToSurfaceMatrix * p2; |
|
3091 p3 = userToSurfaceMatrix * p3; |
|
3092 if(p0.z <= 0.0f || p1.z <= 0.0f || p2.z <= 0.0f || p3.z <= 0.0f) |
|
3093 return false; |
|
3094 |
|
3095 //projection |
|
3096 p0 *= 1.0f/p0.z; |
|
3097 p1 *= 1.0f/p1.z; |
|
3098 p2 *= 1.0f/p2.z; |
|
3099 p3 *= 1.0f/p3.z; |
|
3100 |
|
3101 Rasterizer& rasterizer = context->m_rasterizer; |
|
3102 rasterizer.clear(); |
|
3103 |
|
3104 rasterizer.setScissoring(context->m_scissoring ? true : false); |
|
3105 if(context->m_scissoring) |
|
3106 rasterizer.setScissor(context->m_scissor); //throws bad_alloc |
|
3107 |
|
3108 PixelPipe& pixelPipe = context->m_pixelPipe; |
|
3109 pixelPipe.setTileFillColor(context->m_tileFillColor); |
|
3110 pixelPipe.setPaint((Paint*)context->m_fillPaint); |
|
3111 pixelPipe.setImageQuality(context->m_imageQuality); |
|
3112 pixelPipe.setBlendMode(context->m_blendMode); |
|
3113 pixelPipe.setRenderToMask(false); |
|
3114 pixelPipe.setDrawable(drawable); |
|
3115 pixelPipe.setMask(context->m_masking ? true : false); |
|
3116 pixelPipe.setColorTransform(context->m_colorTransform ? true : false, context->m_colorTransformValues); |
|
3117 const bool aa = context->m_renderingQuality == VG_RENDERING_QUALITY_NONANTIALIASED ? false : true; |
|
3118 rasterizer.setAntiAliasing(aa); |
|
3119 |
|
3120 Matrix3x3 surfaceToImageMatrix = userToSurfaceMatrix; |
|
3121 Matrix3x3 surfaceToPaintMatrix = userToSurfaceMatrix * context->m_fillPaintToUser; |
|
3122 if(surfaceToImageMatrix.invert() && surfaceToPaintMatrix.invert()) |
|
3123 { |
|
3124 VGImageMode imode = context->m_imageMode; |
|
3125 if(!surfaceToPaintMatrix.isAffine()) |
|
3126 imode = VG_DRAW_IMAGE_NORMAL; //if paint matrix is not affine, always use normal image mode |
|
3127 surfaceToPaintMatrix[2].set(0,0,1); //force affine |
|
3128 |
|
3129 pixelPipe.setImage(img, imode); |
|
3130 pixelPipe.setSurfaceToPaintMatrix(surfaceToPaintMatrix); |
|
3131 pixelPipe.setSurfaceToImageMatrix(surfaceToImageMatrix); |
|
3132 pixelPipe.prepareSpanUniforms(aa); |
|
3133 rasterizer.setup(0, 0, drawable->getWidth(), drawable->getHeight(), VG_EVEN_ODD, &pixelPipe); |
|
3134 |
|
3135 rasterizer.addEdge(Vector2(p0.x,p0.y), Vector2(p1.x,p1.y)); //throws bad_alloc |
|
3136 rasterizer.addEdge(Vector2(p1.x,p1.y), Vector2(p2.x,p2.y)); //throws bad_alloc |
|
3137 rasterizer.addEdge(Vector2(p2.x,p2.y), Vector2(p3.x,p3.y)); //throws bad_alloc |
|
3138 rasterizer.addEdge(Vector2(p3.x,p3.y), Vector2(p0.x,p0.y)); //throws bad_alloc |
|
3139 |
|
3140 rasterizer.fill(); //throws bad_alloc |
|
3141 } |
|
3142 return true; |
|
3143 } |
|
3144 |
|
3145 void RI_APIENTRY vgDrawImage(VGImage image) |
|
3146 { |
|
3147 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3148 RI_IF_ERROR(!context->isValidImage(image), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); |
|
3149 Image* img = (Image*)image; |
|
3150 RI_IF_ERROR(eglvgIsInUse(img), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
3151 |
|
3152 try |
|
3153 { |
|
3154 if(!drawImage(context, image, context->m_imageUserToSurface)) |
|
3155 { |
|
3156 RI_RETURN(RI_NO_RETVAL); |
|
3157 } |
|
3158 } |
|
3159 catch(std::bad_alloc) |
|
3160 { |
|
3161 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
3162 } |
|
3163 RI_RETURN(RI_NO_RETVAL); |
|
3164 } |
|
3165 |
|
3166 /*-------------------------------------------------------------------*//*! |
|
3167 * \brief |
|
3168 * \param |
|
3169 * \return |
|
3170 * \note |
|
3171 *//*-------------------------------------------------------------------*/ |
|
3172 |
|
3173 void RI_APIENTRY vgSetPixels(VGint dx, VGint dy, VGImage src, VGint sx, VGint sy, VGint width, VGint height) |
|
3174 { |
|
3175 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3176 RI_IF_ERROR(!context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); |
|
3177 RI_IF_ERROR(eglvgIsInUse((Image*)src), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
3178 RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3179 |
|
3180 Drawable* drawable = context->getCurrentDrawable(); |
|
3181 Array<OpenVGRI::Rectangle>* scissors = !context->m_scissoring ? NULL : &context->m_scissor; |
|
3182 if(!drawable) |
|
3183 { |
|
3184 RI_RETURN(RI_NO_RETVAL); //no EGL surface is current at the moment |
|
3185 } |
|
3186 try |
|
3187 { |
|
3188 drawable->getColorBuffer()->m_image->blit(context, (Image*)src, sx, sy, dx, dy, width, height, scissors, false); //throws bad_alloc |
|
3189 //drawable->getColorBuffer()->blit(*(Image*)src, sx, sy, dx, dy, width, height); //throws bad_alloc |
|
3190 } |
|
3191 catch(std::bad_alloc) |
|
3192 { |
|
3193 } |
|
3194 RI_RETURN(RI_NO_RETVAL); |
|
3195 } |
|
3196 |
|
3197 /*-------------------------------------------------------------------*//*! |
|
3198 * \brief |
|
3199 * \param |
|
3200 * \return |
|
3201 * \note |
|
3202 *//*-------------------------------------------------------------------*/ |
|
3203 |
|
3204 void RI_APIENTRY vgWritePixels(const void * data, VGint dataStride, VGImageFormat dataFormat, VGint dx, VGint dy, VGint width, VGint height) |
|
3205 { |
|
3206 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3207 RI_IF_ERROR(!isValidImageFormat(dataFormat), VG_UNSUPPORTED_IMAGE_FORMAT_ERROR, RI_NO_RETVAL); |
|
3208 RI_IF_ERROR(!data || !isAligned(data, dataFormat) || width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3209 Drawable* drawable = context->getCurrentDrawable(); |
|
3210 if(!drawable) |
|
3211 { |
|
3212 RI_RETURN(RI_NO_RETVAL); //no EGL surface is current at the moment |
|
3213 } |
|
3214 { |
|
3215 Array<OpenVGRI::Rectangle>* scissors = !context->m_scissoring ? NULL : &context->m_scissor; |
|
3216 Image input(Color::formatToDescriptor(dataFormat), width, height, dataStride, const_cast<RIuint8*>((const RIuint8*)data)); |
|
3217 input.addReference(); |
|
3218 try |
|
3219 { |
|
3220 drawable->getColorBuffer()->m_image->blit(context, &input, 0, 0, dx, dy, width, height, scissors, false); //throws bad_alloc |
|
3221 } |
|
3222 catch(std::bad_alloc) |
|
3223 { |
|
3224 // TEROP: out-of-mem? |
|
3225 } |
|
3226 input.removeReference(); |
|
3227 } |
|
3228 RI_RETURN(RI_NO_RETVAL); |
|
3229 } |
|
3230 |
|
3231 /*-------------------------------------------------------------------*//*! |
|
3232 * \brief |
|
3233 * \param |
|
3234 * \return |
|
3235 * \note |
|
3236 *//*-------------------------------------------------------------------*/ |
|
3237 |
|
3238 void RI_APIENTRY vgGetPixels(VGImage dst, VGint dx, VGint dy, VGint sx, VGint sy, VGint width, VGint height) |
|
3239 { |
|
3240 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3241 RI_IF_ERROR(!context->isValidImage(dst), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); |
|
3242 RI_IF_ERROR(eglvgIsInUse((Image*)dst), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
3243 RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3244 Drawable* drawable = context->getCurrentDrawable(); |
|
3245 if(!drawable) |
|
3246 { |
|
3247 RI_RETURN(RI_NO_RETVAL); //no EGL surface is current at the moment |
|
3248 } |
|
3249 try |
|
3250 { |
|
3251 ((Image*)dst)->blit(context, drawable->getColorBuffer()->m_image, sx, sy, dx, dy, width, height); //throws bad_alloc |
|
3252 } |
|
3253 catch(std::bad_alloc) |
|
3254 { |
|
3255 } |
|
3256 RI_RETURN(RI_NO_RETVAL); |
|
3257 } |
|
3258 |
|
3259 /*-------------------------------------------------------------------*//*! |
|
3260 * \brief |
|
3261 * \param |
|
3262 * \return |
|
3263 * \note |
|
3264 *//*-------------------------------------------------------------------*/ |
|
3265 |
|
3266 void RI_APIENTRY vgReadPixels(void* data, VGint dataStride, VGImageFormat dataFormat, VGint sx, VGint sy, VGint width, VGint height) |
|
3267 { |
|
3268 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3269 RI_IF_ERROR(!isValidImageFormat(dataFormat), VG_UNSUPPORTED_IMAGE_FORMAT_ERROR, RI_NO_RETVAL); |
|
3270 RI_IF_ERROR(!data || !isAligned(data, dataFormat) || width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3271 Drawable* drawable = context->getCurrentDrawable(); |
|
3272 if(!drawable) |
|
3273 { |
|
3274 RI_RETURN(RI_NO_RETVAL); //no EGL surface is current at the moment |
|
3275 } |
|
3276 { |
|
3277 Image output(Color::formatToDescriptor(dataFormat), width, height, dataStride, (RIuint8*)data); |
|
3278 output.addReference(); |
|
3279 try |
|
3280 { |
|
3281 output.blit(context, drawable->getColorBuffer()->m_image, sx, sy, 0, 0, width, height); //throws bad_alloc |
|
3282 } |
|
3283 catch(std::bad_alloc) |
|
3284 { |
|
3285 } |
|
3286 output.removeReference(); |
|
3287 } |
|
3288 RI_RETURN(RI_NO_RETVAL); |
|
3289 } |
|
3290 |
|
3291 /*-------------------------------------------------------------------*//*! |
|
3292 * \brief |
|
3293 * \param |
|
3294 * \return |
|
3295 * \note |
|
3296 *//*-------------------------------------------------------------------*/ |
|
3297 |
|
3298 void RI_APIENTRY vgCopyPixels(VGint dx, VGint dy, VGint sx, VGint sy, VGint width, VGint height) |
|
3299 { |
|
3300 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3301 RI_IF_ERROR(width <= 0 || height <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3302 Drawable* drawable = context->getCurrentDrawable(); |
|
3303 Array<OpenVGRI::Rectangle>* scissors = !context->m_scissoring ? NULL : &context->m_scissor; |
|
3304 if(!drawable) |
|
3305 { |
|
3306 RI_RETURN(RI_NO_RETVAL); //no EGL surface is current at the moment |
|
3307 } |
|
3308 try |
|
3309 { |
|
3310 drawable->getColorBuffer()->m_image->blit(context, drawable->getColorBuffer()->m_image, sx, sy, dx, dy, width, height, scissors, false); //throws bad_alloc |
|
3311 //drawable->getColorBuffer()->blit(drawable->getColorBuffer(), sx, sy, dx, dy, width, height); //throws bad_alloc |
|
3312 } |
|
3313 catch(std::bad_alloc) |
|
3314 { |
|
3315 } |
|
3316 RI_RETURN(RI_NO_RETVAL); |
|
3317 } |
|
3318 |
|
3319 /*-------------------------------------------------------------------*//*! |
|
3320 * \brief |
|
3321 * \param |
|
3322 * \return |
|
3323 * \note |
|
3324 *//*-------------------------------------------------------------------*/ |
|
3325 |
|
3326 void RI_APIENTRY vgColorMatrix(VGImage dst, VGImage src, const VGfloat * matrix) |
|
3327 { |
|
3328 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3329 RI_IF_ERROR(!context->isValidImage(dst) || !context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); |
|
3330 Image* d = (Image*)dst; |
|
3331 Image* s = (Image*)src; |
|
3332 RI_IF_ERROR(eglvgIsInUse(d) || eglvgIsInUse(s), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
3333 RI_IF_ERROR(d->overlaps(s), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3334 RI_IF_ERROR(!matrix || !isAligned(matrix,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3335 unsigned int channelMask = context->m_filterChannelMask & (VG_RED|VG_GREEN|VG_BLUE|VG_ALPHA); //undefined bits are ignored |
|
3336 |
|
3337 RIfloat m[20]; |
|
3338 for(int i=0;i<20;i++) |
|
3339 { |
|
3340 m[i] = inputFloat(matrix[i]); |
|
3341 } |
|
3342 try |
|
3343 { |
|
3344 d->colorMatrix(*s, m, context->m_filterFormatLinear ? true : false, context->m_filterFormatPremultiplied ? true : false, channelMask); |
|
3345 } |
|
3346 catch(std::bad_alloc) |
|
3347 { |
|
3348 } |
|
3349 RI_RETURN(RI_NO_RETVAL); |
|
3350 } |
|
3351 |
|
3352 /*-------------------------------------------------------------------*//*! |
|
3353 * \brief |
|
3354 * \param |
|
3355 * \return |
|
3356 * \note |
|
3357 *//*-------------------------------------------------------------------*/ |
|
3358 |
|
3359 void RI_APIENTRY vgConvolve(VGImage dst, VGImage src, VGint kernelWidth, VGint kernelHeight, VGint shiftX, VGint shiftY, const VGshort * kernel, VGfloat scale, VGfloat bias, VGTilingMode tilingMode) |
|
3360 { |
|
3361 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3362 RI_IF_ERROR(!context->isValidImage(dst) || !context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); |
|
3363 Image* d = (Image*)dst; |
|
3364 Image* s = (Image*)src; |
|
3365 RI_IF_ERROR(eglvgIsInUse(d) || eglvgIsInUse(s), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
3366 RI_IF_ERROR(d->overlaps(s), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3367 RI_IF_ERROR(!kernel || !isAligned(kernel,2) || kernelWidth <= 0 || kernelHeight <= 0 || kernelWidth > RI_MAX_KERNEL_SIZE || kernelHeight > RI_MAX_KERNEL_SIZE, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3368 RI_IF_ERROR(tilingMode < VG_TILE_FILL || tilingMode > VG_TILE_REFLECT, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3369 unsigned int channelMask = context->m_filterChannelMask & (VG_RED|VG_GREEN|VG_BLUE|VG_ALPHA); //undefined bits are ignored |
|
3370 try |
|
3371 { |
|
3372 d->convolve(*s, kernelWidth, kernelHeight, shiftX, shiftY, (const RIint16*)kernel, inputFloat(scale), inputFloat(bias), tilingMode, context->m_tileFillColor, context->m_filterFormatLinear ? true : false, context->m_filterFormatPremultiplied ? true : false, channelMask); |
|
3373 } |
|
3374 catch(std::bad_alloc) |
|
3375 { |
|
3376 } |
|
3377 RI_RETURN(RI_NO_RETVAL); |
|
3378 } |
|
3379 |
|
3380 /*-------------------------------------------------------------------*//*! |
|
3381 * \brief |
|
3382 * \param |
|
3383 * \return |
|
3384 * \note |
|
3385 *//*-------------------------------------------------------------------*/ |
|
3386 |
|
3387 void RI_APIENTRY vgSeparableConvolve(VGImage dst, VGImage src, VGint kernelWidth, VGint kernelHeight, VGint shiftX, VGint shiftY, const VGshort * kernelX, const VGshort * kernelY, VGfloat scale, VGfloat bias, VGTilingMode tilingMode) |
|
3388 { |
|
3389 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3390 RI_IF_ERROR(!context->isValidImage(dst) || !context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); |
|
3391 Image* d = (Image*)dst; |
|
3392 Image* s = (Image*)src; |
|
3393 RI_IF_ERROR(eglvgIsInUse(d) || eglvgIsInUse(s), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
3394 RI_IF_ERROR(d->overlaps(s), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3395 RI_IF_ERROR(!kernelX || !kernelY || !isAligned(kernelX,2) || !isAligned(kernelY,2) || kernelWidth <= 0 || kernelHeight <= 0 || kernelWidth > RI_MAX_SEPARABLE_KERNEL_SIZE || kernelHeight > RI_MAX_SEPARABLE_KERNEL_SIZE, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3396 RI_IF_ERROR(tilingMode < VG_TILE_FILL || tilingMode > VG_TILE_REFLECT, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3397 unsigned int channelMask = context->m_filterChannelMask & (VG_RED|VG_GREEN|VG_BLUE|VG_ALPHA); //undefined bits are ignored |
|
3398 try |
|
3399 { |
|
3400 d->separableConvolve(*s, kernelWidth, kernelHeight, shiftX, shiftY, (const RIint16*)kernelX, (const RIint16*)kernelY, |
|
3401 inputFloat(scale), inputFloat(bias), tilingMode, context->m_tileFillColor, context->m_filterFormatLinear ? true : false, |
|
3402 context->m_filterFormatPremultiplied ? true : false, channelMask); |
|
3403 } |
|
3404 catch(std::bad_alloc) |
|
3405 { |
|
3406 } |
|
3407 RI_RETURN(RI_NO_RETVAL); |
|
3408 } |
|
3409 |
|
3410 /*-------------------------------------------------------------------*//*! |
|
3411 * \brief |
|
3412 * \param |
|
3413 * \return |
|
3414 * \note |
|
3415 *//*-------------------------------------------------------------------*/ |
|
3416 |
|
3417 void RI_APIENTRY vgGaussianBlur(VGImage dst, VGImage src, VGfloat stdDeviationX, VGfloat stdDeviationY, VGTilingMode tilingMode) |
|
3418 { |
|
3419 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3420 RI_IF_ERROR(!context->isValidImage(dst) || !context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); |
|
3421 Image* d = (Image*)dst; |
|
3422 Image* s = (Image*)src; |
|
3423 RI_IF_ERROR(eglvgIsInUse(d) || eglvgIsInUse(s), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
3424 RI_IF_ERROR(d->overlaps(s), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3425 RIfloat sx = inputFloat(stdDeviationX); |
|
3426 RIfloat sy = inputFloat(stdDeviationY); |
|
3427 RI_IF_ERROR(sx <= 0.0f || sy <= 0.0f || sx > (RIfloat)RI_MAX_GAUSSIAN_STD_DEVIATION || sy > (RIfloat)RI_MAX_GAUSSIAN_STD_DEVIATION, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3428 RI_IF_ERROR(tilingMode < VG_TILE_FILL || tilingMode > VG_TILE_REFLECT, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3429 unsigned int channelMask = context->m_filterChannelMask & (VG_RED|VG_GREEN|VG_BLUE|VG_ALPHA); //undefined bits are ignored |
|
3430 try |
|
3431 { |
|
3432 d->gaussianBlur(*s, sx, sy, tilingMode, context->m_tileFillColor, context->m_filterFormatLinear ? true : false, |
|
3433 context->m_filterFormatPremultiplied ? true : false, channelMask); |
|
3434 } |
|
3435 catch(std::bad_alloc) |
|
3436 { |
|
3437 } |
|
3438 RI_RETURN(RI_NO_RETVAL); |
|
3439 } |
|
3440 |
|
3441 /*-------------------------------------------------------------------*//*! |
|
3442 * \brief |
|
3443 * \param |
|
3444 * \return |
|
3445 * \note |
|
3446 *//*-------------------------------------------------------------------*/ |
|
3447 |
|
3448 void RI_APIENTRY vgLookup(VGImage dst, VGImage src, const VGubyte * redLUT, const VGubyte * greenLUT, const VGubyte * blueLUT, const VGubyte * alphaLUT, VGboolean outputLinear, VGboolean outputPremultiplied) |
|
3449 { |
|
3450 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3451 RI_IF_ERROR(!context->isValidImage(dst) || !context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); |
|
3452 Image* d = (Image*)dst; |
|
3453 Image* s = (Image*)src; |
|
3454 RI_IF_ERROR(eglvgIsInUse(d) || eglvgIsInUse(s), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
3455 RI_IF_ERROR(d->overlaps(s), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3456 RI_IF_ERROR(!redLUT || !greenLUT || !blueLUT || !alphaLUT, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3457 unsigned int channelMask = context->m_filterChannelMask & (VG_RED|VG_GREEN|VG_BLUE|VG_ALPHA); //undefined bits are ignored |
|
3458 try |
|
3459 { |
|
3460 d->lookup(*s, (const RIuint8*)redLUT, (const RIuint8*)greenLUT, (const RIuint8*)blueLUT, (const RIuint8*)alphaLUT, |
|
3461 outputLinear ? true : false, outputPremultiplied ? true : false, context->m_filterFormatLinear ? true : false, |
|
3462 context->m_filterFormatPremultiplied ? true : false, channelMask); |
|
3463 } |
|
3464 catch(std::bad_alloc) |
|
3465 { |
|
3466 } |
|
3467 RI_RETURN(RI_NO_RETVAL); |
|
3468 } |
|
3469 |
|
3470 /*-------------------------------------------------------------------*//*! |
|
3471 * \brief |
|
3472 * \param |
|
3473 * \return |
|
3474 * \note |
|
3475 *//*-------------------------------------------------------------------*/ |
|
3476 |
|
3477 void RI_APIENTRY vgLookupSingle(VGImage dst, VGImage src, const VGuint * lookupTable, VGImageChannel sourceChannel, VGboolean outputLinear, VGboolean outputPremultiplied) |
|
3478 { |
|
3479 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3480 RI_IF_ERROR(!context->isValidImage(dst) || !context->isValidImage(src), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); |
|
3481 Image* d = (Image*)dst; |
|
3482 Image* s = (Image*)src; |
|
3483 RI_IF_ERROR(eglvgIsInUse(d) || eglvgIsInUse(s), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); |
|
3484 RI_IF_ERROR(d->overlaps(s), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3485 RI_IF_ERROR(!lookupTable || !isAligned(lookupTable,4), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3486 const Color::Descriptor& desc = s->getDescriptor(); |
|
3487 RI_ASSERT(Color::isValidDescriptor(desc)); |
|
3488 //give an error if src is in rgb format and the source channel is not valid |
|
3489 RI_IF_ERROR((!desc.isLuminance() && !desc.isAlphaOnly()) && (sourceChannel != VG_RED && sourceChannel != VG_GREEN && sourceChannel != VG_BLUE && sourceChannel != VG_ALPHA), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3490 unsigned int channelMask = context->m_filterChannelMask & (VG_RED|VG_GREEN|VG_BLUE|VG_ALPHA); //undefined bits are ignored |
|
3491 try |
|
3492 { |
|
3493 d->lookupSingle(*s, (const RIuint32*)lookupTable, sourceChannel, outputLinear ? true : false, outputPremultiplied ? true : false, |
|
3494 context->m_filterFormatLinear ? true : false, context->m_filterFormatPremultiplied ? true : false, channelMask); |
|
3495 } |
|
3496 catch(std::bad_alloc) |
|
3497 { |
|
3498 } |
|
3499 RI_RETURN(RI_NO_RETVAL); |
|
3500 } |
|
3501 |
|
3502 /*-------------------------------------------------------------------*//*! |
|
3503 * \brief |
|
3504 * \param |
|
3505 * \return |
|
3506 * \note |
|
3507 *//*-------------------------------------------------------------------*/ |
|
3508 |
|
3509 VGHardwareQueryResult RI_APIENTRY vgHardwareQuery(VGHardwareQueryType key, VGint setting) |
|
3510 { |
|
3511 RI_GET_CONTEXT(VG_HARDWARE_UNACCELERATED); |
|
3512 RI_IF_ERROR(key != VG_IMAGE_FORMAT_QUERY && key != VG_PATH_DATATYPE_QUERY, VG_ILLEGAL_ARGUMENT_ERROR, VG_HARDWARE_UNACCELERATED); |
|
3513 RI_IF_ERROR(key == VG_IMAGE_FORMAT_QUERY && !isValidImageFormat(setting), VG_ILLEGAL_ARGUMENT_ERROR, VG_HARDWARE_UNACCELERATED); |
|
3514 RI_IF_ERROR(key == VG_PATH_DATATYPE_QUERY && (setting < VG_PATH_DATATYPE_S_8 || setting > VG_PATH_DATATYPE_F), VG_ILLEGAL_ARGUMENT_ERROR, VG_HARDWARE_UNACCELERATED); |
|
3515 RI_RETURN(VG_HARDWARE_UNACCELERATED); |
|
3516 } |
|
3517 |
|
3518 /*-------------------------------------------------------------------*//*! |
|
3519 * \brief |
|
3520 * \param |
|
3521 * \return |
|
3522 * \note |
|
3523 *//*-------------------------------------------------------------------*/ |
|
3524 |
|
3525 const VGubyte * RI_APIENTRY vgGetString(VGStringID name) |
|
3526 { |
|
3527 static const VGubyte vendor[] = "Nokia"; |
|
3528 static const VGubyte renderer[] = {"OpenVG 1.1 Faster Reference Implementation May 13 2008"}; |
|
3529 static const VGubyte version[] = "1.1"; |
|
3530 static const VGubyte extensions[] = ""; |
|
3531 const VGubyte* r = NULL; |
|
3532 RI_GET_CONTEXT(NULL); |
|
3533 switch(name) |
|
3534 { |
|
3535 case VG_VENDOR: |
|
3536 r = vendor; |
|
3537 break; |
|
3538 case VG_RENDERER: |
|
3539 r = renderer; |
|
3540 break; |
|
3541 case VG_VERSION: |
|
3542 r = version; |
|
3543 break; |
|
3544 case VG_EXTENSIONS: |
|
3545 r = extensions; |
|
3546 break; |
|
3547 default: |
|
3548 break; |
|
3549 } |
|
3550 RI_RETURN(r); |
|
3551 } |
|
3552 |
|
3553 /*-------------------------------------------------------------------*//*! |
|
3554 * \brief |
|
3555 * \param |
|
3556 * \return |
|
3557 * \note |
|
3558 *//*-------------------------------------------------------------------*/ |
|
3559 |
|
3560 VGFont RI_APIENTRY vgCreateFont(VGint glyphCapacityHint) |
|
3561 { |
|
3562 RI_GET_CONTEXT(VG_INVALID_HANDLE); |
|
3563 RI_IF_ERROR(glyphCapacityHint < 0, VG_ILLEGAL_ARGUMENT_ERROR, VG_INVALID_HANDLE); |
|
3564 |
|
3565 Font* font = NULL; |
|
3566 try |
|
3567 { |
|
3568 font = RI_NEW(Font, (glyphCapacityHint)); //throws bad_alloc |
|
3569 RI_ASSERT(font); |
|
3570 context->m_fontManager->addResource(font, context); //throws bad_alloc |
|
3571 RI_RETURN((VGFont)font); |
|
3572 } |
|
3573 catch(std::bad_alloc) |
|
3574 { |
|
3575 RI_DELETE(font); |
|
3576 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
3577 RI_RETURN(VG_INVALID_HANDLE); |
|
3578 } |
|
3579 } |
|
3580 |
|
3581 /*-------------------------------------------------------------------*//*! |
|
3582 * \brief |
|
3583 * \param |
|
3584 * \return |
|
3585 * \note |
|
3586 *//*-------------------------------------------------------------------*/ |
|
3587 |
|
3588 void RI_APIENTRY vgDestroyFont(VGFont font) |
|
3589 { |
|
3590 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3591 RI_IF_ERROR(!context->isValidFont(font), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid font handle |
|
3592 |
|
3593 context->m_fontManager->removeResource((Font*)font); |
|
3594 |
|
3595 RI_RETURN(RI_NO_RETVAL); |
|
3596 } |
|
3597 |
|
3598 /*-------------------------------------------------------------------*//*! |
|
3599 * \brief |
|
3600 * \param |
|
3601 * \return |
|
3602 * \note |
|
3603 *//*-------------------------------------------------------------------*/ |
|
3604 |
|
3605 void RI_APIENTRY vgSetGlyphToPath(VGFont font, VGuint glyphIndex, VGPath path, VGboolean isHinted, const VGfloat glyphOrigin[2], const VGfloat escapement[2]) |
|
3606 { |
|
3607 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3608 RI_IF_ERROR(!context->isValidFont(font), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid font handle |
|
3609 RI_IF_ERROR(path != VG_INVALID_HANDLE && !context->isValidPath(path), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid path handle |
|
3610 RI_IF_ERROR(!glyphOrigin || !escapement || !isAligned(glyphOrigin,sizeof(VGfloat)) || !isAligned(escapement,sizeof(VGfloat)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3611 Font* f = (Font*)font; |
|
3612 |
|
3613 try |
|
3614 { |
|
3615 f->setGlyphToPath(glyphIndex, path, isHinted ? true : false, Vector2(inputFloat(glyphOrigin[0]), inputFloat(glyphOrigin[1])), Vector2(inputFloat(escapement[0]), inputFloat(escapement[1]))); |
|
3616 } |
|
3617 catch(std::bad_alloc) |
|
3618 { |
|
3619 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
3620 } |
|
3621 RI_RETURN(RI_NO_RETVAL); |
|
3622 } |
|
3623 |
|
3624 /*-------------------------------------------------------------------*//*! |
|
3625 * \brief |
|
3626 * \param |
|
3627 * \return |
|
3628 * \note |
|
3629 *//*-------------------------------------------------------------------*/ |
|
3630 |
|
3631 void RI_APIENTRY vgSetGlyphToImage(VGFont font, VGuint glyphIndex, VGImage image, const VGfloat glyphOrigin[2], const VGfloat escapement[2]) |
|
3632 { |
|
3633 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3634 RI_IF_ERROR(!context->isValidFont(font), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid font handle |
|
3635 if(image != VG_INVALID_HANDLE) |
|
3636 { |
|
3637 RI_IF_ERROR(!context->isValidImage(image), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid image handle |
|
3638 RI_IF_ERROR(eglvgIsInUse((Image*)image), VG_IMAGE_IN_USE_ERROR, RI_NO_RETVAL); //image in use |
|
3639 } |
|
3640 RI_IF_ERROR(!glyphOrigin || !escapement || !isAligned(glyphOrigin,sizeof(VGfloat)) || !isAligned(escapement,sizeof(VGfloat)), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3641 Font* f = (Font*)font; |
|
3642 |
|
3643 try |
|
3644 { |
|
3645 f->setGlyphToImage(glyphIndex, image, Vector2(inputFloat(glyphOrigin[0]), inputFloat(glyphOrigin[1])), Vector2(inputFloat(escapement[0]), inputFloat(escapement[1]))); |
|
3646 } |
|
3647 catch(std::bad_alloc) |
|
3648 { |
|
3649 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
3650 } |
|
3651 RI_RETURN(RI_NO_RETVAL); |
|
3652 } |
|
3653 |
|
3654 /*-------------------------------------------------------------------*//*! |
|
3655 * \brief |
|
3656 * \param |
|
3657 * \return |
|
3658 * \note |
|
3659 *//*-------------------------------------------------------------------*/ |
|
3660 |
|
3661 void RI_APIENTRY vgClearGlyph(VGFont font, VGuint glyphIndex) |
|
3662 { |
|
3663 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3664 RI_IF_ERROR(!context->isValidFont(font), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid font handle |
|
3665 Font* f = (Font*)font; |
|
3666 Font::Glyph* g = f->findGlyph(glyphIndex); |
|
3667 RI_IF_ERROR(!g, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //glyphIndex not defined |
|
3668 |
|
3669 f->clearGlyph(g); |
|
3670 |
|
3671 RI_RETURN(RI_NO_RETVAL); |
|
3672 } |
|
3673 |
|
3674 /*-------------------------------------------------------------------*//*! |
|
3675 * \brief |
|
3676 * \param |
|
3677 * \return |
|
3678 * \note |
|
3679 *//*-------------------------------------------------------------------*/ |
|
3680 |
|
3681 void RI_APIENTRY vgDrawGlyph(VGFont font, VGuint glyphIndex, VGbitfield paintModes, VGboolean allowAutoHinting) |
|
3682 { |
|
3683 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3684 RI_IF_ERROR(!context->isValidFont(font), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid font handle |
|
3685 RI_IF_ERROR(paintModes & ~(VG_FILL_PATH | VG_STROKE_PATH), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //invalid paint mode |
|
3686 Font* f = (Font*)font; |
|
3687 Font::Glyph* g = f->findGlyph(glyphIndex); |
|
3688 RI_IF_ERROR(!g, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //glyphIndex not defined |
|
3689 RI_UNREF(allowAutoHinting); //RI doesn't implement autohinting |
|
3690 |
|
3691 try |
|
3692 { |
|
3693 if(paintModes) |
|
3694 { |
|
3695 Matrix3x3 userToSurfaceMatrix = context->m_glyphUserToSurface; |
|
3696 Vector2 t = context->m_glyphOrigin - g->m_origin; |
|
3697 Matrix3x3 n(1, 0, t.x, |
|
3698 0, 1, t.y, |
|
3699 0, 0, 1 ); |
|
3700 userToSurfaceMatrix *= n; |
|
3701 userToSurfaceMatrix[2].set(0,0,1); //force affinity |
|
3702 |
|
3703 bool ret = true; |
|
3704 eglvgLockSurface(0, 1); |
|
3705 if(g->m_image != VG_INVALID_HANDLE) |
|
3706 ret = drawImage(context, g->m_image, userToSurfaceMatrix); |
|
3707 else if(g->m_path != VG_INVALID_HANDLE) |
|
3708 ret = drawPath(context, g->m_path, userToSurfaceMatrix, paintModes); |
|
3709 eglvgUnlockSurface(); |
|
3710 if(!ret) |
|
3711 { |
|
3712 RI_RETURN(RI_NO_RETVAL); |
|
3713 } |
|
3714 } |
|
3715 |
|
3716 context->m_glyphOrigin += g->m_escapement; |
|
3717 context->m_inputGlyphOrigin = context->m_glyphOrigin; |
|
3718 } |
|
3719 catch(std::bad_alloc) |
|
3720 { |
|
3721 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
3722 } |
|
3723 |
|
3724 RI_RETURN(RI_NO_RETVAL); |
|
3725 } |
|
3726 |
|
3727 /*-------------------------------------------------------------------*//*! |
|
3728 * \brief |
|
3729 * \param |
|
3730 * \return |
|
3731 * \note |
|
3732 *//*-------------------------------------------------------------------*/ |
|
3733 |
|
3734 void RI_APIENTRY vgDrawGlyphs(VGFont font, VGint glyphCount, const VGuint *glyphIndices, const VGfloat *adjustments_x, const VGfloat *adjustments_y, VGbitfield paintModes, VGboolean allowAutoHinting) |
|
3735 { |
|
3736 RI_GET_CONTEXT(RI_NO_RETVAL); |
|
3737 RI_IF_ERROR(!context->isValidFont(font), VG_BAD_HANDLE_ERROR, RI_NO_RETVAL); //invalid font handle |
|
3738 RI_IF_ERROR(!glyphIndices || !isAligned(glyphIndices, sizeof(VGuint)) || glyphCount <= 0, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3739 RI_IF_ERROR((adjustments_x && !isAligned(adjustments_x, sizeof(VGfloat))) || (adjustments_y && !isAligned(adjustments_y, sizeof(VGfloat))), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); |
|
3740 RI_IF_ERROR(paintModes & ~(VG_FILL_PATH | VG_STROKE_PATH), VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //invalid paint mode |
|
3741 Font* f = (Font*)font; |
|
3742 for(int i=0;i<glyphCount;i++) |
|
3743 { |
|
3744 Font::Glyph* g = f->findGlyph(glyphIndices[i]); |
|
3745 RI_IF_ERROR(!g, VG_ILLEGAL_ARGUMENT_ERROR, RI_NO_RETVAL); //glyphIndex not defined |
|
3746 } |
|
3747 RI_UNREF(allowAutoHinting); //RI doesn't implement autohinting |
|
3748 |
|
3749 try |
|
3750 { |
|
3751 for(int i=0;i<glyphCount;i++) |
|
3752 { |
|
3753 Font::Glyph* g = f->findGlyph(glyphIndices[i]); |
|
3754 |
|
3755 if(paintModes) |
|
3756 { |
|
3757 Matrix3x3 userToSurfaceMatrix = context->m_glyphUserToSurface; |
|
3758 Vector2 t = context->m_glyphOrigin - g->m_origin; |
|
3759 Matrix3x3 n(1, 0, t.x, |
|
3760 0, 1, t.y, |
|
3761 0, 0, 1 ); |
|
3762 userToSurfaceMatrix *= n; |
|
3763 userToSurfaceMatrix[2].set(0,0,1); //force affinity |
|
3764 |
|
3765 bool ret = true; |
|
3766 if(g->m_image != VG_INVALID_HANDLE) |
|
3767 ret = drawImage(context, g->m_image, userToSurfaceMatrix); |
|
3768 else if(g->m_path != VG_INVALID_HANDLE) |
|
3769 ret = drawPath(context, g->m_path, userToSurfaceMatrix, paintModes); |
|
3770 if(!ret) |
|
3771 { |
|
3772 RI_RETURN(RI_NO_RETVAL); |
|
3773 } |
|
3774 } |
|
3775 |
|
3776 context->m_glyphOrigin += g->m_escapement; |
|
3777 if(adjustments_x) |
|
3778 context->m_glyphOrigin.x += inputFloat(adjustments_x[i]); |
|
3779 if(adjustments_y) |
|
3780 context->m_glyphOrigin.y += inputFloat(adjustments_y[i]); |
|
3781 context->m_inputGlyphOrigin = context->m_glyphOrigin; |
|
3782 } |
|
3783 } |
|
3784 catch(std::bad_alloc) |
|
3785 { |
|
3786 context->setError(VG_OUT_OF_MEMORY_ERROR); |
|
3787 } |
|
3788 RI_RETURN(RI_NO_RETVAL); |
|
3789 } |
|
3790 |
|
3791 VGint vgePathCoordsSizeInBytes(VGPath path, VGint startIndex, VGint numSegments) |
|
3792 { |
|
3793 RI_GET_CONTEXT( 0 ); |
|
3794 RI_IF_ERROR(!context->isValidPath(path), VG_BAD_HANDLE_ERROR, 0); |
|
3795 VGint ret = ((OpenVGRI::Path*)path)->coordsSizeInBytes( startIndex, numSegments ); |
|
3796 RI_RETURN(ret); |
|
3797 } |
|
3798 |
|
3799 |
|
3800 VGImage vgCreateEGLImageTargetKHR(VGeglImageKHR image) |
|
3801 { |
|
3802 #if defined(USE_FULL_EGL) |
|
3803 RI_GET_CONTEXT( 0 ); |
|
3804 VGImage ret; |
|
3805 OpenVGRI::Color::Descriptor desc; |
|
3806 OpenVGRI::RIuint8* data; |
|
3807 // Get data for VGImage |
|
3808 int width; |
|
3809 int height; |
|
3810 int stride; |
|
3811 |
|
3812 eglvgGetImageDescriptor( image, desc, width, height, stride ); |
|
3813 // There is some error. |
|
3814 // EGLImage is null or EGLImage target is EGL_VG_PARENT_IMAGE_KHR. |
|
3815 RI_IF_ERROR(!width || !height || !stride, VG_ILLEGAL_ARGUMENT_ERROR, NULL); |
|
3816 // Data is created in EGLImage class. |
|
3817 data = (OpenVGRI::RIuint8*)eglvgGetImageData( image ); |
|
3818 // Create VGImage |
|
3819 // allowedQuality = VG_IMAGE_QUALITY_NONANTIALIASED | VG_IMAGE_QUALITY_FASTER | VG_IMAGE_QUALITY_BETTER |
|
3820 ret = vgCreateImage( desc.vgFormat, width, height, VG_IMAGE_QUALITY_NONANTIALIASED ); |
|
3821 // If VGImage is not created raise error and return null |
|
3822 RI_IF_ERROR(!ret, VG_UNSUPPORTED_IMAGE_FORMAT_ERROR, NULL); |
|
3823 // Set data for VGImage. |
|
3824 // This will copy that data-object. |
|
3825 vgImageSubData( ret, |
|
3826 data, |
|
3827 stride, |
|
3828 desc.vgFormat, |
|
3829 0, |
|
3830 0, |
|
3831 width, |
|
3832 height); |
|
3833 // Return VGImage |
|
3834 RI_RETURN(ret); |
|
3835 #else |
|
3836 (void)image; |
|
3837 return VG_INVALID_HANDLE; |
|
3838 #endif //USE_FULL_EGL |
|
3839 } |