1 /****************************************************************************
2 *
3 *    The MIT License (MIT)
4 *
5 *    Copyright 2020 NXP
6 *    All Rights Reserved.
7 *
8 *    Permission is hereby granted, free of charge, to any person obtaining
9 *    a copy of this software and associated documentation files (the
10 *    'Software'), to deal in the Software without restriction, including
11 *    without limitation the rights to use, copy, modify, merge, publish,
12 *    distribute, sub license, and/or sell copies of the Software, and to
13 *    permit persons to whom the Software is furnished to do so, subject
14 *    to the following conditions:
15 *
16 *    The above copyright notice and this permission notice (including the
17 *    next paragraph) shall be included in all copies or substantial
18 *    portions of the Software.
19 *
20 *    THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
21 *    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 *    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
23 *    IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
24 *    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
25 *    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
26 *    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 *
28 *****************************************************************************/
29 
30 /** Include Files */
31 #include <mcufont.h>
32 #include <stdio.h>
33 #include <string.h>
34 #include <stdlib.h>
35 
36 #include "vg_lite.h"
37 #include "buf_reader.h"
38 #include "vg_lite_text.h"
39 #include "vft_draw.h"
40 #include "vft_debug.h"
41 
42 /** Macros */
43 #define __COUNTOF(x) (sizeof(x)/sizeof(x[0]))
44 #define MAX_SYSTEM_FONTS (8)
45 
46 #define RCD_ALLOC(x) _mem_allocate(x)
47 #define RCD_FREE(x) _mem_free(x)
48 
49 #ifdef ENABLE_DEBUG_TRACE
50 static int g_id;
51 
52 #define DBG_ID() (g_id)
53 #define DBG_INC_ID() (g_id++)
54 #define DBG_SET_ID(x) g_id = x
55 #else
56 
57 #define DBG_ID() (0)
58 #define DBG_INC_ID() (0)
59 #define DBG_SET_ID(x)
60 #endif
61 
62 #if APP_ENABLE_SDCARD
63 #define sprintf_s snprintf
64 #endif
65 
66 /** Data structures */
67 typedef struct font_height_list {
68     const char font_height;
69     const char ref_font_height;
70     const char ref_font_scale;
71 } font_height_list_t;
72 
73 typedef struct font_info_internal {
74   /* Variable shared between user and driver */
75   vg_lite_font_params_t font_params;
76   /* any additional variables internal to driver */
77   int valid;
78   /* Internal loaded raster font */
79   struct mf_font_s *_raster_font;
80   /* Internal loaded vector font */
81   font_face_desc_t *_vector_font;
82 }font_info_internal_t;
83 
84 /** Internal or external API prototypes */
85 
86 /** Globals */
87 static font_info_internal_t s_device_fonts[MAX_SYSTEM_FONTS];
88 
89 /** Local function prototypes */
90 int read_rle_font_header(bufferred_reader_t *f, struct mf_font_s* font);
91 int read_rle_font_from_buffer(char *buf, int size, struct mf_font_s* font);
92 int load_raster_font(char *data, int data_len, struct mf_font_s** font);
93 
94 int read_8b(bufferred_reader_t *f, uint8_t* pdata);
95 int read_16b(bufferred_reader_t *f, uint16_t* pword);
96 int read_32b(bufferred_reader_t *f, uint32_t* pword);
97 int read_16b_blob(bufferred_reader_t *f, uint16_t** ary, uint32_t* ary_len);
98 int read_8b_blob(bufferred_reader_t *f, uint8_t** ary, uint32_t* ary_len);
99 int free_rle_font_memory(struct mf_font_s** font);
100 vg_lite_error_t vg_lite_free_font_memory(vg_lite_font_t font);
101 vg_lite_error_t vg_lite_load_font_data(vg_lite_font_t font, int font_height);
102 
103 /** Externs if any */
104 
105 /** Code section */
106 vg_lite_font_t vg_lite_find_font(
107     char *font_name,
108     eFontWeight_t  font_weight,
109     eFontStretch_t font_stretch,
110     eFontStyle_t   font_style,
111     int font_height);
112 
vg_lite_register_font(vg_lite_font_t * font,vg_lite_font_params_t * params)113 vg_lite_error_t vg_lite_register_font(vg_lite_font_t *font,
114     vg_lite_font_params_t *params)
115 {
116   int i;
117   int free_entry = VG_LITE_INVALID_FONT;
118 
119   if (font != NULL)
120     *font = VG_LITE_INVALID_FONT;
121 
122   /* Check if font is already registered */
123   for (i=0; i<MAX_SYSTEM_FONTS; i++) {
124     /* Is entry is valid ? */
125     if ( s_device_fonts[i].valid == 0 ) {
126         /* Grab free entry in list for new font */
127         if (free_entry == -1 ) {
128             free_entry = i;
129         }
130     } else if (s_device_fonts[i].valid == 1 ) {
131       /* Does font.name matches */
132       if ( strncmp(s_device_fonts[i].font_params.name,
133                   params->name,
134                   strlen(s_device_fonts[i].font_params.name)) == 0)
135       {
136             return VG_LITE_ALREADY_EXISTS;
137       }
138     } else {
139       printf("Corrupt font table\n");
140       return VG_LITE_INVALID_ARGUMENT;
141     }
142   }
143 
144   /* Check if list is completely full or not */
145   if ( i == MAX_SYSTEM_FONTS && free_entry == VG_LITE_INVALID_FONT) {
146       /* Font List descriptor exhausted */
147       return VG_LITE_OUT_OF_RESOURCES;
148   } else {
149       /* Add new font in global table */
150       memcpy(&s_device_fonts[free_entry].font_params, params, sizeof(vg_lite_font_params_t));
151       s_device_fonts[free_entry].valid = 1;
152 /*
153    Loading font here leads to low run-time memory, we may need to characterize memory usage
154    e.g. pure path test don't require font, eventhrough application registers them
155 */
156 #if 0
157       error = vg_lite_load_font_data(free_entry, params->font_height);
158       if ( error != 0 ) {
159           s_device_fonts[free_entry].valid = 0;
160           return error;
161       }
162 #endif
163   }
164 
165   if (font != NULL)
166     *font = free_entry;
167 
168   return VG_LITE_SUCCESS;
169 }
170 
vg_lite_is_font_valid(vg_lite_font_t font)171 int vg_lite_is_font_valid(vg_lite_font_t font)
172 {
173     if (font < MAX_SYSTEM_FONTS) {
174         if (s_device_fonts[font].valid == 1)
175             return 0;
176     }
177     return VG_LITE_INVALID_ARGUMENT;
178 }
179 
vg_lite_is_vector_font(vg_lite_font_t font)180 int vg_lite_is_vector_font(vg_lite_font_t font)
181 {
182     if (font < MAX_SYSTEM_FONTS) {
183         if (s_device_fonts[font].valid == 1)
184             return (s_device_fonts[font].font_params.font_type ==
185                 eFontTypeVector);
186         else
187             return 0;
188     }
189     return VG_LITE_INVALID_ARGUMENT;;
190 }
191 
vg_lite_unregister_font(vg_lite_font_t font)192 vg_lite_error_t vg_lite_unregister_font(vg_lite_font_t font)
193 {
194     if (vg_lite_is_font_valid(font) != 0 ) {
195         /* Font not found */
196         return VG_LITE_INVALID_ARGUMENT;;
197     }
198 
199     vg_lite_free_font_memory(font);
200     s_device_fonts[font].valid = 0;
201     return VG_LITE_SUCCESS;
202 }
203 
vg_lite_get_font_name(vg_lite_font_t font)204 char *vg_lite_get_font_name(vg_lite_font_t font)
205 {
206   if ( vg_lite_is_font_valid(font) != 0 ) {
207         return NULL;
208   }
209 
210   return (char *)s_device_fonts[font].font_params.name;
211 }
212 
vg_lite_free_font_memory(vg_lite_font_t font)213 vg_lite_error_t vg_lite_free_font_memory(vg_lite_font_t font)
214 {
215   if ( vg_lite_is_font_valid(font) != 0 ) {
216         /* Font not found */
217         return VG_LITE_INVALID_ARGUMENT;
218   }
219   switch (s_device_fonts[font].font_params.font_type) {
220     case eFontTypeVector:
221       if ( s_device_fonts[font]._vector_font != NULL ) {
222           vft_unload(s_device_fonts[font]._vector_font);
223           s_device_fonts[font]._vector_font = NULL;
224       }
225       break;
226     case eFontTypeRaster:
227       if ( s_device_fonts[font]._raster_font != NULL ) {
228           free_rle_font_memory(&s_device_fonts[font]._raster_font);
229           s_device_fonts[font]._raster_font = NULL;
230       }
231       break;
232   }
233 
234   return VG_LITE_SUCCESS;
235 }
236 
_vg_lite_get_vector_font(vg_lite_font_t font)237 font_face_desc_t *_vg_lite_get_vector_font(vg_lite_font_t font)
238 {
239   if ( vg_lite_is_font_valid(font) != 0 ) {
240         return NULL;
241   }
242 
243   return s_device_fonts[font]._vector_font;
244 }
245 
_vg_lite_get_raster_font(vg_lite_font_t font)246 struct mf_font_s *_vg_lite_get_raster_font(vg_lite_font_t font)
247 {
248   if ( vg_lite_is_font_valid(font) != 0 ) {
249         return NULL;
250   }
251 
252   return s_device_fonts[font]._raster_font;
253 }
254 
vg_lite_load_font_data(vg_lite_font_t font,int font_height)255 vg_lite_error_t vg_lite_load_font_data(vg_lite_font_t font, int font_height)
256 {
257   if ( vg_lite_is_font_valid(font) != 0 ) {
258         /* Font not found */
259         return VG_LITE_INVALID_ARGUMENT;
260   }
261 
262   switch (s_device_fonts[font].font_params.font_type) {
263     case eFontTypeVector:
264       if (s_device_fonts[font]._vector_font == NULL ) {
265           //printf("Loading vector font : [%s]\n",
266           //       s_device_fonts[font].font_params.name);
267           s_device_fonts[font]._vector_font =
268           vft_load_from_buffer(
269                  s_device_fonts[font].font_params.data,
270                  s_device_fonts[font].font_params.data_len);
271           if ( s_device_fonts[font]._vector_font == NULL )  {
272                 return VG_LITE_INVALID_ARGUMENT;
273           }
274       }
275       return VG_LITE_SUCCESS;
276     case eFontTypeRaster:
277       if (s_device_fonts[font]._raster_font == NULL ) {
278           //printf("Loading raster font : [%s]\n",
279           //       s_device_fonts[font].font_params.name);
280           /* Raster fonts height should match */
281           if ( font_height == s_device_fonts[font].font_params.font_height &&
282               load_raster_font(
283                  s_device_fonts[font].font_params.data,
284                  s_device_fonts[font].font_params.data_len,
285                  &s_device_fonts[font]._raster_font) != 0)
286           {
287               return VG_LITE_INVALID_ARGUMENT;
288           }
289       }
290       return VG_LITE_SUCCESS;
291   }
292   return VG_LITE_INVALID_ARGUMENT;
293 }
294 
295 
vg_lite_find_font(char * font_name_list,eFontWeight_t font_weight,eFontStretch_t font_stretch,eFontStyle_t font_style,int font_height)296 vg_lite_font_t vg_lite_find_font(
297     char *font_name_list,
298     eFontWeight_t  font_weight,
299     eFontStretch_t font_stretch,
300     eFontStyle_t   font_style,
301     int font_height)
302 {
303     int i;
304     char tmp_data;
305     int font_found = 0;
306     int end_pos = 0; /* End position of font name */
307     char *font_name;
308     /*
309     printf("Font params: [%s],%d, %d, %d, %d\n",
310            font_name_list,
311            font_weight,
312            font_stretch,
313            font_style,
314            font_height);
315     */
316 
317     /* While probing font, if required font is found, then
318        only keep that name in supplied font list */
319 
320     /* Split and extract font name one-by-one */
321     font_name = font_name_list;
322     while (font_found == 0 &&
323            font_name[end_pos] != '\0')
324     {
325         tmp_data = '\0';
326         /* Scan for seperator */
327         while (font_name[end_pos] != '\0') {
328             if (font_name[end_pos] == ',' || font_name[end_pos] == ' ' ||
329               font_name[end_pos] == '\t')
330             {
331                 tmp_data = font_name[end_pos];
332                 font_name[end_pos] = '\0';
333                 break;
334             }
335             end_pos++;
336         }
337 
338         /* Search for exact font-name match */
339         for (i=0; i<__COUNTOF(s_device_fonts); i++) {
340            if (s_device_fonts[i].valid == 0)
341                continue;
342 
343            /* For vector font only compare name */
344            if (s_device_fonts[i].font_params.font_type == eFontTypeVector ) {
345                 if ( strlen(font_name) > 0 &&
346                     strcmp(font_name,
347                     s_device_fonts[i].font_params.name) == 0)
348                 {
349                    font_name[end_pos] = tmp_data; /* Restor delimeter */
350                    return i;
351                 }
352            } else {
353                 /* For raster font compare all properties */
354                 if (s_device_fonts[i].font_params.font_weight == font_weight &&
355                     s_device_fonts[i].font_params.font_stretch == font_stretch &&
356                     s_device_fonts[i].font_params.font_style == font_style )
357                 {
358                     if ( strlen(font_name) > 0 &&
359                         strcmp(font_name,
360                         s_device_fonts[i].font_params.name) == 0)
361                     {
362                        font_name[end_pos] = tmp_data; /* Restor delimeter */
363 
364                        if (s_device_fonts[i].font_params.font_height == font_height)
365                        {
366                             return i;
367                        }
368                         /* Update font_name_list to improve future searches */
369                         strncpy(font_name_list, font_name, strlen(font_name)+1);
370                     }
371                 }
372             }
373         }
374         /* Continue searching for other font entries */
375         font_name[end_pos] = tmp_data;
376         font_name += (end_pos + 1);
377         end_pos = 0;
378     }
379     printf("WARNING: [%s] Font not found\r\n",font_name_list);
380 
381     return VG_LITE_INVALID_FONT;
382 }
383 
vg_lite_text_init(void)384 void vg_lite_text_init(void)
385 {
386     static int font_table_ready = 0;
387 
388     if (font_table_ready)
389         return;
390 
391     /* Initialize font table */
392     memset(s_device_fonts, 0, MAX_SYSTEM_FONTS * sizeof(font_info_internal_t));
393     font_table_ready = 1;
394 }
395 
396 /* Read-Write 8-bit unsigned int data */
read_8b(bufferred_reader_t * f,uint8_t * pdata)397 int read_8b(bufferred_reader_t * f, uint8_t* pdata)
398 {
399     bufferred_fread(pdata, 1, 1, f);
400     TRACE_DBG(("%d) 8b: fp=%08x %d %d\r\n", DBG_INC_ID(),
401                bufferred_ftell(f) - 1, 1, *pdata));
402     return 1;
403 }
404 
405 /* Read-Write 16-bit unsigned int data */
read_16b(bufferred_reader_t * f,uint16_t * pword)406 int read_16b(bufferred_reader_t * f, uint16_t* pword)
407 {
408     uint8_t buf[4];
409     uint16_t word;
410 
411     bufferred_fread(buf, 2, 1, f);
412     word = 0;   word += buf[1];
413     word <<= 8; word += buf[0];
414 
415     TRACE_DBG(("%d) 16b: fp=%08x %d %d\r\n", DBG_INC_ID(),
416                bufferred_ftell(f)-2, 2, word));
417     *pword = word;
418     return 2;
419 }
420 
421 /* Read-write 32-bit unsigned int data */
read_32b(bufferred_reader_t * f,uint32_t * pword)422 int read_32b(bufferred_reader_t * f, uint32_t* pword)
423 {
424     uint8_t buf[4];
425     uint32_t word;
426 
427     bufferred_fread(buf, 4, 1, f);
428     word = 0;   word += buf[3];
429     word <<= 8; word += buf[2];
430     word <<= 8; word += buf[1];
431     word <<= 8; word += buf[0];
432 
433     *pword = word;
434     TRACE_DBG(("%d) 32b: fp=%08x %d %d\r\n", DBG_INC_ID(),
435                bufferred_ftell(f) - 4, 4,
436                word));
437     return 4;
438 }
439 
read_16b_blob(bufferred_reader_t * f,uint16_t ** ary,uint32_t * ary_len)440 int read_16b_blob(bufferred_reader_t * f, uint16_t** ary, uint32_t* ary_len)
441 {
442     uint16_t blob_len = 0;
443 
444     *ary_len = 0;
445     bufferred_fread(&blob_len, 1, sizeof(uint16_t), f);
446     *ary = (uint16_t *)RCD_ALLOC(blob_len * sizeof(uint16_t)); /* Malloc must be aligned on 2 byte boundary */
447     if (*ary == NULL) {
448         TRACE_ERR(("ERROR: malloc failed\n"));;
449         return VG_LITE_OUT_OF_MEMORY;
450     }
451     if ((((unsigned long)*ary) & 0x1) != 0) {
452         TRACE_ERR(("ERROR: malloc pointer not 2 byte aligned\n"));;
453         return VG_LITE_NOT_ALIGNED;
454     }
455     TRACE_DBG(("%d ) 16b_blob: fp=%08x %d\r\n", DBG_INC_ID(), bufferred_ftell(f)-2,
456                (int)blob_len));
457     bufferred_fread(*ary, 2, blob_len, f);
458     *ary_len = blob_len * 2;
459 
460     return blob_len + 2; /* Actual bytes read from file */
461 }
462 
read_8b_blob(bufferred_reader_t * f,uint8_t ** ary,uint32_t * ary_len)463 int read_8b_blob(bufferred_reader_t * f, uint8_t** ary, uint32_t *ary_len)
464 {
465     uint16_t blob_len = 0;
466     uint8_t* p_tmp = (uint8_t *)NULL;
467     bufferred_fread(&blob_len, 1, sizeof(uint16_t), f);
468     //TRACE_DBG(("%d) 8b_blob: %d\r\n", DBG_INC_ID(), blob_len));
469     p_tmp = (uint8_t *)RCD_ALLOC(blob_len+1);
470     if (p_tmp == NULL) {
471         TRACE_ERR(("ERROR: malloc failed\n"));;
472         return VG_LITE_OUT_OF_MEMORY;
473     }
474     TRACE_DBG(("%d ) 8b_blob: fp=%08x %d\r\n", DBG_INC_ID(), bufferred_ftell(f)-2,
475                (int)blob_len));
476     bufferred_fread(p_tmp, 1, blob_len, f);
477     p_tmp[blob_len] = 0;
478     *ary = p_tmp;
479 
480     return blob_len + 2; /* Actual bytes read from file */
481 }
482 
483 #define EXIT_IF_NEGATIVE(param) if ((ret = param) < 0) return ret;
484 
read_rle_font_header(bufferred_reader_t * f,struct mf_font_s * font)485 int read_rle_font_header(bufferred_reader_t * f, struct mf_font_s* font)
486 {
487     int raw_header_offset = 0;
488     struct mf_rlefont_s* mfont = (struct mf_rlefont_s*)font;
489     uint32_t size = 0;
490     int ret = 0;
491 
492     TRACE_DBG(("** %s\r\n", __FUNCTION__));
493     DBG_SET_ID(0);
494 
495     EXIT_IF_NEGATIVE(read_8b_blob(f, (uint8_t **)&font->full_name, &size));
496     raw_header_offset += ret; /* font.full_name */
497 
498     EXIT_IF_NEGATIVE(read_8b_blob(f, (uint8_t **)&font->short_name, &size));
499     raw_header_offset += ret; /* font.short_name */
500 
501     EXIT_IF_NEGATIVE(read_8b(f, &font->width));
502     raw_header_offset += 1;                       /* font.width */
503 
504     EXIT_IF_NEGATIVE(read_8b(f, &font->height));
505     raw_header_offset += 1;                       /* font.height */
506 
507     EXIT_IF_NEGATIVE(read_8b(f, &font->min_x_advance));
508     raw_header_offset += 1;                       /* font.min_x_advance */
509 
510     EXIT_IF_NEGATIVE(read_8b(f, &font->max_x_advance));
511     raw_header_offset += 1;                       /* font.max_x_advance */
512 
513     EXIT_IF_NEGATIVE(read_8b(f, (uint8_t *)&font->baseline_x));
514     raw_header_offset += 1;                       /* font.baseline_x */
515 
516     EXIT_IF_NEGATIVE(read_8b(f, &font->baseline_y));
517     raw_header_offset += 1;                       /* font.baseline_y */
518 
519     EXIT_IF_NEGATIVE(read_8b(f, &font->line_height));
520     raw_header_offset += 1;                       /* font.line_height */
521 
522     EXIT_IF_NEGATIVE(read_8b(f, &font->flags));
523     raw_header_offset += 1;                       /* font.flags */
524 
525     EXIT_IF_NEGATIVE(read_16b(f, &font->fallback_character));
526     raw_header_offset += 2;                       /* font.fallback_character */
527 
528     EXIT_IF_NEGATIVE(read_8b(f, &(mfont->version)));
529     raw_header_offset += 1;                           /* mf_rlefont_s.version */
530 
531     /* Other mf_rlefont_s variables */
532     uint16_t value = 0;
533     EXIT_IF_NEGATIVE(read_16b(f, &value)); //&mfont->dictionary_data_size));
534     mfont->dictionary_data_size = value;
535     raw_header_offset += 2;                           /* mf_rlefont_s.dictionary_data_size */
536 
537     EXIT_IF_NEGATIVE(read_32b(f, &mfont->dictionary_data_fp_offset));
538     raw_header_offset += 4;                           /* mf_rlefont_s.dictionary_data_fp_offset */
539 
540     value = 0;
541     EXIT_IF_NEGATIVE(read_16b(f, &value)); //mfont->dictionary_offsets_size));
542     mfont->dictionary_offsets_size = value;
543     raw_header_offset += 2;                           /* mf_rlefont_s.dictionary_data_size */
544 
545     EXIT_IF_NEGATIVE(read_32b(f, &mfont->dictionary_offsets_fp_offset));
546     raw_header_offset += 4;                           /* mf_rlefont_s.dictionary_data_fp_offset */
547 
548     EXIT_IF_NEGATIVE(read_8b(f, &mfont->rle_entry_count));
549     raw_header_offset += 1;                           /* mf_rlefont_s.rle_entry_count */
550 
551     EXIT_IF_NEGATIVE(read_8b(f, &mfont->dict_entry_count));
552     raw_header_offset += 1;                           /* mf_rlefont_s.dict_entry_count */
553 
554     EXIT_IF_NEGATIVE(read_8b(f, &mfont->char_range_count));
555     raw_header_offset += 1;                           /* mf_rlefont_s.char_range_count */
556 
557     mfont->char_ranges = (struct mf_rlefont_char_range_s *)RCD_ALLOC(sizeof(struct mf_rlefont_char_range_s)* mfont->char_range_count);
558     memset(mfont->char_ranges, 0, sizeof(struct mf_rlefont_char_range_s) * mfont->char_range_count);
559 
560     /* Skip size of ranges */
561     for (int r = 0; r < mfont->char_range_count; r++) {
562         EXIT_IF_NEGATIVE(read_16b(f, &mfont->char_ranges[r].first_char));
563         raw_header_offset += 2;                           /* mf_rlefont_s.char_ranges[r].first_char */
564 
565         EXIT_IF_NEGATIVE(read_16b(f, &mfont->char_ranges[r].char_count));
566         raw_header_offset += 2;                           /* mf_rlefont_s.char_ranges[r].char_count */
567 
568         EXIT_IF_NEGATIVE(read_32b(f, &mfont->char_ranges[r].glyph_offsets_fp_offset));
569         raw_header_offset += 4;                           /* mf_rlefont_s.char_ranges[r].glyph_offsets_fp_offset */
570 
571         EXIT_IF_NEGATIVE(read_32b(f, &mfont->char_ranges[r].glyph_offsets_size));
572         raw_header_offset += 4;                           /* mf_rlefont_s.char_ranges[r].glyph_offsets_size */
573 
574         EXIT_IF_NEGATIVE(read_32b(f, &mfont->char_ranges[r].glyph_data_fp_offset));
575         raw_header_offset += 4;                           /* mf_rlefont_s.char_ranges[r].glyph_offsets_fp_offset */
576 
577         EXIT_IF_NEGATIVE(read_32b(f, &mfont->char_ranges[r].glyph_data_size));
578         raw_header_offset += 4;                           /* mf_rlefont_s.char_ranges[r].glyph_offsets_size */
579     }
580     return raw_header_offset;
581 }
582 
583 /* Writes a BMP file. The data is assumed to be 8-bit grayscale. */
read_rle_font_from_buffer(char * buff,int size,struct mf_font_s * font)584 int read_rle_font_from_buffer(char *buff, int size, struct mf_font_s* font)
585 {
586     struct mf_rlefont_s* mfont = (struct mf_rlefont_s*)font;
587     bufferred_reader_t f_obj;
588     bufferred_reader_t * f = &f_obj;
589     int raw_header_offset = 0;
590     int fp_offset;
591     int ret;
592 
593     DBG_SET_ID(0);
594 
595     /* No need to dynamically allocate small descriptor */
596     if ( bufferred_fopen(f, buff, size) < 0 ) {
597         /* Font file open failed */
598         return VG_LITE_INVALID_ARGUMENT;
599     }
600 
601     raw_header_offset = read_rle_font_header(f, font);
602     if (mfont->dictionary_data_fp_offset != raw_header_offset) {
603         TRACE_ERR(("ERROR: dictonary offset is different"));
604     }
605     TRACE_DBG(("** %s\r\n", __FUNCTION__));
606     DBG_SET_ID(0);
607 
608     /* Skip header portion */
609     bufferred_fseek(f, raw_header_offset, SEEK_SET);
610     /* Write dictionary entries */
611     fp_offset = raw_header_offset;
612     TRACE_DBG(("dictionary_data_fp_offset=%08x %08x\r\n",
613         mfont->dictionary_data_fp_offset, bufferred_ftell(f)));
614     //mfont->dictionary_data_fp_offset = fp_offset;
615     EXIT_IF_NEGATIVE(read_8b_blob(f, &mfont->dictionary_data,
616         &mfont->dictionary_data_size));
617     fp_offset += mfont->dictionary_data_size + 2;
618 
619     //mfont->dictionary_offsets_fp_offset = fp_offset;
620     TRACE_DBG(("dictionary_offsets_fp_offset=%08x %08x\r\n",
621         mfont->dictionary_offsets_fp_offset, bufferred_ftell(f)));
622     EXIT_IF_NEGATIVE(read_16b_blob(f, &mfont->dictionary_offsets,
623         &mfont->dictionary_offsets_size));
624     fp_offset += mfont->dictionary_offsets_size + 2;
625 
626     /* Write range entries */
627     for (int r = 0; r < mfont->char_range_count; r++) {
628         //mfont->char_ranges[r].glyph_offsets_fp_offset = fp_offset;
629         TRACE_DBG(("mfont->char_ranges[%d].glyph_offsets=%08x %08x\r\n", r,
630             mfont->char_ranges[r].glyph_offsets_fp_offset, bufferred_ftell(f)));
631         EXIT_IF_NEGATIVE(read_16b_blob(f, &mfont->char_ranges[r].glyph_offsets,
632             &mfont->char_ranges[r].glyph_offsets_size));
633         fp_offset += mfont->char_ranges[r].glyph_offsets_size + 2;
634 
635         //mfont->char_ranges[r].glyph_data_fp_offset = fp_offset;
636         TRACE_DBG(("mfont->char_ranges[%d].glyph_data_fp_offset=%08x %08x\r\n",
637             r,
638             mfont->char_ranges[r].glyph_data_fp_offset, bufferred_ftell(f)));
639         EXIT_IF_NEGATIVE(read_8b_blob(f, &mfont->char_ranges[r].glyph_data,\
640             &mfont->char_ranges[r].glyph_data_size));
641         fp_offset += mfont->char_ranges[r].glyph_data_size + 2;
642     }
643 
644     bufferred_fclose(f);
645     return 0;
646 }
647 
load_raster_font(char * data,int data_len,struct mf_font_s ** font)648 int load_raster_font(char *data, int data_len, struct mf_font_s** font)
649 {
650     int ret;
651 
652     /* Allocate font memory */
653     *font = (struct mf_font_s*)RCD_ALLOC(sizeof(struct mf_rlefont_s));
654     if (*font == NULL) {
655         return VG_LITE_OUT_OF_MEMORY;
656     }
657     memset(*font, 0, sizeof(struct mf_rlefont_s));
658 
659     /* Load font from file */
660     ret = read_rle_font_from_buffer(data,
661                                     data_len, *font);
662     if (ret < 0) {
663         return ret;
664     }
665 
666     /* Update generic char width pointers of mculib */
667     uint8_t mf_rlefont_character_width(const struct mf_font_s* font,
668         uint16_t character);
669     uint8_t mf_rlefont_render_character(const struct mf_font_s* font,
670         int16_t x0, int16_t y0,
671         uint16_t character,
672         mf_pixel_callback_t callback,
673         void* state);
674 
675     (*font)->character_width = &mf_rlefont_character_width;
676     (*font)->render_character = &mf_rlefont_render_character;
677 
678 
679     return 0;
680 }
681 
free_rle_font_memory(struct mf_font_s ** font)682 int free_rle_font_memory(struct mf_font_s** font)
683 {
684     struct mf_rlefont_s* mfont = (struct mf_rlefont_s*)(*font);
685 
686     RCD_FREE(mfont->font.full_name);
687     RCD_FREE(mfont->font.short_name);
688     RCD_FREE(mfont->dictionary_data);
689     RCD_FREE(mfont->dictionary_offsets);
690     for (int r = 0; r < mfont->char_range_count; r++) {
691         RCD_FREE(mfont->char_ranges[r].glyph_offsets);
692         RCD_FREE(mfont->char_ranges[r].glyph_data);
693     }
694     #ifdef DEBUG_RESET_DATASTRUCTURE_ON_FREE
695     memset(mfont->char_ranges);
696     #endif
697     RCD_FREE(mfont->char_ranges);
698 
699     #ifdef DEBUG_RESET_DATASTRUCTURE_ON_FREE
700     memset(mfont);
701     #endif
702     RCD_FREE(mfont);
703 
704     *font = NULL;
705     return 0;
706 }
707 
vg_lite_unload_font_data(void)708 void vg_lite_unload_font_data(void)
709 {
710     for(int i=0; i<MAX_SYSTEM_FONTS; i++)
711     {
712         vg_lite_free_font_memory(i);
713     }
714 
715     return;
716 }
717