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