1 /****************************************************************************
2 *
3 * Copyright 2012 - 2021 Vivante Corporation, Santa Clara, California.
4 * All Rights Reserved.
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining
7 * a copy of this software and associated documentation files (the
8 * 'Software'), to deal in the Software without restriction, including
9 * without limitation the rights to use, copy, modify, merge, publish,
10 * distribute, sub license, and/or sell copies of the Software, and to
11 * permit persons to whom the Software is furnished to do so, subject
12 * to the following conditions:
13 *
14 * The above copyright notice and this permission notice (including the
15 * next paragraph) shall be included in all copies or substantial
16 * portions of the Software.
17 *
18 * THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
19 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
20 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
21 * IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
22 * CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
23 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
24 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
25 *
26 *****************************************************************************/
27
28 #include "elm_precom.h"
29 #include "elm_os.h"
30 #include "vg_lite_text.h"
31 #include "vft_debug.h"
32 #include "elm_headers.h"
33
34 #if (VG_RENDER_TEXT==1)
35 #include "elm_text.h"
36 #endif /* VG_RENDER_TEXT */
37
38 #if RTOS
39 #define BASE_ADDRESS_ALIGNMENT 32
40 #else
41 #define BASE_ADDRESS_ALIGNMENT 4
42 # endif
43 /* #define ENABLE_ELM_CRATE_OBJECT_FROM_FILE */
44
45 /*
46 * ANSI APIs are missing so application can use ElmCreateObjectFromData
47 * This simplifies things since file can be from FATFS, NOR Flash buffer etc.
48 */
49
50 #if (RTOS && DDRLESS) || BAREMETAL
51 /* Find some free objects, return the first index,
52 * and mark the bits as 1 (allocated).
53 * Params:
54 * free_map: the map bits of the objects where 0 is free and 1 is allocated;
55 * count : the element count of free_map[];
56 * obj_count:how many objects to allocate from the pool.
57 *
58 * Return:
59 * The free index of the object in the pool.
60 * */
get_free_objects(int32_t free_map[],int count,int obj_count)61 int get_free_objects(int32_t free_map[], int count, int obj_count)
62 {
63 int i, j;
64 int result = -1;
65 int counter = 0;
66 int bit_count = 0;
67 int32_t bits;
68
69 /* Find a free bit. */
70 for (i = 0; i < count; i++) {
71 bits = free_map[i];
72
73 for (j = 0; j < 32; j++) {
74 //Increase the bit counter.
75 bit_count++;
76
77 if ((bits & 0x80000000) == 0) {
78 //Free bit is found. then count available free bits.
79 counter++;
80 }
81 else {
82 //Free bit is not found, reset the counter.
83 counter = 0;
84 }
85
86 //Check to see whether enough bits are found.
87 if (counter >= obj_count) {
88 result = bit_count - counter;
89
90 //Get out of the two loops.
91 i = count;
92 break;
93 }
94
95 //Shift to next bit.
96 bits <<= 1;
97 }
98 }
99
100 /* Mark the bits as allocated if OK. */
101 if (result > -1) {
102 int bits_set = 1;
103 int bit_offset = result % 32;
104 bit_count = result / 32;
105
106 while (obj_count > 0) {
107 bits_set = ~(0xffffffff << (32 - bit_offset));
108 if (obj_count <= 32 - bit_offset) {
109 //Done.
110 bits_set = bits_set & (0xffffffff << (32 - bit_offset - obj_count));
111 free_map[bit_count] |= bits_set;
112 break;
113 }
114 free_map[bit_count] |= bits_set;
115
116 //Go to next map element.
117 obj_count -= (32 - bit_offset);
118 bit_count++;
119 bit_offset = 0;
120 }
121 }
122
123 return result;
124 }
125
126 /* When an object is "freed", mark the corresponding bits to 0. */
mark_free_object(int32_t free_map[],int object)127 void mark_free_object(int32_t free_map[], int object)
128 {
129 int index, offset;
130
131 index = object / 32;
132 offset = object % 32;
133
134 free_map[index] &= ~(1 << (31 - offset));
135 }
136
137 /* Check whether an object (with given index) allocated or not. */
object_exists(int32_t free_map[],int index)138 int object_exists(int32_t free_map[], int index)
139 {
140 int32_t bits;
141 int offset = index % 32;
142 index /= 32;
143
144 bits = ~(1 << (31 - offset));
145
146 if (free_map[index] & bits) {
147 return 1;
148 }
149 else {
150 return 0;
151 }
152 }
153
154 /* Allocate an EVO object from pool. */
alloc_evo(int count)155 static el_Obj_EVO * alloc_evo(int count)
156 {
157 elm_tls_t* elm_tls;
158 int index;
159 el_Obj_EVO *object = NULL;
160
161 elm_tls = (elm_tls_t *) elm_os_get_tls();
162 if (elm_tls == NULL)
163 return NULL;
164
165 index = get_free_objects(elm_tls->gContext.objmap_evo, COUNT_OF(elm_tls->gContext.objmap_evo), count);
166
167 if (index > -1) {
168 object = &elm_tls->gContext.objpool_evo[index];
169 elm_tls->gContext.objcounter_evo += count;
170 for (; count > 0; count--) {
171 object[count - 1].object.index = index + count - 1;
172 }
173 }
174
175 return object;
176 }
177
178 /* Allocate an EBO object from pool. */
alloc_ebo()179 static el_Obj_EBO * alloc_ebo()
180 {
181 elm_tls_t* elm_tls;
182 int index;
183 el_Obj_EBO *object = NULL;
184
185 elm_tls = (elm_tls_t *) elm_os_get_tls();
186 if (elm_tls == NULL)
187 return NULL;
188
189 index = get_free_objects(elm_tls->gContext.objmap_ebo, COUNT_OF(elm_tls->gContext.objmap_ebo), 1);
190
191 if (index > -1) {
192 object = &elm_tls->gContext.objpool_ebo[index];
193 object->object.index = index;
194 elm_tls->gContext.objcounter_ebo++;
195 }
196
197 return object;
198 }
199
200 /* Allocate an EGO object from pool. */
alloc_ego()201 static el_Obj_Group * alloc_ego()
202 {
203 elm_tls_t* elm_tls;
204 int index;
205 el_Obj_Group *object = NULL;
206
207 elm_tls = (elm_tls_t *) elm_os_get_tls();
208 if (elm_tls == NULL)
209 return NULL;
210
211 index = get_free_objects(elm_tls->gContext.objmap_group, COUNT_OF(elm_tls->gContext.objmap_group), 1);
212
213 if (index > -1) {
214 object = &elm_tls->gContext.objpool_group[index];
215 object->object.index = index;
216 elm_tls->gContext.objcounter_group++;
217 }
218
219 return object;
220 }
221
222 /* Mark an EGO object as free: insert it into the free list. */
free_ego(el_Obj_Group * object)223 static void free_ego(el_Obj_Group *object)
224 {
225 elm_tls_t* elm_tls;
226 elm_tls = (elm_tls_t *) elm_os_get_tls();
227 if (elm_tls == NULL)
228 return NULL;
229
230 mark_free_object(elm_tls->gContext.objmap_group, elm_tls->object->object.index);
231 elm_tls->gContext.objcounter_group--;
232 }
233
234 /* Allocate a grad object from pool. */
alloc_grad()235 static el_Obj_Grad * alloc_grad()
236 {
237 elm_tls_t* elm_tls;
238 int index;
239 el_Obj_Grad *object = NULL;
240
241 elm_tls = (elm_tls_t *) elm_os_get_tls();
242 if (elm_tls == NULL)
243 return NULL;
244
245 index = get_free_objects(elm_tls->gContext.objmap_grad, COUNT_OF(elm_tls->gContext.objmap_grad), 1);
246
247 if (index > -1) {
248 object = &elm_tls->gContext.objpool_grad[index];
249 object->object.index = index;
250 elm_tls->gContext.objcounter_grad++;
251 }
252
253 return object;
254 }
255
256 #endif
257 /* Internal Implementations *******************************/
deref_object(el_Object * object)258 int deref_object(el_Object *object)
259 {
260 object->reference--;
261 return object->reference;
262 }
263
ref_object(el_Object * object)264 int ref_object(el_Object *object)
265 {
266 object->reference++;
267 return object->reference;
268 }
269
add_object(el_Object * object)270 int add_object(el_Object *object)
271 {
272 elm_tls_t* elm_tls;
273 elm_tls = (elm_tls_t *) elm_os_get_tls();
274 if (elm_tls == NULL)
275 return 0;
276 #if (RTOS && DDRLESS) || BAREMETAL
277 /* Assign handle. */
278 object->handle = elm_tls->gContext.currentHandle++;
279 return 1;
280 #else
281 int result = 1;
282 el_ObjList *list = NULL;
283
284 /* Assign handle. */
285 object->handle = elm_tls->gContext.currentHandle++;
286
287 /* Get the list slot. */
288 list = OBJECT_SLOT(object->handle);
289 if (list == NULL) {
290 list = (el_ObjList *) elm_alloc(1, sizeof(el_ObjList));
291 if ( list == NULL ) {
292 return 0; /* Memory allocation failed */
293 }
294 #ifdef ENABLE_STRICT_DEBUG_MEMSET
295 memset(list, 0, sizeof(el_ObjList));
296 #endif
297
298 OBJECT_SLOT(object->handle) = list;
299
300 list->object = object;
301 list->next = NULL;
302
303 return 1;
304 }
305
306 /* Insert the object. */
307 while (list->next != NULL) {
308 list = list->next;
309 }
310 list->next = (el_ObjList *) elm_alloc(1, sizeof(el_ObjList));
311 if ( list->next == NULL ) {
312 return 0; /* Memory allocation failed */
313 }
314 #ifdef ENABLE_STRICT_DEBUG_MEMSET
315 memset(list->next, 0, sizeof(el_ObjList));
316 #endif
317 list = list->next;
318 list->object = object;
319 list->next = NULL;
320
321 return result;
322 #endif
323 }
324
remove_object(el_Object * object)325 int remove_object(el_Object *object)
326 {
327 elm_tls_t* elm_tls;
328 elm_tls = (elm_tls_t *) elm_os_get_tls();
329 if (elm_tls == NULL)
330 return 0;
331
332 int result = 0;
333 #if (!(RTOS && DDRLESS)) && (!BAREMETAL)
334 el_ObjList *list = NULL, *node = NULL;
335
336 // Get the list slot.
337 list = OBJECT_SLOT(object->handle);
338
339 // Invalid.
340 if (list == NULL)
341 return 0;
342
343 // Find the object.
344 if (list->object == object) {
345 OBJECT_SLOT(object->handle) = list->next;
346 elm_free(list);
347 return 1;
348 }
349
350 while (list->next != NULL) {
351 if (list->next->object == object) {
352 node = list->next;
353 list->next = list->next->next;
354 elm_free(node);
355 return 1;
356 }
357 list = list->next;
358 }
359 #endif
360
361 return result;
362 }
363
get_object(ElmHandle handle)364 el_Object *get_object(ElmHandle handle)
365 {
366 elm_tls_t* elm_tls;
367 el_Object *object = NULL;
368
369 elm_tls = (elm_tls_t *) elm_os_get_tls();
370 if (elm_tls == NULL)
371 return NULL;
372
373 #if (RTOS && DDRLESS) || BAREMETAL
374 int i;
375 for (i = 0; i < OBJCOUNT_EVO; i++) {
376 if (object_exists(elm_tls->gContext.objmap_evo, i)) {
377 if (elm_tls->gContext.objpool_evo[i].object.handle == handle) {
378 object = (el_Object *)&elm_tls->gContext.objpool_evo[i];
379 return object;
380 }
381 }
382 }
383 for (i = 0; i < OBJCOUNT_EBO; i++) {
384 if (object_exists(elm_tls->gContext.objmap_ebo, i)) {
385 if (elm_tls->gContext.objpool_ebo[i].object.handle == handle) {
386 object = (el_Object *)&elm_tls->gContext.objpool_ebo[i];
387 return object;
388 }
389 }
390 }
391 for (i = 0; i < OBJCOUNT_GRAD; i++) {
392 if (object_exists(elm_tls->gContext.objmap_grad, i)) {
393 if (elm_tls->gContext.objpool_grad[i].object.handle == handle) {
394 object = (el_Object *)&elm_tls->gContext.objpool_grad[i];
395 return object;
396 }
397 }
398 }
399 for (i = 0; i < OBJCOUNT_GROUP; i++) {
400 if (object_exists(elm_tls->gContext.objmap_group, i)) {
401 if (elm_tls->gContext.objpool_group[i].object.handle == handle) {
402 object = (el_Object *)&elm_tls->gContext.objpool_group[i];
403 return object;
404 }
405 }
406 }
407 #else
408 el_ObjList *list = NULL;
409
410 // Get the slot.
411 list = OBJECT_SLOT(handle);
412
413 // Find the object.
414 while (list != NULL) {
415 if ((list->object != NULL) &&
416 (list->object->handle == handle)) {
417 object = list->object;
418 return object;
419 }
420 list = list->next;
421 }
422 #endif
423
424 DEBUG_ASSERT(0, "Unknown object");
425 return NULL;
426 }
427
428 #if (RTOS && DDRLESS) || BAREMETAL
free_grad(el_Obj_Grad * object)429 static void free_grad(el_Obj_Grad *object)
430 {
431 elm_tls_t* elm_tls;
432 elm_tls = (elm_tls_t *) elm_os_get_tls();
433 if (elm_tls != NULL) {
434 mark_free_object(elm_tls->gContext.objmap_grad, object->object.index);
435 elm_tls->gContext.objcounter_grad--;
436 }
437 }
438 #endif
439
440 /* Destroy an evo object data. */
destroy_evo(el_Obj_EVO * evo)441 int destroy_evo(el_Obj_EVO *evo)
442 {
443 elm_tls_t* elm_tls;
444 elm_tls = (elm_tls_t *) elm_os_get_tls();
445 if (elm_tls == NULL)
446 return 0;
447
448 #if (RTOS && DDRLESS) || BAREMETAL
449 mark_free_object(elm_tls->gContext.objmap_evo, evo->object.index);
450 elm_tls->gContext.objcounter_evo--;
451 free_grad(evo->defaultAttrib.paint.grad);
452 #else
453
454 if ( evo->defaultAttrib.paint.type == ELM_PAINT_TEXT ) {
455 #if (VG_RENDER_TEXT==1)
456 _unload_text(evo);
457 #else
458 ;
459 #endif /* VG_RENDER_TEXT */
460 } else {
461 /* TODO: EVO destroy not done yet. */
462 if (evo->defaultAttrib.paint.grad != NULL) {
463 vg_lite_clear_grad(&evo->defaultAttrib.paint.grad->data.grad);
464 elm_free(evo->defaultAttrib.paint.grad);
465 evo->defaultAttrib.paint.grad = NULL;
466 }
467
468 if (evo->data.path.path != NULL) {
469 vg_lite_clear_path(&evo->data.path);
470 elm_free(evo->data.path.path);
471 evo->data.path.path = NULL;
472 }
473 }
474
475 remove_object(&evo->object);
476 #endif
477
478 #if (VG_RENDER_TEXT==1)
479 destroy_font_data();
480 #endif /* VG_RENDER_TEXT */
481 return 1;
482 }
483
484 /* Destroy an ego object data. */
destroy_ego(el_Obj_Group * ego)485 int destroy_ego(el_Obj_Group *ego)
486 {
487 elm_tls_t* elm_tls;
488 elm_tls = (elm_tls_t *) elm_os_get_tls();
489 if(elm_tls == NULL)
490 return 0;
491
492 #if (RTOS && DDRLESS) || BAREMETAL
493 mark_free_object(elm_tls->gContext.objmap_group, ego->object.index);
494 elm_tls->gContext.objcounter_group--;
495 #else
496 int i;
497 for (i = 0; i < ego->group.count; i++)
498 {
499 destroy_evo(&ego->group.objects[i]);
500 }
501 elm_free(ego->group.objects);
502 elm_free(ego);
503 #endif
504
505 #if (VG_RENDER_TEXT==1)
506 destroy_font_data();
507 #endif /* VG_RENDER_TEXT */
508 return 1;
509 }
510
511 /* Destroy an ebo object data. */
destroy_ebo(el_Obj_EBO * ebo)512 int destroy_ebo(el_Obj_EBO *ebo)
513 {
514 elm_tls_t* elm_tls;
515 elm_tls = (elm_tls_t *) elm_os_get_tls();
516 if(elm_tls == NULL)
517 return 0;
518
519 #if (RTOS && DDRLESS) || BAREMETAL
520 mark_free_object(elm_tls->gContext.objmap_ebo, ebo->object.index);
521 elm_tls->gContext.objcounter_ebo--;
522 #else
523 if ( ebo != NULL && ebo->data.buffer.handle != NULL) {
524 vg_lite_free(&ebo->data.buffer);
525 }
526 elm_free(ebo);
527 #endif
528 return 1;
529 }
530
531 /* Destroy an object.
532 return:
533 -1: any error;
534 0: destroyed when reference count is 0;
535 1: decreased reference count but still > 0.
536 */
destroy_object(ElmHandle handle)537 int destroy_object(ElmHandle handle)
538 {
539 el_Object *object = NULL;
540 int ref_count = 0;
541
542 object = get_object(handle);
543
544 // No such object.
545 if (object == NULL) {
546 DEBUG_ASSERT(0, "No such object");
547 return -1;
548 }
549
550 // Dereference object, and destroy if it's no more referred.
551 ref_count = deref_object(object);
552 if (ref_count == 0) {
553 remove_object(object);
554
555 switch (object->type) {
556 case ELM_OBJECT_TYPE_EVO:
557 destroy_evo((el_Obj_EVO *)object);
558 elm_free(object);
559 break;
560
561 case ELM_OBJECT_TYPE_EGO:
562 destroy_ego((el_Obj_Group *) object);
563 break;
564
565 case ELM_OBJECT_TYPE_EBO:
566 destroy_ebo((el_Obj_EBO *) object);
567 break;
568
569 default:
570 DEBUG_ASSERT(0, "Unknow object type");
571 break;
572 }
573 }
574
575 return 1;
576 }
577
_init_transform(el_Transform * transform)578 void _init_transform(el_Transform *transform)
579 {
580 int i = 0;
581 transform->rotate = 0.0f;
582 for (i = 0;i < 2; i++)
583 {
584 transform->scale[i] = 1.0f;
585 transform->translate[i] = 0.0f;
586 }
587 vg_lite_identity(&transform->matrix);
588 }
589
590 /* Static functions. *************************************************/
591
592 /* Get the specified vector object in a group. */
_get_evo(el_Obj_Group * group,int32_t id)593 static el_Obj_EVO* _get_evo(el_Obj_Group *group, int32_t id)
594 {
595 if ((id >= group->group.count) ||
596 (id < 0)){
597 return (el_Obj_EVO*)NULL;
598 }
599 else {
600 return (el_Obj_EVO*)(group->group.objects + id);
601 }
602 }
603
604 #if (VG_RENDER_TEXT==1)
_load_font(uint8_t * data,unsigned size)605 static int _load_font(uint8_t *data,
606 unsigned size)
607 {
608 ElmHandle ret = ELM_NULL_HANDLE;
609 el_Font_Header *font_header = (el_Font_Header *)data;
610
611
612 if (font_header->size_font_block != size)
613 return ret;
614
615 return _load_font_data(data);
616 }
617
_load_text(uint8_t * data,unsigned size,el_Obj_EVO * evo)618 static ElmHandle _load_text(uint8_t *data,
619 unsigned size,
620 el_Obj_EVO *evo)
621 {
622 ElmHandle ret = ELM_NULL_HANDLE;
623 el_Text_Header *text_header = (el_Text_Header *)data;
624
625
626 if (text_header->size_text_block != size)
627 return ret;
628
629 return _load_text_data(data, evo);
630 }
631 #endif /* VG_RENDER_TEXT */
632
633 #if (defined(__ICCARM__))
634 /*
635 * Disable the unaligned structure attribute warning. Due to the packed data
636 * structures used to interpret ELM objects data the IAR compiler issues a
637 * number of warnings that certain attributes of the headers might be unaligned.
638 * This is not true, however, as all atributes are manually aligned to 4 bytes.
639 */
640 #pragma diag_suppress = Pa039
641 #endif
642
_load_evo(const uint8_t * data,unsigned size,el_Obj_EVO * evo)643 static ElmHandle _load_evo(const uint8_t *data, unsigned size, el_Obj_EVO *evo)
644 {
645 int i = 0;
646 #if (RTOS && DDRLESS) || BAREMETAL
647 uint32_t colors[VLC_MAX_GRAD];
648 void *path_data;
649 #else
650 uint32_t *colors = NULL;
651 uint8_t *path_data = NULL;
652 #endif
653 el_Obj_EVO *local_evo = NULL;
654 el_EVO_Header *evo_header = (el_EVO_Header *) data;
655
656 if (evo == NULL) {
657 #if (RTOS && DDRLESS) || BAREMETAL
658 local_evo = alloc_evo(1);
659 #else
660 local_evo = (el_Obj_EVO *)elm_alloc(1, sizeof(el_Obj_EVO));
661 #endif
662 evo = local_evo;
663 }
664 JUMP_IF_NULL(evo, error_exit);
665 memset(evo, 0, sizeof(el_Obj_EVO));
666
667 /*
668 * Check if object size is valid. The size parameter
669 * needs to be a value greater or equal to the
670 * size of the current object to be loaded.
671 * This check needs to be done in order to ensure
672 * that the is_image field is correctly read and
673 * we do not read from invalid memory.
674 */
675 JUMP_IF_LOWER(size,
676 MIN(sizeof(el_EVO_Polygon), sizeof(el_EVO_Image)),
677 error_exit);
678
679 if(evo_header->polygon.paint_type.is_image)
680 {
681 /*
682 * Check if object size is valid
683 * (greater or equal to el_EVO_Image size).
684 */
685 JUMP_IF_LOWER(size,
686 sizeof(el_EVO_Image),
687 error_exit);
688 memcpy(evo->eboname,
689 evo_header->image.eboname,
690 evo_header->image.namelength);
691 evo->is_image = evo_header->image.paint_type.is_image;
692 _init_transform(&evo->defaultAttrib.transform);
693 memcpy(&evo->defaultAttrib.transform.matrix,
694 &(evo_header->image.matrix),
695 sizeof(vg_lite_matrix_t));
696 evo->img_width = evo_header->image.width;
697 evo->img_height = evo_header->image.height;
698 }
699 else
700 {
701 /*
702 * Check if object size is valid
703 * (greater or equal to el_EVO_Polygon size).
704 */
705 JUMP_IF_LOWER(size,
706 sizeof(el_EVO_Polygon),
707 error_exit);
708 el_Transform *transform = NULL;
709 el_Transform *grad_transform = NULL;
710 el_EVO_Polygon *object_data = (el_EVO_Polygon *) &(evo_header->polygon);
711 el_EVO_GradData *grad_data = (el_EVO_GradData *) &(evo_header->polygon.grad);
712
713 /* Get path data from the object. */
714 #if (RTOS && DDRLESS) || BAREMETAL
715 path_data = (void *) (data + object_data->offset);
716 #else
717 path_data = (uint8_t *)elm_alloc(1, object_data->length);
718 JUMP_IF_NULL(path_data, error_exit);
719
720 #ifdef ENABLE_STRICT_DEBUG_MEMSET
721 memset(path_data, 0, object_data->length);
722 #endif
723 JUMP_IF_LOWER(size,
724 object_data->offset + object_data->length,
725 error_exit);
726 /* Get path data. */
727 memcpy(path_data, (void *)(data + object_data->offset),
728 object_data->length);
729 #endif
730
731 if(object_data->paint_type.has_pattern)
732 evo->has_pattern = 1;
733 if(object_data->paint_type.is_pattern)
734 evo->is_pattern = 1;
735
736 _init_transform(&evo->defaultAttrib.transform);
737 transform = &evo->defaultAttrib.transform;
738
739 evo->object.type = ELM_OBJECT_TYPE_EVO;
740 evo->object.reference = 0;
741
742 if ((object_data->paint_type.paint == ELM_PAINT_RADIAL_GRADIENT) ||
743 (object_data->paint_type.paint == ELM_PAINT_GRADIENT)) {
744 #if (RTOS && DDRLESS) || BAREMETAL
745 evo->defaultAttrib.paint.grad = alloc_grad();
746 #else
747 evo->defaultAttrib.paint.grad = (el_Obj_Grad*)elm_alloc(1, sizeof(el_Obj_Grad));
748 #endif
749 JUMP_IF_NULL(evo->defaultAttrib.paint.grad, error_exit);
750 #ifdef ENABLE_STRICT_DEBUG_MEMSET
751 memset(evo->defaultAttrib.paint.grad, 0, sizeof(el_Obj_Grad));
752 #endif
753 evo->defaultAttrib.paint.grad->data.grad.image.width = 0;
754 evo->defaultAttrib.paint.grad->data.grad.image.height = 0;
755 evo->defaultAttrib.paint.grad->data.grad.image.stride = 0;
756 evo->defaultAttrib.paint.grad->data.grad.image.tiled = VG_LITE_LINEAR;
757
758 _init_transform(&evo->defaultAttrib.paint.grad->data.transform);
759 grad_transform = &evo->defaultAttrib.paint.grad->data.transform;
760 memcpy(&grad_transform->matrix, &(grad_data->matrix),
761 sizeof(vg_lite_matrix_t));
762 colors = (uint32_t *)elm_alloc(grad_data->stop_count, sizeof(uint32_t));
763 JUMP_IF_NULL(colors, error_exit);
764 memcpy(colors,
765 data + grad_data->color_offset,
766 grad_data->stop_count * sizeof(uint32_t));
767 }
768
769 if (object_data->arc_flag)
770 vg_lite_init_arc_path(&evo->data.path,
771 (vg_lite_format_t) object_data->format,
772 (vg_lite_quality_t) object_data->quality,
773 object_data->length,
774 path_data,
775 object_data->min_x,
776 object_data->min_y,
777 object_data->max_x,
778 object_data->max_y);
779 else
780 vg_lite_init_path(&evo->data.path,
781 (vg_lite_format_t) object_data->format,
782 (vg_lite_quality_t) object_data->quality,
783 object_data->length,
784 path_data,
785 object_data->min_x,
786 object_data->min_y,
787 object_data->max_x,
788 object_data->max_y);
789
790 memcpy(&transform->matrix, &(object_data->matrix), sizeof(vg_lite_matrix_t));
791
792 evo->defaultAttrib.quality = ELM_QUALITY_LOW;
793 evo->defaultAttrib.fill_rule = (ELM_EVO_FILL) object_data->fill_rule;
794 evo->defaultAttrib.blend = (ELM_BLEND) object_data->blend;
795 evo->defaultAttrib.paint.type = (ELM_PAINT_TYPE) object_data->paint_type.paint;
796
797 switch (object_data->paint_type.paint) {
798 case ELM_PAINT_GRADIENT:
799 {
800 #if (RTOS && DDRLESS) || BAREMETAL
801 uint32_t stops[VLC_MAX_GRAD];
802 #else
803 uint32_t *stops = NULL;
804
805 stops = (uint32_t *)elm_alloc(sizeof(uint32_t), grad_data->stop_count);
806 JUMP_IF_NULL(stops, error_exit);
807 #endif
808 for (i = 0 ;i < grad_data->stop_count; i++)
809 {
810 stops[i] = (uint32_t)((*(float *) (data +
811 grad_data->stop_offset + i * 4)) * 255);
812 }
813
814 vg_lite_init_grad(&evo->defaultAttrib.paint.grad->data.grad);
815 vg_lite_set_grad(&evo->defaultAttrib.paint.grad->data.grad,
816 grad_data->stop_count, colors, stops);
817 if (grad_data->stop_count > 0)
818 {
819 vg_lite_update_grad(&evo->defaultAttrib.paint.grad->data.grad);
820 }
821 #if (RTOS && DDRLESS) || BAREMETAL
822 #else
823 elm_free(stops);
824 #endif
825 break;
826 }
827 case ELM_PAINT_RADIAL_GRADIENT:
828 {
829 float *stops;
830 vg_lite_color_ramp_t *vgColorRamp;
831 el_EVO_RadGradDataExt *rad_grad = (el_EVO_RadGradDataExt *) (data + sizeof(el_EVO_Header));
832
833 JUMP_IF_LOWER(size,
834 sizeof(el_EVO_Polygon) + sizeof(el_EVO_RadGradDataExt),
835 error_exit);
836
837 stops = (float *)elm_alloc(grad_data->stop_count, sizeof(float));
838 JUMP_IF_NULL(stops, error_exit);
839 memset(stops, 0, grad_data->stop_count * sizeof(float));
840 vgColorRamp = (vg_lite_color_ramp_t *) elm_alloc(grad_data->stop_count,
841 sizeof(vg_lite_color_ramp_t));
842 if (vgColorRamp == NULL) {
843 elm_free(stops);
844 goto error_exit;
845 }
846 memset(vgColorRamp, 0,
847 sizeof(vg_lite_color_ramp_t) * grad_data->stop_count);
848 for (i = 0; i < grad_data->stop_count; i++)
849 {
850 stops[i] = (*(float *) (data + grad_data->stop_offset + i * 4));
851 vgColorRamp[i].alpha = (float)(colors[i] >> 24) / 255.0f;
852 vgColorRamp[i].red = (float)(colors[i] >> 16 & 0xFF) / 255.0f;
853 vgColorRamp[i].green = (float)(colors[i] >> 8 & 0xFF) / 255.0f;
854 vgColorRamp[i].blue = (float)(colors[i] & 0xFF) / 255.0f;
855 vgColorRamp[i].stop = stops[i];
856 }
857
858 memset(&evo->defaultAttrib.paint.radgrad->data.rad_grad, 0, sizeof(evo->defaultAttrib.paint.radgrad->data.rad_grad));
859 vg_lite_set_rad_grad(&evo->defaultAttrib.paint.radgrad->data.rad_grad,
860 grad_data->stop_count,
861 vgColorRamp,
862 rad_grad->params,
863 rad_grad->spread_mode,
864 0);
865 vg_lite_update_rad_grad(&evo->defaultAttrib.paint.radgrad->data.rad_grad);
866
867 elm_free(stops);
868 elm_free(vgColorRamp);
869 break;
870 }
871 default:
872 /* Do nothing */
873 break;
874 }
875
876 evo->defaultAttrib.paint.color = object_data->color;
877 evo->attribute = evo->defaultAttrib;
878 ref_object(&evo->object);
879 JUMP_IF_NON_ZERO_VALUE(add_object(&evo->object), error_exit);
880
881 #if (RTOS && DDRLESS) || BAREMETAL
882 #else
883 elm_free(colors);
884 #endif
885 }
886
887 return evo->object.handle;
888
889 error_exit:
890 #if (RTOS && DDRLESS) || BAREMETAL
891 #else
892 if ( colors != NULL )
893 elm_free(colors);
894 if ( path_data != NULL)
895 elm_free(path_data);
896 #endif
897
898 if ( (evo != NULL) && (evo->defaultAttrib.paint.grad != NULL) )
899 elm_free(evo->defaultAttrib.paint.grad);
900 if ( (evo != NULL) && (evo->defaultAttrib.paint.radgrad != NULL) )
901 elm_free(evo->defaultAttrib.paint.radgrad);
902 if ( local_evo != NULL )
903 elm_free(local_evo);
904
905 return ELM_NULL_HANDLE;
906 }
907
_load_ebo(const uint8_t * data,int size,uint32_t version)908 static ElmHandle _load_ebo(const uint8_t *data, int size, uint32_t version)
909 {
910 vg_lite_error_t error;
911 vg_lite_buffer_t *buffer;
912 uint32_t *colors, bytes = 0;
913
914 el_EBO_Header *ebo_header = (el_EBO_Header *) data;
915
916 #if (RTOS && DDRLESS) || BAREMETAL
917 el_Obj_EBO *ebo = alloc_ebo();
918 #else
919 el_Obj_EBO *ebo = (el_Obj_EBO *)elm_alloc(1, (sizeof(el_Obj_EBO)));
920 #endif
921 JUMP_IF_NULL(ebo, error_exit);
922 #ifdef ENABLE_STRICT_DEBUG_MEMSET
923 memset(ebo, 0, sizeof(el_Obj_EBO));
924 #endif
925 buffer = &ebo->data.buffer;
926
927 /*
928 * Check if object size is valid. "size" needs to be a value greater than or
929 * equal to the size of the current object header.
930 */
931 JUMP_IF_LOWER(size, sizeof(el_EBO_Header), error_exit);
932 bytes += sizeof(el_EBO_Header);
933
934 if(version == 1)
935 {
936 el_EBO_Palette *clut_header = (el_EBO_Palette *) (data + sizeof(el_EBO_Header));
937
938 /* Make sure object size includes the CLUT header */
939 bytes += sizeof(el_EBO_Palette);
940 JUMP_IF_LOWER(size, bytes, error_exit);
941
942 ebo->object.type = (ELM_OBJECT_TYPE) ebo_header->type;
943 ebo->object.reference = 0;
944
945 buffer->width = ebo_header->width;
946 buffer->height = ebo_header->height;
947 buffer->format = (vg_lite_buffer_format_t) ebo_header->format;
948 buffer->stride = 0;
949
950 error = vg_lite_allocate(buffer);
951 if (error != VG_LITE_SUCCESS)
952 {
953 destroy_ebo(ebo);
954 return 0;
955 }
956
957 buffer->stride = ebo_header->stride;
958 buffer->tiled = (vg_lite_buffer_layout_t) ebo_header->tiled;
959 colors = (uint32_t *)(data + clut_header->clut_data_offset);
960
961 /* Make sure the object size includes image data */
962 JUMP_IF_LOWER(size,
963 ebo_header->data_offset +
964 (buffer->stride * buffer->height),
965 error_exit);
966
967 memcpy(buffer->memory,
968 data + ebo_header->data_offset,
969 buffer->stride * buffer->height);
970
971 /* Save CLUT infomation. */
972 ebo->clut_count = clut_header->clut_count;
973
974 /* Make sure object size includes CLUT data */
975 JUMP_IF_LOWER(size,
976 clut_header->clut_data_offset +
977 (sizeof(uint32_t) * clut_header->clut_count),
978 error_exit);
979
980 memcpy(ebo->clut, colors, sizeof(uint32_t) * clut_header->clut_count);
981 }
982 else if(version == 2)
983 {
984 ebo->object.type = (ELM_OBJECT_TYPE) ebo_header->type;
985 ebo->object.reference = 0;
986
987 buffer->width = ebo_header->width;
988 buffer->height = ebo_header->height;
989 buffer->format = (vg_lite_buffer_format_t) ebo_header->format;
990 buffer->stride = 0;
991
992 error = vg_lite_allocate(buffer);
993 if (error != VG_LITE_SUCCESS)
994 {
995 destroy_ebo(ebo);
996 return 0;
997 }
998
999 buffer->stride = ebo_header->stride;
1000 buffer->tiled = (vg_lite_buffer_layout_t) ebo_header->tiled;
1001
1002 /* Make sure the object size includes image data */
1003 JUMP_IF_LOWER(size,
1004 ebo_header->data_offset +
1005 (buffer->stride * buffer->height),
1006 error_exit);
1007
1008 memcpy(buffer->memory,
1009 data + ebo_header->data_offset,
1010 buffer->stride * buffer->height);
1011 }
1012 /* Set transformation to identity. */
1013 ebo->defaultAttrib.transform.dirty = 1;
1014 ebo->defaultAttrib.transform.identity = 1;
1015
1016 _init_transform(&ebo->defaultAttrib.transform);
1017 ebo->attribute = ebo->defaultAttrib;
1018
1019 ref_object(&ebo->object);
1020 JUMP_IF_NON_ZERO_VALUE(add_object(&ebo->object), error_exit);
1021
1022 return ebo->object.handle;
1023
1024 error_exit:
1025 if (ebo != NULL ) {
1026 elm_free(ebo);
1027 }
1028
1029 return ELM_NULL_HANDLE;
1030 }
1031
_load_ego(const uint8_t * data,int size)1032 static ElmHandle _load_ego(const uint8_t *data, int size)
1033 {
1034 int i;
1035 unsigned int invalid_count = 0;
1036 uint32_t *obj_size, *obj_offset, *obj_type;
1037 void *obj_data;
1038 el_EGO_Header *ego_header = (el_EGO_Header *) data;
1039
1040 #if (RTOS && DDRLESS) || BAREMETAL
1041 el_Obj_Group *ego = alloc_ego();
1042 #else
1043 el_Obj_Group *ego = (el_Obj_Group *)elm_alloc(1, sizeof(el_Obj_Group));
1044 #endif
1045 JUMP_IF_NULL(ego, error_exit);
1046 #ifdef ENABLE_STRICT_DEBUG_MEMSET
1047 memset(ego, 0, sizeof(el_Obj_Group));
1048 #endif
1049
1050 ego->object.type = (ELM_OBJECT_TYPE) ego_header->type;
1051 ego->object.reference = 0;
1052
1053 _init_transform(&ego->defaultTrans);
1054 memcpy(&(ego->defaultTrans.matrix.m),
1055 &(ego_header->matrix),
1056 sizeof(vg_lite_matrix_t));
1057 ego->group.count = ego_header->count;
1058 #if (RTOS && DDRLESS) || BAREMETAL
1059 ego->group.objects = alloc_evo(ego->group.count);
1060 #else
1061 ego->group.objects = (el_Obj_EVO *)elm_alloc(1, ego->group.count * sizeof(el_Obj_EVO));
1062 #endif
1063 JUMP_IF_NULL(ego->group.objects, error_exit);
1064 #ifdef ENABLE_STRICT_DEBUG_MEMSET
1065 memset(ego->group.objects, 0, ego->group.count * sizeof(el_Obj_EVO));
1066 #endif
1067
1068 obj_size = (uint32_t *)((unsigned)data + sizeof(el_EGO_Header));
1069 obj_offset = (uint32_t *)((unsigned)obj_size + \
1070 (ego_header->count * sizeof(uint32_t)));
1071
1072 for (i = 0; i < ego->group.count && obj_offset[i] < size; i++)
1073 {
1074 if (obj_size[i] == 0) {
1075 invalid_count++;
1076 continue;
1077 }
1078
1079 /* Check whether EVO object is truncated */
1080 JUMP_IF_GREATER(obj_offset[i] + obj_size[i], size, error_exit);
1081
1082 /* Call appropriate object loader according to object type */
1083 obj_data = (void*)((unsigned)data + obj_offset[i]);
1084 obj_type = obj_data;
1085 switch (*obj_type) {
1086 case ELM_OBJECT_TYPE_EVO:
1087 ego->group.objects[i].object.handle = _load_evo(obj_data,
1088 obj_size[i],
1089 &ego->group.objects[i]);
1090 break;
1091 #if (VG_RENDER_TEXT==1)
1092 case ELM_OBJECT_TYPE_FONT:
1093 _load_font(obj_data, obj_size[i]);
1094 break;
1095 case ELM_OBJECT_TYPE_TEXT:
1096 ego->group.objects[i].object.handle = _load_text(obj_data,
1097 obj_size[i],
1098 &ego->group.objects[i]);
1099 break;
1100 #endif /* VG_RENDER_TEXT */
1101 default:
1102 break;
1103 }
1104 }
1105
1106 ego->group.count -= invalid_count;
1107 ego->transform = ego->defaultTrans;
1108
1109 ref_object(&ego->object);
1110 JUMP_IF_NON_ZERO_VALUE(add_object(&ego->object), error_exit);
1111
1112 return ego->object.handle;
1113
1114 error_exit:
1115 if (ego != NULL ) {
1116 if ( ego->group.objects != NULL ) {
1117 elm_free(ego->group.objects);
1118 }
1119 elm_free(ego);
1120 }
1121
1122 return ELM_NULL_HANDLE;
1123 }
1124
1125 #if (defined(__ICCARM__))
1126 /* Restore the unaligned data structure attribute warning */
1127 #pragma diag_default = Pa039
1128 #endif
1129
_scale(ElmHandle obj,float x,float y)1130 static BOOL _scale(ElmHandle obj, float x, float y)
1131 {
1132 elm_tls_t* elm_tls;
1133 elm_tls = (elm_tls_t *) elm_os_get_tls();
1134 if (elm_tls == NULL)
1135 return FALSE;
1136
1137 el_Object *object = get_object(obj);
1138 el_Obj_EBO *ebo = NULL;
1139 el_Obj_EVO *evo = NULL;
1140 el_Obj_Group *ego = NULL;
1141 el_Transform *transform = NULL;
1142
1143 switch (object->type) {
1144 case ELM_OBJECT_TYPE_EBO:
1145 ebo = (el_Obj_EBO *)object;
1146 transform = &ebo->attribute.transform;
1147 break;
1148
1149 case ELM_OBJECT_TYPE_EGO:
1150 ego = (el_Obj_Group *)object;
1151 if (elm_tls->gContext.vector_id < 0) {
1152 transform = &ego->transform;
1153 }
1154 else {
1155 evo = _get_evo(ego, elm_tls->gContext.vector_id);
1156 if (evo != NULL) {
1157 transform = &evo->attribute.transform;
1158 }
1159 else { /* No such vector object to set. */
1160 return FALSE;
1161 }
1162 }
1163 break;
1164
1165 case ELM_OBJECT_TYPE_EVO:
1166 evo = (el_Obj_EVO *)object;
1167 transform = &evo->attribute.transform;
1168 break;
1169
1170 default:
1171 DEBUG_ASSERT(0, "Bad object type");
1172 break;
1173 }
1174
1175 // Update the transformation params.
1176 transform->scale[0] *= x;
1177 transform->scale[1] *= y;
1178
1179 vg_lite_scale(x, y, &transform->matrix);
1180
1181 // Clean dirty.
1182 transform->dirty = FALSE;
1183
1184 return TRUE;
1185 }
1186
_reset_attrib(ElmHandle obj,ELM_EVO_PROP_BIT mask)1187 static BOOL _reset_attrib(ElmHandle obj, ELM_EVO_PROP_BIT mask)
1188 {
1189 elm_tls_t* elm_tls;
1190 elm_tls = (elm_tls_t *) elm_os_get_tls();
1191 if (elm_tls == NULL)
1192 return FALSE;
1193
1194 el_Object *object = get_object(obj);
1195 el_Obj_EBO *ebo = NULL;
1196 el_Obj_EVO *evo = NULL;
1197 el_Obj_Group *ego = NULL;
1198 el_Attribute *attrib = NULL;
1199 el_Attribute *defaultAttr = NULL;
1200 el_Transform *transform = NULL;
1201 el_Transform *defaultTrans = NULL;
1202
1203 switch (object->type) {
1204 case ELM_OBJECT_TYPE_EBO:
1205 ebo = (el_Obj_EBO *)object;
1206 attrib = &ebo->attribute;
1207 defaultAttr = &ebo->defaultAttrib;
1208 transform = &attrib->transform;
1209 defaultTrans = &defaultAttr->transform;
1210 break;
1211
1212 case ELM_OBJECT_TYPE_EGO:
1213 ego = (el_Obj_Group *)object;
1214 if (elm_tls->gContext.vector_id < 0) {
1215 transform = &ego->transform;
1216 defaultTrans = &ego->defaultTrans;
1217 }
1218 else {
1219 evo = _get_evo((el_Obj_Group*)obj, elm_tls->gContext.vector_id);
1220 if (evo != NULL) {
1221 attrib = &evo->attribute;
1222 defaultAttr = &evo->defaultAttrib;
1223 transform = &attrib->transform;
1224 defaultTrans = &defaultAttr->transform;
1225 }
1226 else {
1227 return FALSE;
1228 }
1229 }
1230 break;
1231
1232 case ELM_OBJECT_TYPE_EVO:
1233 evo = (el_Obj_EVO *)object;
1234 attrib = &evo->attribute;
1235 defaultAttr = &evo->defaultAttrib;
1236 transform = &attrib->transform;
1237 defaultTrans = &defaultAttr->transform;
1238 break;
1239
1240 default:
1241 DEBUG_ASSERT(0, "Bad object type");
1242 return FALSE;
1243 break;
1244 }
1245
1246 // Update the attribute value. When transform is modified, update the matrix.
1247 if (mask & ELM_PROP_ROTATE_BIT) {
1248 transform->rotate = defaultTrans->rotate;
1249 }
1250
1251 if (mask & ELM_PROP_TRANSFER_BIT) {
1252 transform->translate[0] = defaultTrans->translate[0];
1253 transform->translate[1] = defaultTrans->translate[1];
1254 }
1255
1256 if (mask & ELM_PROP_SCALE_BIT) {
1257 transform->scale[0] = defaultTrans->scale[0];
1258 transform->scale[1] = defaultTrans->scale[1];
1259 }
1260
1261 /* On any bit reset, reset the whole matrix to the default one. */
1262 if (mask & (ELM_PROP_ROTATE_BIT | ELM_PROP_TRANSFER_BIT | ELM_PROP_SCALE_BIT)) {
1263 memcpy(&(transform->matrix), &(defaultTrans->matrix), sizeof(defaultTrans->matrix));
1264 transform->dirty = FALSE;
1265 }
1266
1267 /* Update other rendering attributes. */
1268 if (mask & ELM_PROP_BLEND_BIT) {
1269 attrib->blend = defaultAttr->blend;
1270 }
1271
1272 if (mask & ELM_PROP_QUALITY_BIT) {
1273 attrib->quality = defaultAttr->quality;
1274 }
1275
1276 if (mask & ELM_PROP_FILL_BIT) {
1277 attrib->fill_rule = defaultAttr->fill_rule;
1278 }
1279
1280 if (mask & ELM_PROP_COLOR_BIT) {
1281 attrib->paint.color = defaultAttr->paint.color;
1282 }
1283
1284 if (mask & ELM_PROP_PAINT_BIT) {
1285 attrib->paint.type = defaultAttr->paint.type;
1286 }
1287
1288 return TRUE;
1289 }
1290
_set_quality(ElmHandle obj,ELM_QUALITY quality)1291 static BOOL _set_quality(ElmHandle obj, ELM_QUALITY quality)
1292 {
1293 elm_tls_t* elm_tls;
1294 elm_tls = (elm_tls_t *) elm_os_get_tls();
1295 if (elm_tls == NULL)
1296 return FALSE;
1297
1298 el_Object *object = get_object(obj);
1299 el_Obj_EBO *ebo = NULL;
1300 el_Obj_EVO *evo = NULL;
1301 el_Obj_Group *group = NULL;
1302 el_Attribute *attrib = NULL;
1303
1304 switch (object->type) {
1305 case ELM_OBJECT_TYPE_EBO:
1306 ebo = (el_Obj_EBO *)object;
1307 attrib = &ebo->attribute;
1308 break;
1309
1310 case ELM_OBJECT_TYPE_EVO:
1311 evo = (el_Obj_EVO *)object;
1312 attrib = &evo->attribute;
1313 break;
1314
1315 case ELM_OBJECT_TYPE_EGO:
1316 group = (el_Obj_Group *)object;
1317 evo = _get_evo(group, elm_tls->gContext.vector_id);
1318 if (evo != NULL) {
1319 attrib = &evo->attribute;
1320 }
1321 else {
1322 return FALSE;
1323 }
1324 break;
1325 default:
1326 DEBUG_ASSERT(0, "Bad object type");
1327 return FALSE;
1328 break;
1329 }
1330
1331 attrib->quality = quality;
1332
1333 return TRUE;
1334 }
1335
_set_fill(ElmVecObj evo,ELM_EVO_FILL fill)1336 static BOOL _set_fill(ElmVecObj evo, ELM_EVO_FILL fill)
1337 {
1338 el_Obj_EVO *object = (el_Obj_EVO *)get_object(evo);
1339
1340 if (object == NULL) {
1341 DEBUG_ASSERT(0, "Bad object handle");
1342 return FALSE;
1343 }
1344
1345 object->attribute.fill_rule = fill;
1346
1347 return TRUE;
1348 }
1349
_set_blend(ElmHandle obj,ELM_BLEND blend)1350 static BOOL _set_blend(ElmHandle obj, ELM_BLEND blend)
1351 {
1352 elm_tls_t* elm_tls;
1353 elm_tls = (elm_tls_t *) elm_os_get_tls();
1354 if (elm_tls == NULL)
1355 return FALSE;
1356
1357 el_Object *object = get_object(obj);
1358 el_Obj_EBO *ebo = NULL;
1359 el_Obj_EVO *evo = NULL;
1360 el_Obj_Group *group = NULL;
1361 el_Attribute *attrib = NULL;
1362
1363 switch (object->type) {
1364 case ELM_OBJECT_TYPE_EBO:
1365 ebo = (el_Obj_EBO *)object;
1366 attrib = &ebo->attribute;
1367 break;
1368
1369 case ELM_OBJECT_TYPE_EVO:
1370 evo = (el_Obj_EVO *)object;
1371 attrib = &evo->attribute;
1372 break;
1373
1374 case ELM_OBJECT_TYPE_EGO:
1375 group = (el_Obj_Group *)object;
1376 evo = _get_evo(group, elm_tls->gContext.vector_id);
1377 if (evo != NULL) {
1378 attrib = &evo->attribute;
1379 }
1380 else {
1381 return FALSE;
1382 }
1383 break;
1384 default:
1385 DEBUG_ASSERT(0, "Bad object type");
1386 return FALSE;
1387 break;
1388 }
1389
1390 attrib->blend = blend;
1391
1392 return TRUE;
1393 }
1394
_set_color(ElmVecObj evo,uint32_t color)1395 static BOOL _set_color(ElmVecObj evo, uint32_t color)
1396 {
1397 elm_tls_t* elm_tls;
1398 elm_tls = (elm_tls_t *) elm_os_get_tls();
1399 if (elm_tls == NULL)
1400 return FALSE;
1401
1402 el_Obj_EVO *object = (el_Obj_EVO *)get_object(evo);
1403 el_Obj_Group *group = NULL;
1404
1405 if (object == NULL) {
1406 DEBUG_ASSERT(0, "Bad object handle");
1407 return FALSE;
1408 }
1409
1410 switch (object->object.type) {
1411 case ELM_OBJECT_TYPE_EVO:
1412 break;
1413
1414 case ELM_OBJECT_TYPE_EGO:
1415 group = (el_Obj_Group *)object;
1416 object = _get_evo(group, elm_tls->gContext.vector_id);
1417 if (object == NULL) {
1418 return FALSE;
1419 }
1420 break;
1421 case ELM_OBJECT_TYPE_EBO:
1422 default:
1423 DEBUG_ASSERT(0, "Bad object type");
1424 return FALSE;
1425 break;
1426 }
1427
1428 object->attribute.paint.color = color;
1429
1430 return TRUE;
1431 }
1432
_set_pattern(ElmVecObj evo,ElmBitmapObj pattern)1433 static BOOL _set_pattern(ElmVecObj evo, ElmBitmapObj pattern)
1434 {
1435 elm_tls_t* elm_tls;
1436 elm_tls = (elm_tls_t *) elm_os_get_tls();
1437 if (elm_tls == NULL)
1438 return FALSE;
1439
1440 el_Obj_EVO *object = (el_Obj_EVO *)get_object(evo);
1441 el_Obj_EBO *ebo_obj = (el_Obj_EBO *) get_object(pattern);
1442 el_Obj_Group *group = NULL;
1443
1444 if ((object == NULL) ||
1445 (ebo_obj == NULL)){
1446 DEBUG_ASSERT(0, "Bad object handle");
1447 return FALSE;
1448 }
1449
1450 switch (object->object.type) {
1451 case ELM_OBJECT_TYPE_EVO:
1452 break;
1453
1454 case ELM_OBJECT_TYPE_EGO:
1455 group = (el_Obj_Group *)object;
1456 object = _get_evo(group, elm_tls->gContext.vector_id);
1457 if (object == NULL) {
1458 return FALSE;
1459 }
1460 break;
1461
1462 default:
1463 break;
1464 }
1465
1466 object->attribute.paint.pattern.pattern = ebo_obj;
1467 ref_object((el_Object *)ebo_obj);
1468
1469 return TRUE;
1470 }
1471
_set_pattern_mode(ElmVecObj evo,ELM_PATTERN_MODE mode,uint32_t color)1472 static BOOL _set_pattern_mode(ElmVecObj evo, ELM_PATTERN_MODE mode, uint32_t color)
1473 {
1474 elm_tls_t* elm_tls;
1475 elm_tls = (elm_tls_t *) elm_os_get_tls();
1476 if (elm_tls == NULL)
1477 return FALSE;
1478
1479 el_Obj_EVO *object = (el_Obj_EVO *)get_object(evo);
1480 el_Obj_Group *group = NULL;
1481
1482 if (object == NULL){
1483 DEBUG_ASSERT(0, "Bad object handle");
1484 return FALSE;
1485 }
1486
1487 switch (object->object.type) {
1488 case ELM_OBJECT_TYPE_EVO:
1489 break;
1490
1491 case ELM_OBJECT_TYPE_EGO:
1492 group = (el_Obj_Group *)object;
1493 object = _get_evo(group, elm_tls->gContext.vector_id);
1494 if (object == NULL) {
1495 return FALSE;
1496 }
1497 break;
1498
1499 default:
1500 break;
1501 }
1502
1503 object->attribute.paint.pattern.mode = mode;
1504 object->attribute.paint.pattern.color = color;
1505
1506 return TRUE;
1507 }
1508
_set_paintType(ElmVecObj evo,ELM_PAINT_TYPE type)1509 static BOOL _set_paintType(ElmVecObj evo, ELM_PAINT_TYPE type)
1510 {
1511 elm_tls_t* elm_tls;
1512 elm_tls = (elm_tls_t *) elm_os_get_tls();
1513 if (elm_tls == NULL)
1514 return FALSE;
1515
1516 el_Obj_EVO *object = (el_Obj_EVO *)get_object(evo);
1517 el_Obj_Group *group = NULL;
1518
1519 if (object == NULL) {
1520 DEBUG_ASSERT(0, "Bad object handle");
1521 return FALSE;
1522 }
1523 switch (object->object.type) {
1524 case ELM_OBJECT_TYPE_EVO:
1525 break;
1526
1527 case ELM_OBJECT_TYPE_EGO:
1528 group = (el_Obj_Group *)object;
1529 object = _get_evo(group, elm_tls->gContext.vector_id);
1530 if (object == NULL) {
1531 return FALSE;
1532 }
1533 break;
1534
1535 default:
1536 break;
1537 }
1538
1539 object->attribute.paint.type = type;
1540
1541 return TRUE;
1542 }
1543
_rotate(ElmHandle obj,float angle)1544 static BOOL _rotate(ElmHandle obj, float angle)
1545 {
1546 elm_tls_t* elm_tls;
1547 elm_tls = (elm_tls_t *) elm_os_get_tls();
1548 if (elm_tls == NULL)
1549 return FALSE;
1550
1551 el_Object *object = get_object(obj);
1552 el_Obj_EBO *ebo = NULL;
1553 el_Obj_EVO *evo = NULL;
1554 el_Obj_Group *ego = NULL;
1555 el_Transform *transform = NULL;
1556
1557 switch (object->type) {
1558 case ELM_OBJECT_TYPE_EBO:
1559 ebo = (el_Obj_EBO *)object;
1560 transform = &ebo->attribute.transform;
1561 break;
1562
1563 case ELM_OBJECT_TYPE_EGO:
1564 ego = (el_Obj_Group *)object;
1565 if (elm_tls->gContext.vector_id < 0) {
1566 transform = &ego->transform;
1567 }
1568 else {
1569 evo = _get_evo(ego, elm_tls->gContext.vector_id);
1570 if (evo != NULL) {
1571 transform = &evo->attribute.transform;
1572 }
1573 else {
1574 return FALSE;
1575 }
1576 }
1577 break;
1578
1579 case ELM_OBJECT_TYPE_EVO:
1580 evo = (el_Obj_EVO *)object;
1581 transform = &evo->attribute.transform;
1582 break;
1583
1584 default:
1585 DEBUG_ASSERT(0, "Bad object type");
1586 break;
1587 }
1588
1589 // Update the transformation params.
1590 transform->rotate += angle;
1591
1592 // Upate the matrix.
1593 vg_lite_rotate(angle, &transform->matrix);
1594
1595 // Clean dirty.
1596 transform->dirty = FALSE;
1597
1598 return TRUE;
1599 }
_translate(ElmHandle obj,float x,float y)1600 static BOOL _translate(ElmHandle obj, float x, float y)
1601 {
1602 elm_tls_t* elm_tls;
1603 elm_tls = (elm_tls_t *) elm_os_get_tls();
1604 if (elm_tls == NULL)
1605 return FALSE;
1606
1607 el_Object *object = get_object(obj);
1608 el_Obj_EBO *ebo = NULL;
1609 el_Obj_EVO *evo = NULL;
1610 el_Obj_Group *ego = NULL;
1611 el_Transform *transform = NULL;
1612
1613 switch (object->type) {
1614 case ELM_OBJECT_TYPE_EBO:
1615 ebo = (el_Obj_EBO *)object;
1616 transform = &ebo->attribute.transform;
1617 break;
1618
1619 case ELM_OBJECT_TYPE_EGO:
1620 ego = (el_Obj_Group *)object;
1621 if (elm_tls->gContext.vector_id < 0) {
1622 transform = &ego->transform;
1623 }
1624 else {
1625 evo = _get_evo(ego, elm_tls->gContext.vector_id);
1626 if (evo != NULL) {
1627 transform = &evo->attribute.transform;
1628 }
1629 else {
1630 return FALSE;
1631 }
1632 }
1633 break;
1634
1635 case ELM_OBJECT_TYPE_EVO:
1636 evo = (el_Obj_EVO *)object;
1637 transform = &evo->attribute.transform;
1638 break;
1639
1640 default:
1641 DEBUG_ASSERT(0, "Bad object type");
1642 break;
1643 }
1644
1645 // Update the transformation params.
1646 transform->translate[0] += x;
1647 transform->translate[1] += y;
1648
1649 // Update the matrix.
1650 vg_lite_translate(x, y, &transform->matrix);
1651
1652 // Clean dirty.
1653 transform->dirty = FALSE;
1654
1655 return TRUE;
1656 }
1657
_verify_header(ELM_OBJECT_TYPE * type,uint32_t * version,void * data)1658 static BOOL _verify_header(ELM_OBJECT_TYPE *type, uint32_t *version, void *data)
1659 {
1660 uint32_t *p32_data = (uint32_t *)data;
1661
1662 if (type != NULL) {
1663 *type = (ELM_OBJECT_TYPE)(*(p32_data + 1));
1664 }
1665
1666 if (version != NULL) {
1667 *version = *p32_data;
1668
1669 if (*version <= ELM_VERSION) {
1670 return TRUE; /* Verified OK, compatible. */
1671 }
1672 else {
1673 return FALSE; /* Verified Failed, API version is lower. */
1674 }
1675 }
1676
1677 return TRUE;
1678 }
1679
1680 /*
1681 Load the specified object from the data.
1682 */
_create_object_from_data(ELM_OBJECT_TYPE type,void * data,int size)1683 static ElmHandle _create_object_from_data(ELM_OBJECT_TYPE type, void *data, int size)
1684 {
1685 ELM_OBJECT_TYPE real_type;
1686 uint32_t p_data = (uint32_t)data;
1687 uint32_t version;
1688
1689 if(p_data % BASE_ADDRESS_ALIGNMENT != 0) {
1690 DEBUG_ASSERT(0, "Error: data address don't align with 32 bytes!");
1691 return ELM_NULL_HANDLE;
1692 }
1693
1694 if (FALSE == _verify_header(&real_type, &version, data)) {
1695 DEBUG_ASSERT(0, "Error: Incompatible file.");
1696 return ELM_NULL_HANDLE;
1697 }
1698
1699 if (real_type != type) {
1700 DEBUG_ASSERT(0, "Warning: Specified type mismatched.\n");
1701 }
1702
1703 /* Jump over the version field to get to the start of the first ELM object */
1704 data = (void *)((unsigned)data + sizeof(uint32_t));
1705
1706 switch (real_type) {
1707 case ELM_OBJECT_TYPE_EVO:
1708 return _load_evo(data, size, NULL);
1709 break;
1710
1711 case ELM_OBJECT_TYPE_EGO:
1712 return _load_ego(data, size);
1713
1714 case ELM_OBJECT_TYPE_EBO:
1715 return _load_ebo(data, size, version);
1716 #if (VG_RENDER_TEXT==1)
1717 case ELM_OBJECT_TYPE_FONT:
1718 return _load_font(data, size);
1719
1720 case ELM_OBJECT_TYPE_TEXT:
1721 return _load_text(data, size, NULL);
1722 #endif
1723 default:
1724 DEBUG_ASSERT(0, "Bad object type");
1725 break;
1726 }
1727
1728 return ELM_NULL_HANDLE;
1729 }
1730
_get_paint_transform(ElmHandle handle)1731 static el_Transform *_get_paint_transform(ElmHandle handle)
1732 {
1733 elm_tls_t* elm_tls;
1734 elm_tls = (elm_tls_t *) elm_os_get_tls();
1735 if (elm_tls == NULL)
1736 return FALSE;
1737
1738 el_Transform *transform = NULL;
1739 el_Obj_Group *group = NULL;
1740 el_Obj_EVO *evo = NULL;
1741
1742 evo = (el_Obj_EVO *)get_object(handle);
1743
1744 if (evo == NULL) {
1745 DEBUG_ASSERT(0, "Bad object handle.\n");
1746 return NULL;
1747 }
1748
1749 /* Find the corresponding evo object. */
1750 switch (evo->object.type) {
1751 case ELM_OBJECT_TYPE_EVO:
1752 break;
1753
1754 case ELM_OBJECT_TYPE_EGO:
1755 group = (el_Obj_Group *)evo;
1756 evo = _get_evo(group, elm_tls->gContext.vector_id);
1757 if (evo == NULL) {
1758 return NULL;
1759 }
1760 break;
1761
1762 case ELM_OBJECT_TYPE_EBO:
1763 default:
1764 DEBUG_ASSERT(0, "Incorrect object tyoe.\n");
1765 return NULL;
1766 break;
1767 }
1768
1769 /* Get the correct transformation based on the paint type. */
1770 if (evo->attribute.paint.type == ELM_PAINT_PATTERN) {
1771 transform = &((el_Obj_EBO*)evo->attribute.paint.pattern.pattern)->attribute.transform;
1772 }
1773 else if (evo->attribute.paint.type == ELM_PAINT_GRADIENT) {
1774 transform = &evo->attribute.paint.grad->data.transform;
1775 }
1776
1777 return transform;
1778 }
1779
1780 /*********************** ELM API *********************/
1781 #if !RTOS
1782 /*!
1783 @abstract Create an elementary object from an existing binary file.
1784
1785 @discussion
1786 This function creates an elementary object from the file whose file name is specified by param name.
1787 Caller must match type with the binary file, otherwise create mail fail by returning ELM_NULL_HANDLE.
1788
1789 @param type
1790 Specify what type of object to be created.
1791
1792 @param name
1793 The name of the binary resource file.
1794
1795 @return ElmHandle
1796 An object handle depending on the corresponding type. If type mismatches, it
1797 returns ELM_NULL_HANDLE.
1798 */
ElmCreateObjectFromFile(ELM_OBJECT_TYPE type,const char * name)1799 ElmHandle ElmCreateObjectFromFile(ELM_OBJECT_TYPE type, const char *name)
1800 {
1801 #if RTOS || BAREMETAL
1802 return ELM_NULL_HANDLE;
1803 #else
1804 void *data = NULL;
1805 long size = 0;
1806 FILE *fp = fopen(name, "rb");
1807 ElmHandle handle = ELM_NULL_HANDLE;
1808
1809 if (fp != NULL) {
1810 fseek(fp, 0, SEEK_END);
1811 size = ftell(fp);
1812
1813 data = elm_alloc(1, size);
1814 if (data != NULL) {
1815 fseek(fp, 0, SEEK_SET);
1816 fread(data, size, 1, fp);
1817
1818 handle = _create_object_from_data(type, data, size);
1819 }
1820 else {
1821 printf("open %s failed!\n", name);
1822 }
1823 elm_free(data);
1824 fclose(fp);
1825 }
1826
1827 return handle;
1828 #endif
1829 }
1830 #else
ElmCreateObjectFromFile(ELM_OBJECT_TYPE type,const char * name)1831 ElmHandle ElmCreateObjectFromFile(ELM_OBJECT_TYPE type, const char *name)
1832 {
1833 return ELM_NULL_HANDLE;
1834 }
1835 #endif /*!ENABLE_ELM_CRATE_OBJECT_FROM_FILE*/
1836 /*!
1837 @abstract Create an elementary object from build-in data within the appplication.
1838
1839 @discussion
1840 This function creates an elementar object from local data pointer, which is specially useful for environment without filesystem support.
1841
1842 @param type
1843 Specify what type of object to be created.
1844
1845 @param data
1846 The pointer to the binary data which has exactly same layout as external resource file.
1847
1848 @return ElmHandle
1849 An object handle depending on the corresponding type. If type mismatches with the binary data, it
1850 returns ELM_NULL_HANDLE.
1851 */
ElmCreateObjectFromData(ELM_OBJECT_TYPE type,void * data,int size)1852 ElmHandle ElmCreateObjectFromData(ELM_OBJECT_TYPE type, void *data, int size)
1853 {
1854 return _create_object_from_data(type, data, size);
1855 }
1856
1857 /*!
1858 @abstract Destroy an ELM object.
1859
1860 @discussion
1861 This function is to release all internal resource inside Elementary libary belonging to this object.
1862 Applicatoin need make sure the object is not being used by elmentary library any more when calling this function.
1863 If an EBO is being destroyed and it's attached to one EVO, it need to guarantee that EVO is not being used by elementary library too.
1864
1865 @param object
1866 The object handle
1867
1868 @return
1869 If destroying is completed successfully.
1870 */
ElmDestroyObject(ElmHandle object)1871 BOOL ElmDestroyObject(ElmHandle object)
1872 {
1873 int result = destroy_object(object);
1874 return (result >= 0);
1875 }
1876
1877 /*!
1878 @abstract Rotate a graphics object with centain degree
1879
1880 @discussion
1881 This function sets an evo/ebo/ego object rotated with specified angle. Without reset, these setting will be
1882 accumulated.
1883
1884 @param obj
1885 The graphics object will be rotated.
1886
1887 @param angle
1888 A radian value to be applied on the evo object.
1889
1890 @return bool
1891 Rotate is set successfully.
1892 */
ElmRotate(ElmHandle obj,float angle)1893 BOOL ElmRotate(ElmHandle obj, float angle)
1894 {
1895 return _rotate(obj, angle);
1896 }
1897
1898 /*!
1899 @abstract Transfer an graphics object at different directions.
1900
1901 @discussion
1902 This function put an evo/ebo/ego object away at different directions. Without reset, the setting will be
1903 accumulated.
1904
1905 @param obj
1906 The graphics object will be transfered.
1907
1908 @param x
1909 The units in pixel of X direction.
1910
1911 @param y
1912 The units in pixel of Y direction.
1913
1914 @return bool
1915 Transfer is set successfully.
1916 */
ElmTransfer(ElmHandle obj,int x,int y)1917 BOOL ElmTransfer(ElmHandle obj, int x, int y)
1918 {
1919 return _translate(obj, x, y);
1920 }
1921
1922 /*!
1923 @abstract Scale an graphics object at different directions.
1924
1925 @discussion
1926 This function scale up or down an evo/ego/ebo object at different directions. Without reset, the setting will
1927 be accumateled.
1928
1929 @param obj
1930 The graphics object which is targeted to manipulate.
1931
1932 @param x
1933 The scale ratio in X direction.
1934
1935 @param y
1936 The scale ratio in Y direction.
1937
1938 @return bool
1939 Scale is set succefully.
1940 */
ElmScale(ElmHandle obj,float x,float y)1941 BOOL ElmScale(ElmHandle obj, float x, float y)
1942 {
1943 return _scale(obj, x, y);
1944 }
1945
1946 /*!
1947 @abstract Reset the attribute of a graphics object for specified property bit.
1948
1949 @discussion
1950 This funcion resets specified property for an elementary object. It can be applied all types of objects.
1951 But some properties are only valid for centain types of objects. If the function is called to reset an invalid
1952 property for this type of object, it will be siliently ignored.
1953 After reset, the specifed property of an evo/ebo/ego object is set to the initial state. The initial states are decided
1954 by the binary resource file. The resource creator should set right value for all properties if they want to directly render
1955 the object without any adjustment in application. There is one issue, at present, application has no way to query current value
1956 of each property, is it required?
1957
1958 @param obj
1959 The graphics object which is targeted to manipulate.
1960
1961 @param mask
1962 Specify which property or properties need to reset to initial value.
1963
1964 @return bool
1965 Reset is done successfully. If some mask is not valid for this type of object, it would return false.
1966 */
ElmReset(ElmHandle obj,ELM_EVO_PROP_BIT mask)1967 BOOL ElmReset(ElmHandle obj, ELM_EVO_PROP_BIT mask)
1968 {
1969 return _reset_attrib(obj, mask);
1970 }
1971
1972 /*!
1973 @abstract Set the rendering quality of an graphics object.
1974
1975 @discussion
1976 This function sets the rendering quality of an evo/ebo object. Avaliable quality setting contains:
1977 ELM_EVO_QUALITY_LOW, ELM_EVO_QUALITY_MED, ELM_EVO_QUALITY_HI. This function is only applied to an evo or an ebo.
1978 Group object can't be set quality. It always use the setting from its binary.
1979
1980 @param obj
1981 The elementary object.
1982
1983 @param quality
1984 The quality enum.
1985
1986 @return bool
1987 The operation for this object is sucessful, for group object and invalid enum, would return false.
1988 */
ElmSetQuality(ElmHandle obj,ELM_QUALITY quality)1989 BOOL ElmSetQuality(ElmHandle obj, ELM_QUALITY quality)
1990 {
1991 return _set_quality(obj, quality);
1992 }
1993
1994 /*!
1995 @abstract Set the fill rule of an evo object.
1996
1997 @discussion
1998 This function sets the fill rule of an elementary object. Avaliable quality setting contains:
1999 ELM_EVO_EO, ELM_EVO_NZ. It only applies to evo object.
2000
2001 @param evo
2002 The evo object.
2003
2004 @param fill
2005 The fill rule enum.
2006
2007 @return bool
2008 The operation for this evo is sucessful. For non-evo object an ENUM is not a valid enum, would return false.
2009 */
ElmSetFill(ElmVecObj evo,ELM_EVO_FILL fill)2010 BOOL ElmSetFill(ElmVecObj evo, ELM_EVO_FILL fill)
2011 {
2012 return _set_fill(evo, fill);
2013 }
2014
2015 /*!
2016 @abstract Set the blending mode of an evo/ebo object.
2017
2018 @discussion
2019 This function sets the blending mode of an evo/ebo object. It's not applied to group object.
2020
2021 @param obj
2022 The graphics object.
2023
2024 @param blend
2025 The blending mode enum.
2026
2027 @return bool
2028 The operation for this evo/ebo is sucessful. If object is a group object or blend mode is not a legal one, it would return false.
2029 */
ElmSetBlend(ElmHandle obj,ELM_BLEND blend)2030 BOOL ElmSetBlend(ElmHandle obj, ELM_BLEND blend)
2031 {
2032 return _set_blend(obj, blend);
2033 }
2034
2035 /*!
2036 @abstract Set the solid fill color of an evo object.
2037
2038 @discussion
2039 This function sets the solid fill color of an evo object.
2040
2041 @param evo
2042 The evo object.
2043
2044 @param color
2045 The uint32 color value in rgba order.
2046
2047 @return bool
2048 The operation for this evo is sucessful. If the object is not a evo object, it would return false.
2049 */
ElmSetColor(ElmVecObj evo,uint32_t color)2050 BOOL ElmSetColor(ElmVecObj evo, uint32_t color)
2051 {
2052 return _set_color(evo, color);
2053 }
2054
2055 /*!
2056 @abstract Set the image paint fill of an evo.
2057
2058 @discussion
2059 This function sets the image pattern for filling an evo. The image pattern
2060 is a loaded ebo. The ebo's transformation is applied when drawing the evo.
2061
2062 @param evo
2063 The evo object.
2064
2065 @param pattern
2066 The image pattern to be set for the evo.
2067
2068 @return bool
2069 The operation is successful or not.
2070 */
ElmSetPattern(ElmVecObj evo,ElmBitmapObj pattern)2071 BOOL ElmSetPattern(ElmVecObj evo, ElmBitmapObj pattern)
2072 {
2073 return _set_pattern(evo, pattern);
2074 }
2075
2076 /*!
2077 @abstract Set the image paint fill of an evo.
2078
2079 @discussion
2080 This function sets the image pattern for filling an evo. The image pattern
2081 is a loaded ebo. The ebo's transformation is applied when drawing the evo.
2082
2083 @param evo
2084 The evo object.
2085
2086 @param pattern
2087 The image pattern to be set for the evo.
2088
2089 @return bool
2090 The operation is successful or not.
2091 */
ElmSetPatternMode(ElmVecObj evo,ELM_PATTERN_MODE mode,uint32_t color)2092 BOOL ElmSetPatternMode(ElmVecObj evo, ELM_PATTERN_MODE mode, uint32_t color)
2093 {
2094 return _set_pattern_mode(evo, mode, color);
2095 }
2096
2097 /*!
2098 @abstract Set the paint type of an evo.
2099
2100 @discussion
2101 This function selects the paint type for evo to use. An evo may have 3 types
2102 of paint: COLOR, PATTERN, and LINEAR GRADIENT. The Linear graident is always
2103 a built-in resource, which can not be altered. If a binary resource doesn't
2104 have built-in gradient paint resource, it can't be selected as the paint source.
2105 Solid color is also a built-in attribute, but it can be changed by ElmSetColor().
2106 Paint with a pattern always need an external ebo object, which is impossible
2107 to be embedded in resource file,i.e. ebo object. Before select paint type to
2108 be PATTERN, ElmSetPattern() must be called to attach an EBO to an EVO.
2109
2110 @param evo
2111 The evo object.
2112
2113 @param type
2114 The paint type to be set for the evo.
2115
2116 @return bool
2117 The operation is successful or not.
2118 If the corresponding type is not avaiable for the evo, it returns false and
2119 type paint type falls back to COLOR.
2120 */
ElmSetPaintType(ElmVecObj evo,ELM_PAINT_TYPE type)2121 BOOL ElmSetPaintType(ElmVecObj evo, ELM_PAINT_TYPE type)
2122 {
2123 return _set_paintType(evo, type);
2124 }
2125
2126 /*!
2127 @abstract Get the solid fill color of an evo object.
2128
2129 @discussion
2130 This function Get the solid fill color of an evo object.
2131
2132 @param evo
2133 The evo object.
2134
2135 @return uint32_t
2136 The uint32 color value in rgba order.
2137 */
ElmGetColor(ElmGroupObj handle,uint32_t * color)2138 BOOL ElmGetColor(ElmGroupObj handle,uint32_t *color)
2139 {
2140 elm_tls_t* elm_tls;
2141 el_Obj_EVO *evo;
2142
2143 elm_tls = (elm_tls_t *) elm_os_get_tls();
2144 if (elm_tls == NULL)
2145 return FALSE;
2146
2147 el_Obj_Group *ego = (el_Obj_Group*) get_object(handle);
2148 evo = _get_evo(ego, elm_tls->gContext.vector_id);
2149 *color = evo->attribute.paint.color;
2150
2151 return TRUE;
2152 }
2153
2154 /*!
2155 @abstract Query the vectory path count of an EGO object. If the given object
2156 is an evo/ebo, the count is 0.
2157 */
ElmGetVectorCount(ElmHandle handle)2158 uint32_t ElmGetVectorCount(ElmHandle handle)
2159 {
2160 el_Obj_Group *ego = (el_Obj_Group*) get_object(handle);
2161 if (ego->object.type != ELM_OBJECT_TYPE_EGO) {
2162 return 0;
2163 }
2164 else {
2165 return ego->group.count;
2166 }
2167 }
2168
2169 /*!
2170 @abstract Query the type of an object (by handle).
2171 */
ElmGetObjectType(ElmHandle handle)2172 ELM_OBJECT_TYPE ElmGetObjectType(ElmHandle handle)
2173 {
2174 el_Object *object = get_object(handle);
2175 return object->type;
2176 }
2177
2178 /*!
2179 @abstract Set the current vectory object index to operate on.
2180 */
ElmSetCurrentVector(int32_t id)2181 BOOL ElmSetCurrentVector(int32_t id)
2182 {
2183 elm_tls_t* elm_tls;
2184 elm_tls = (elm_tls_t *) elm_os_get_tls();
2185 if (elm_tls == NULL)
2186 return FALSE;
2187
2188 elm_tls->gContext.vector_id = id;
2189
2190 return TRUE;
2191 }
2192
ElmScalePaint(ElmHandle handle,float sx,float sy)2193 BOOL ElmScalePaint(ElmHandle handle, float sx, float sy)
2194 {
2195 el_Transform *transform = NULL;
2196
2197 transform = _get_paint_transform(handle);
2198
2199 if (transform != NULL) {
2200 vg_lite_scale(sx, sy, &transform->matrix);
2201 transform->dirty = FALSE;
2202 return TRUE;
2203 }
2204 else {
2205 return FALSE;
2206 }
2207 }
ElmRotatePaint(ElmHandle handle,float degrees)2208 BOOL ElmRotatePaint(ElmHandle handle, float degrees)
2209 {
2210 el_Transform *transform = NULL;
2211
2212 transform = _get_paint_transform(handle);
2213
2214 if (transform != NULL) {
2215 vg_lite_rotate(degrees, &transform->matrix);
2216 transform->dirty = FALSE;
2217 return TRUE;
2218 }
2219 else {
2220 return FALSE;
2221 }
2222 }
2223
ElmTranslatePaint(ElmHandle handle,float tx,float ty)2224 BOOL ElmTranslatePaint(ElmHandle handle, float tx, float ty)
2225 {
2226 el_Transform *transform = NULL;
2227
2228 transform = _get_paint_transform(handle);
2229
2230 if (transform != NULL) {
2231 vg_lite_translate(tx, ty, &transform->matrix);
2232 transform->dirty = FALSE;
2233 return TRUE;
2234 }
2235 else {
2236 return FALSE;
2237 }
2238 }
2239