717 lines
23 KiB
C
717 lines
23 KiB
C
|
/****************************************************************************
|
||
|
*
|
||
|
* The MIT License (MIT)
|
||
|
*
|
||
|
* Copyright 2020 NXP
|
||
|
* All Rights Reserved.
|
||
|
*
|
||
|
* Permission is hereby granted, free of charge, to any person obtaining
|
||
|
* a copy of this software and associated documentation files (the
|
||
|
* 'Software'), to deal in the Software without restriction, including
|
||
|
* without limitation the rights to use, copy, modify, merge, publish,
|
||
|
* distribute, sub license, and/or sell copies of the Software, and to
|
||
|
* permit persons to whom the Software is furnished to do so, subject
|
||
|
* to the following conditions:
|
||
|
*
|
||
|
* The above copyright notice and this permission notice (including the
|
||
|
* next paragraph) shall be included in all copies or substantial
|
||
|
* portions of the Software.
|
||
|
*
|
||
|
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
||
|
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
|
||
|
* IN NO EVENT SHALL VIVANTE AND/OR ITS SUPPLIERS BE LIABLE FOR ANY
|
||
|
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||
|
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
||
|
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||
|
*
|
||
|
*****************************************************************************/
|
||
|
|
||
|
/** Include Files */
|
||
|
#include <mcufont.h>
|
||
|
#include <stdio.h>
|
||
|
#include <string.h>
|
||
|
#include <stdlib.h>
|
||
|
|
||
|
#include "vg_lite.h"
|
||
|
#include "buf_reader.h"
|
||
|
#include "vg_lite_text.h"
|
||
|
#include "vft_draw.h"
|
||
|
#include "vft_debug.h"
|
||
|
|
||
|
/** Macros */
|
||
|
#define __COUNTOF(x) (sizeof(x)/sizeof(x[0]))
|
||
|
#define MAX_SYSTEM_FONTS (8)
|
||
|
|
||
|
#define RCD_ALLOC(x) _mem_allocate(x)
|
||
|
#define RCD_FREE(x) _mem_free(x)
|
||
|
|
||
|
#ifdef ENABLE_DEBUG_TRACE
|
||
|
static int g_id;
|
||
|
|
||
|
#define DBG_ID() (g_id)
|
||
|
#define DBG_INC_ID() (g_id++)
|
||
|
#define DBG_SET_ID(x) g_id = x
|
||
|
#else
|
||
|
|
||
|
#define DBG_ID() (0)
|
||
|
#define DBG_INC_ID() (0)
|
||
|
#define DBG_SET_ID(x)
|
||
|
#endif
|
||
|
|
||
|
#if APP_ENABLE_SDCARD
|
||
|
#define sprintf_s snprintf
|
||
|
#endif
|
||
|
|
||
|
/** Data structures */
|
||
|
typedef struct font_height_list {
|
||
|
const char font_height;
|
||
|
const char ref_font_height;
|
||
|
const char ref_font_scale;
|
||
|
} font_height_list_t;
|
||
|
|
||
|
typedef struct font_info_internal {
|
||
|
/* Variable shared between user and driver */
|
||
|
vg_lite_font_params_t font_params;
|
||
|
/* any additional variables internal to driver */
|
||
|
int valid;
|
||
|
/* Internal loaded raster font */
|
||
|
struct mf_font_s *_raster_font;
|
||
|
/* Internal loaded vector font */
|
||
|
font_face_desc_t *_vector_font;
|
||
|
}font_info_internal_t;
|
||
|
|
||
|
/** Internal or external API prototypes */
|
||
|
|
||
|
/** Globals */
|
||
|
static font_info_internal_t s_device_fonts[MAX_SYSTEM_FONTS];
|
||
|
|
||
|
/** Local function prototypes */
|
||
|
int read_rle_font_header(bufferred_reader_t *f, struct mf_font_s* font);
|
||
|
int read_rle_font_from_buffer(char *buf, int size, struct mf_font_s* font);
|
||
|
int load_raster_font(char *data, int data_len, struct mf_font_s** font);
|
||
|
|
||
|
int read_8b(bufferred_reader_t *f, uint8_t* pdata);
|
||
|
int read_16b(bufferred_reader_t *f, uint16_t* pword);
|
||
|
int read_32b(bufferred_reader_t *f, uint32_t* pword);
|
||
|
int read_16b_blob(bufferred_reader_t *f, uint16_t** ary, uint32_t* ary_len);
|
||
|
int read_8b_blob(bufferred_reader_t *f, uint8_t** ary, uint32_t* ary_len);
|
||
|
int free_rle_font_memory(struct mf_font_s** font);
|
||
|
vg_lite_error_t vg_lite_free_font_memory(vg_lite_font_t font);
|
||
|
vg_lite_error_t vg_lite_load_font_data(vg_lite_font_t font, int font_height);
|
||
|
|
||
|
/** Externs if any */
|
||
|
|
||
|
/** Code section */
|
||
|
vg_lite_font_t vg_lite_find_font(
|
||
|
char *font_name,
|
||
|
eFontWeight_t font_weight,
|
||
|
eFontStretch_t font_stretch,
|
||
|
eFontStyle_t font_style,
|
||
|
int font_height);
|
||
|
|
||
|
vg_lite_error_t vg_lite_register_font(vg_lite_font_t *font,
|
||
|
vg_lite_font_params_t *params)
|
||
|
{
|
||
|
int i;
|
||
|
int free_entry = VG_LITE_INVALID_FONT;
|
||
|
|
||
|
if (font != NULL)
|
||
|
*font = VG_LITE_INVALID_FONT;
|
||
|
|
||
|
/* Check if font is already registered */
|
||
|
for (i=0; i<MAX_SYSTEM_FONTS; i++) {
|
||
|
/* Is entry is valid ? */
|
||
|
if ( s_device_fonts[i].valid == 0 ) {
|
||
|
/* Grab free entry in list for new font */
|
||
|
if (free_entry == -1 ) {
|
||
|
free_entry = i;
|
||
|
}
|
||
|
} else if (s_device_fonts[i].valid == 1 ) {
|
||
|
/* Does font.name matches */
|
||
|
if ( strncmp(s_device_fonts[i].font_params.name,
|
||
|
params->name,
|
||
|
strlen(s_device_fonts[i].font_params.name)) == 0)
|
||
|
{
|
||
|
return VG_LITE_ALREADY_EXISTS;
|
||
|
}
|
||
|
} else {
|
||
|
printf("Corrupt font table\n");
|
||
|
return VG_LITE_INVALID_ARGUMENT;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
/* Check if list is completely full or not */
|
||
|
if ( i == MAX_SYSTEM_FONTS && free_entry == VG_LITE_INVALID_FONT) {
|
||
|
/* Font List descriptor exhausted */
|
||
|
return VG_LITE_OUT_OF_RESOURCES;
|
||
|
} else {
|
||
|
/* Add new font in global table */
|
||
|
memcpy(&s_device_fonts[free_entry].font_params, params, sizeof(vg_lite_font_params_t));
|
||
|
s_device_fonts[free_entry].valid = 1;
|
||
|
/*
|
||
|
Loading font here leads to low run-time memory, we may need to characterize memory usage
|
||
|
e.g. pure path test don't require font, eventhrough application registers them
|
||
|
*/
|
||
|
#if 0
|
||
|
error = vg_lite_load_font_data(free_entry, params->font_height);
|
||
|
if ( error != 0 ) {
|
||
|
s_device_fonts[free_entry].valid = 0;
|
||
|
return error;
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
if (font != NULL)
|
||
|
*font = free_entry;
|
||
|
|
||
|
return VG_LITE_SUCCESS;
|
||
|
}
|
||
|
|
||
|
int vg_lite_is_font_valid(vg_lite_font_t font)
|
||
|
{
|
||
|
if (font < MAX_SYSTEM_FONTS) {
|
||
|
if (s_device_fonts[font].valid == 1)
|
||
|
return 0;
|
||
|
}
|
||
|
return VG_LITE_INVALID_ARGUMENT;
|
||
|
}
|
||
|
|
||
|
int vg_lite_is_vector_font(vg_lite_font_t font)
|
||
|
{
|
||
|
if (font < MAX_SYSTEM_FONTS) {
|
||
|
if (s_device_fonts[font].valid == 1)
|
||
|
return (s_device_fonts[font].font_params.font_type ==
|
||
|
eFontTypeVector);
|
||
|
else
|
||
|
return 0;
|
||
|
}
|
||
|
return VG_LITE_INVALID_ARGUMENT;;
|
||
|
}
|
||
|
|
||
|
vg_lite_error_t vg_lite_unregister_font(vg_lite_font_t font)
|
||
|
{
|
||
|
if (vg_lite_is_font_valid(font) != 0 ) {
|
||
|
/* Font not found */
|
||
|
return VG_LITE_INVALID_ARGUMENT;;
|
||
|
}
|
||
|
|
||
|
vg_lite_free_font_memory(font);
|
||
|
s_device_fonts[font].valid = 0;
|
||
|
return VG_LITE_SUCCESS;
|
||
|
}
|
||
|
|
||
|
char *vg_lite_get_font_name(vg_lite_font_t font)
|
||
|
{
|
||
|
if ( vg_lite_is_font_valid(font) != 0 ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return (char *)s_device_fonts[font].font_params.name;
|
||
|
}
|
||
|
|
||
|
vg_lite_error_t vg_lite_free_font_memory(vg_lite_font_t font)
|
||
|
{
|
||
|
if ( vg_lite_is_font_valid(font) != 0 ) {
|
||
|
/* Font not found */
|
||
|
return VG_LITE_INVALID_ARGUMENT;
|
||
|
}
|
||
|
switch (s_device_fonts[font].font_params.font_type) {
|
||
|
case eFontTypeVector:
|
||
|
if ( s_device_fonts[font]._vector_font != NULL ) {
|
||
|
vft_unload(s_device_fonts[font]._vector_font);
|
||
|
s_device_fonts[font]._vector_font = NULL;
|
||
|
}
|
||
|
break;
|
||
|
case eFontTypeRaster:
|
||
|
if ( s_device_fonts[font]._raster_font != NULL ) {
|
||
|
free_rle_font_memory(&s_device_fonts[font]._raster_font);
|
||
|
s_device_fonts[font]._raster_font = NULL;
|
||
|
}
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return VG_LITE_SUCCESS;
|
||
|
}
|
||
|
|
||
|
font_face_desc_t *_vg_lite_get_vector_font(vg_lite_font_t font)
|
||
|
{
|
||
|
if ( vg_lite_is_font_valid(font) != 0 ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return s_device_fonts[font]._vector_font;
|
||
|
}
|
||
|
|
||
|
struct mf_font_s *_vg_lite_get_raster_font(vg_lite_font_t font)
|
||
|
{
|
||
|
if ( vg_lite_is_font_valid(font) != 0 ) {
|
||
|
return NULL;
|
||
|
}
|
||
|
|
||
|
return s_device_fonts[font]._raster_font;
|
||
|
}
|
||
|
|
||
|
vg_lite_error_t vg_lite_load_font_data(vg_lite_font_t font, int font_height)
|
||
|
{
|
||
|
if ( vg_lite_is_font_valid(font) != 0 ) {
|
||
|
/* Font not found */
|
||
|
return VG_LITE_INVALID_ARGUMENT;
|
||
|
}
|
||
|
|
||
|
switch (s_device_fonts[font].font_params.font_type) {
|
||
|
case eFontTypeVector:
|
||
|
if (s_device_fonts[font]._vector_font == NULL ) {
|
||
|
//printf("Loading vector font : [%s]\n",
|
||
|
// s_device_fonts[font].font_params.name);
|
||
|
s_device_fonts[font]._vector_font =
|
||
|
vft_load_from_buffer(
|
||
|
s_device_fonts[font].font_params.data,
|
||
|
s_device_fonts[font].font_params.data_len);
|
||
|
if ( s_device_fonts[font]._vector_font == NULL ) {
|
||
|
return VG_LITE_INVALID_ARGUMENT;
|
||
|
}
|
||
|
}
|
||
|
return VG_LITE_SUCCESS;
|
||
|
case eFontTypeRaster:
|
||
|
if (s_device_fonts[font]._raster_font == NULL ) {
|
||
|
//printf("Loading raster font : [%s]\n",
|
||
|
// s_device_fonts[font].font_params.name);
|
||
|
/* Raster fonts height should match */
|
||
|
if ( font_height == s_device_fonts[font].font_params.font_height &&
|
||
|
load_raster_font(
|
||
|
s_device_fonts[font].font_params.data,
|
||
|
s_device_fonts[font].font_params.data_len,
|
||
|
&s_device_fonts[font]._raster_font) != 0)
|
||
|
{
|
||
|
return VG_LITE_INVALID_ARGUMENT;
|
||
|
}
|
||
|
}
|
||
|
return VG_LITE_SUCCESS;
|
||
|
}
|
||
|
return VG_LITE_INVALID_ARGUMENT;
|
||
|
}
|
||
|
|
||
|
|
||
|
vg_lite_font_t vg_lite_find_font(
|
||
|
char *font_name_list,
|
||
|
eFontWeight_t font_weight,
|
||
|
eFontStretch_t font_stretch,
|
||
|
eFontStyle_t font_style,
|
||
|
int font_height)
|
||
|
{
|
||
|
int i;
|
||
|
char tmp_data;
|
||
|
int font_found = 0;
|
||
|
int end_pos = 0; /* End position of font name */
|
||
|
char *font_name;
|
||
|
/*
|
||
|
printf("Font params: [%s],%d, %d, %d, %d\n",
|
||
|
font_name_list,
|
||
|
font_weight,
|
||
|
font_stretch,
|
||
|
font_style,
|
||
|
font_height);
|
||
|
*/
|
||
|
|
||
|
/* While probing font, if required font is found, then
|
||
|
only keep that name in supplied font list */
|
||
|
|
||
|
/* Split and extract font name one-by-one */
|
||
|
font_name = font_name_list;
|
||
|
while (font_found == 0 &&
|
||
|
font_name[end_pos] != '\0')
|
||
|
{
|
||
|
tmp_data = '\0';
|
||
|
/* Scan for seperator */
|
||
|
while (font_name[end_pos] != '\0') {
|
||
|
if (font_name[end_pos] == ',' || font_name[end_pos] == ' ' ||
|
||
|
font_name[end_pos] == '\t')
|
||
|
{
|
||
|
tmp_data = font_name[end_pos];
|
||
|
font_name[end_pos] = '\0';
|
||
|
break;
|
||
|
}
|
||
|
end_pos++;
|
||
|
}
|
||
|
|
||
|
/* Search for exact font-name match */
|
||
|
for (i=0; i<__COUNTOF(s_device_fonts); i++) {
|
||
|
if (s_device_fonts[i].valid == 0)
|
||
|
continue;
|
||
|
|
||
|
/* For vector font only compare name */
|
||
|
if (s_device_fonts[i].font_params.font_type == eFontTypeVector ) {
|
||
|
if ( strlen(font_name) > 0 &&
|
||
|
strcmp(font_name,
|
||
|
s_device_fonts[i].font_params.name) == 0)
|
||
|
{
|
||
|
font_name[end_pos] = tmp_data; /* Restor delimeter */
|
||
|
return i;
|
||
|
}
|
||
|
} else {
|
||
|
/* For raster font compare all properties */
|
||
|
if (s_device_fonts[i].font_params.font_weight == font_weight &&
|
||
|
s_device_fonts[i].font_params.font_stretch == font_stretch &&
|
||
|
s_device_fonts[i].font_params.font_style == font_style )
|
||
|
{
|
||
|
if ( strlen(font_name) > 0 &&
|
||
|
strcmp(font_name,
|
||
|
s_device_fonts[i].font_params.name) == 0)
|
||
|
{
|
||
|
font_name[end_pos] = tmp_data; /* Restor delimeter */
|
||
|
|
||
|
if (s_device_fonts[i].font_params.font_height == font_height)
|
||
|
{
|
||
|
return i;
|
||
|
}
|
||
|
/* Update font_name_list to improve future searches */
|
||
|
strncpy(font_name_list, font_name, strlen(font_name)+1);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
/* Continue searching for other font entries */
|
||
|
font_name[end_pos] = tmp_data;
|
||
|
font_name += (end_pos + 1);
|
||
|
end_pos = 0;
|
||
|
}
|
||
|
printf("WARNING: [%s] Font not found\r\n",font_name_list);
|
||
|
|
||
|
return VG_LITE_INVALID_FONT;
|
||
|
}
|
||
|
|
||
|
void vg_lite_text_init(void)
|
||
|
{
|
||
|
static int font_table_ready = 0;
|
||
|
|
||
|
if (font_table_ready)
|
||
|
return;
|
||
|
|
||
|
/* Initialize font table */
|
||
|
memset(s_device_fonts, 0, MAX_SYSTEM_FONTS * sizeof(font_info_internal_t));
|
||
|
font_table_ready = 1;
|
||
|
}
|
||
|
|
||
|
/* Read-Write 8-bit unsigned int data */
|
||
|
int read_8b(bufferred_reader_t * f, uint8_t* pdata)
|
||
|
{
|
||
|
bufferred_fread(pdata, 1, 1, f);
|
||
|
TRACE_DBG(("%d) 8b: fp=%08x %d %d\r\n", DBG_INC_ID(),
|
||
|
bufferred_ftell(f) - 1, 1, *pdata));
|
||
|
return 1;
|
||
|
}
|
||
|
|
||
|
/* Read-Write 16-bit unsigned int data */
|
||
|
int read_16b(bufferred_reader_t * f, uint16_t* pword)
|
||
|
{
|
||
|
uint8_t buf[4];
|
||
|
uint16_t word;
|
||
|
|
||
|
bufferred_fread(buf, 2, 1, f);
|
||
|
word = 0; word += buf[1];
|
||
|
word <<= 8; word += buf[0];
|
||
|
|
||
|
TRACE_DBG(("%d) 16b: fp=%08x %d %d\r\n", DBG_INC_ID(),
|
||
|
bufferred_ftell(f)-2, 2, word));
|
||
|
*pword = word;
|
||
|
return 2;
|
||
|
}
|
||
|
|
||
|
/* Read-write 32-bit unsigned int data */
|
||
|
int read_32b(bufferred_reader_t * f, uint32_t* pword)
|
||
|
{
|
||
|
uint8_t buf[4];
|
||
|
uint32_t word;
|
||
|
|
||
|
bufferred_fread(buf, 4, 1, f);
|
||
|
word = 0; word += buf[3];
|
||
|
word <<= 8; word += buf[2];
|
||
|
word <<= 8; word += buf[1];
|
||
|
word <<= 8; word += buf[0];
|
||
|
|
||
|
*pword = word;
|
||
|
TRACE_DBG(("%d) 32b: fp=%08x %d %d\r\n", DBG_INC_ID(),
|
||
|
bufferred_ftell(f) - 4, 4,
|
||
|
word));
|
||
|
return 4;
|
||
|
}
|
||
|
|
||
|
int read_16b_blob(bufferred_reader_t * f, uint16_t** ary, uint32_t* ary_len)
|
||
|
{
|
||
|
uint16_t blob_len = 0;
|
||
|
|
||
|
*ary_len = 0;
|
||
|
bufferred_fread(&blob_len, 1, sizeof(uint16_t), f);
|
||
|
*ary = (uint16_t *)RCD_ALLOC(blob_len * sizeof(uint16_t)); /* Malloc must be aligned on 2 byte boundary */
|
||
|
if (*ary == NULL) {
|
||
|
TRACE_ERR(("ERROR: malloc failed\n"));;
|
||
|
return VG_LITE_OUT_OF_MEMORY;
|
||
|
}
|
||
|
if ((((unsigned long)*ary) & 0x1) != 0) {
|
||
|
TRACE_ERR(("ERROR: malloc pointer not 2 byte aligned\n"));;
|
||
|
return VG_LITE_NOT_ALIGNED;
|
||
|
}
|
||
|
TRACE_DBG(("%d ) 16b_blob: fp=%08x %d\r\n", DBG_INC_ID(), bufferred_ftell(f)-2,
|
||
|
(int)blob_len));
|
||
|
bufferred_fread(*ary, 2, blob_len, f);
|
||
|
*ary_len = blob_len * 2;
|
||
|
|
||
|
return blob_len + 2; /* Actual bytes read from file */
|
||
|
}
|
||
|
|
||
|
int read_8b_blob(bufferred_reader_t * f, uint8_t** ary, uint32_t *ary_len)
|
||
|
{
|
||
|
uint16_t blob_len = 0;
|
||
|
uint8_t* p_tmp = (uint8_t *)NULL;
|
||
|
bufferred_fread(&blob_len, 1, sizeof(uint16_t), f);
|
||
|
//TRACE_DBG(("%d) 8b_blob: %d\r\n", DBG_INC_ID(), blob_len));
|
||
|
p_tmp = (uint8_t *)RCD_ALLOC(blob_len+1);
|
||
|
if (p_tmp == NULL) {
|
||
|
TRACE_ERR(("ERROR: malloc failed\n"));;
|
||
|
return VG_LITE_OUT_OF_MEMORY;
|
||
|
}
|
||
|
TRACE_DBG(("%d ) 8b_blob: fp=%08x %d\r\n", DBG_INC_ID(), bufferred_ftell(f)-2,
|
||
|
(int)blob_len));
|
||
|
bufferred_fread(p_tmp, 1, blob_len, f);
|
||
|
p_tmp[blob_len] = 0;
|
||
|
*ary = p_tmp;
|
||
|
|
||
|
return blob_len + 2; /* Actual bytes read from file */
|
||
|
}
|
||
|
|
||
|
#define EXIT_IF_NEGATIVE(param) if ((ret = param) < 0) return ret;
|
||
|
|
||
|
int read_rle_font_header(bufferred_reader_t * f, struct mf_font_s* font)
|
||
|
{
|
||
|
int raw_header_offset = 0;
|
||
|
struct mf_rlefont_s* mfont = (struct mf_rlefont_s*)font;
|
||
|
uint32_t size = 0;
|
||
|
int ret = 0;
|
||
|
|
||
|
TRACE_DBG(("** %s\r\n", __FUNCTION__));
|
||
|
DBG_SET_ID(0);
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_8b_blob(f, (uint8_t **)&font->full_name, &size));
|
||
|
raw_header_offset += ret; /* font.full_name */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_8b_blob(f, (uint8_t **)&font->short_name, &size));
|
||
|
raw_header_offset += ret; /* font.short_name */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_8b(f, &font->width));
|
||
|
raw_header_offset += 1; /* font.width */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_8b(f, &font->height));
|
||
|
raw_header_offset += 1; /* font.height */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_8b(f, &font->min_x_advance));
|
||
|
raw_header_offset += 1; /* font.min_x_advance */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_8b(f, &font->max_x_advance));
|
||
|
raw_header_offset += 1; /* font.max_x_advance */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_8b(f, (uint8_t *)&font->baseline_x));
|
||
|
raw_header_offset += 1; /* font.baseline_x */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_8b(f, &font->baseline_y));
|
||
|
raw_header_offset += 1; /* font.baseline_y */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_8b(f, &font->line_height));
|
||
|
raw_header_offset += 1; /* font.line_height */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_8b(f, &font->flags));
|
||
|
raw_header_offset += 1; /* font.flags */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_16b(f, &font->fallback_character));
|
||
|
raw_header_offset += 2; /* font.fallback_character */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_8b(f, &(mfont->version)));
|
||
|
raw_header_offset += 1; /* mf_rlefont_s.version */
|
||
|
|
||
|
/* Other mf_rlefont_s variables */
|
||
|
uint16_t value = 0;
|
||
|
EXIT_IF_NEGATIVE(read_16b(f, &value)); //&mfont->dictionary_data_size));
|
||
|
mfont->dictionary_data_size = value;
|
||
|
raw_header_offset += 2; /* mf_rlefont_s.dictionary_data_size */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_32b(f, &mfont->dictionary_data_fp_offset));
|
||
|
raw_header_offset += 4; /* mf_rlefont_s.dictionary_data_fp_offset */
|
||
|
|
||
|
value = 0;
|
||
|
EXIT_IF_NEGATIVE(read_16b(f, &value)); //mfont->dictionary_offsets_size));
|
||
|
mfont->dictionary_offsets_size = value;
|
||
|
raw_header_offset += 2; /* mf_rlefont_s.dictionary_data_size */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_32b(f, &mfont->dictionary_offsets_fp_offset));
|
||
|
raw_header_offset += 4; /* mf_rlefont_s.dictionary_data_fp_offset */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_8b(f, &mfont->rle_entry_count));
|
||
|
raw_header_offset += 1; /* mf_rlefont_s.rle_entry_count */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_8b(f, &mfont->dict_entry_count));
|
||
|
raw_header_offset += 1; /* mf_rlefont_s.dict_entry_count */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_8b(f, &mfont->char_range_count));
|
||
|
raw_header_offset += 1; /* mf_rlefont_s.char_range_count */
|
||
|
|
||
|
mfont->char_ranges = (struct mf_rlefont_char_range_s *)RCD_ALLOC(sizeof(struct mf_rlefont_char_range_s)* mfont->char_range_count);
|
||
|
memset(mfont->char_ranges, 0, sizeof(struct mf_rlefont_char_range_s) * mfont->char_range_count);
|
||
|
|
||
|
/* Skip size of ranges */
|
||
|
for (int r = 0; r < mfont->char_range_count; r++) {
|
||
|
EXIT_IF_NEGATIVE(read_16b(f, &mfont->char_ranges[r].first_char));
|
||
|
raw_header_offset += 2; /* mf_rlefont_s.char_ranges[r].first_char */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_16b(f, &mfont->char_ranges[r].char_count));
|
||
|
raw_header_offset += 2; /* mf_rlefont_s.char_ranges[r].char_count */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_32b(f, &mfont->char_ranges[r].glyph_offsets_fp_offset));
|
||
|
raw_header_offset += 4; /* mf_rlefont_s.char_ranges[r].glyph_offsets_fp_offset */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_32b(f, &mfont->char_ranges[r].glyph_offsets_size));
|
||
|
raw_header_offset += 4; /* mf_rlefont_s.char_ranges[r].glyph_offsets_size */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_32b(f, &mfont->char_ranges[r].glyph_data_fp_offset));
|
||
|
raw_header_offset += 4; /* mf_rlefont_s.char_ranges[r].glyph_offsets_fp_offset */
|
||
|
|
||
|
EXIT_IF_NEGATIVE(read_32b(f, &mfont->char_ranges[r].glyph_data_size));
|
||
|
raw_header_offset += 4; /* mf_rlefont_s.char_ranges[r].glyph_offsets_size */
|
||
|
}
|
||
|
return raw_header_offset;
|
||
|
}
|
||
|
|
||
|
/* Writes a BMP file. The data is assumed to be 8-bit grayscale. */
|
||
|
int read_rle_font_from_buffer(char *buff, int size, struct mf_font_s* font)
|
||
|
{
|
||
|
struct mf_rlefont_s* mfont = (struct mf_rlefont_s*)font;
|
||
|
bufferred_reader_t f_obj;
|
||
|
bufferred_reader_t * f = &f_obj;
|
||
|
int raw_header_offset = 0;
|
||
|
int fp_offset;
|
||
|
int ret;
|
||
|
|
||
|
DBG_SET_ID(0);
|
||
|
|
||
|
/* No need to dynamically allocate small descriptor */
|
||
|
if ( bufferred_fopen(f, buff, size) < 0 ) {
|
||
|
/* Font file open failed */
|
||
|
return VG_LITE_INVALID_ARGUMENT;
|
||
|
}
|
||
|
|
||
|
raw_header_offset = read_rle_font_header(f, font);
|
||
|
if (mfont->dictionary_data_fp_offset != raw_header_offset) {
|
||
|
TRACE_ERR(("ERROR: dictonary offset is different"));
|
||
|
}
|
||
|
TRACE_DBG(("** %s\r\n", __FUNCTION__));
|
||
|
DBG_SET_ID(0);
|
||
|
|
||
|
/* Skip header portion */
|
||
|
bufferred_fseek(f, raw_header_offset, SEEK_SET);
|
||
|
/* Write dictionary entries */
|
||
|
fp_offset = raw_header_offset;
|
||
|
TRACE_DBG(("dictionary_data_fp_offset=%08x %08x\r\n",
|
||
|
mfont->dictionary_data_fp_offset, bufferred_ftell(f)));
|
||
|
//mfont->dictionary_data_fp_offset = fp_offset;
|
||
|
EXIT_IF_NEGATIVE(read_8b_blob(f, &mfont->dictionary_data,
|
||
|
&mfont->dictionary_data_size));
|
||
|
fp_offset += mfont->dictionary_data_size + 2;
|
||
|
|
||
|
//mfont->dictionary_offsets_fp_offset = fp_offset;
|
||
|
TRACE_DBG(("dictionary_offsets_fp_offset=%08x %08x\r\n",
|
||
|
mfont->dictionary_offsets_fp_offset, bufferred_ftell(f)));
|
||
|
EXIT_IF_NEGATIVE(read_16b_blob(f, &mfont->dictionary_offsets,
|
||
|
&mfont->dictionary_offsets_size));
|
||
|
fp_offset += mfont->dictionary_offsets_size + 2;
|
||
|
|
||
|
/* Write range entries */
|
||
|
for (int r = 0; r < mfont->char_range_count; r++) {
|
||
|
//mfont->char_ranges[r].glyph_offsets_fp_offset = fp_offset;
|
||
|
TRACE_DBG(("mfont->char_ranges[%d].glyph_offsets=%08x %08x\r\n", r,
|
||
|
mfont->char_ranges[r].glyph_offsets_fp_offset, bufferred_ftell(f)));
|
||
|
EXIT_IF_NEGATIVE(read_16b_blob(f, &mfont->char_ranges[r].glyph_offsets,
|
||
|
&mfont->char_ranges[r].glyph_offsets_size));
|
||
|
fp_offset += mfont->char_ranges[r].glyph_offsets_size + 2;
|
||
|
|
||
|
//mfont->char_ranges[r].glyph_data_fp_offset = fp_offset;
|
||
|
TRACE_DBG(("mfont->char_ranges[%d].glyph_data_fp_offset=%08x %08x\r\n",
|
||
|
r,
|
||
|
mfont->char_ranges[r].glyph_data_fp_offset, bufferred_ftell(f)));
|
||
|
EXIT_IF_NEGATIVE(read_8b_blob(f, &mfont->char_ranges[r].glyph_data,\
|
||
|
&mfont->char_ranges[r].glyph_data_size));
|
||
|
fp_offset += mfont->char_ranges[r].glyph_data_size + 2;
|
||
|
}
|
||
|
|
||
|
bufferred_fclose(f);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int load_raster_font(char *data, int data_len, struct mf_font_s** font)
|
||
|
{
|
||
|
int ret;
|
||
|
|
||
|
/* Allocate font memory */
|
||
|
*font = (struct mf_font_s*)RCD_ALLOC(sizeof(struct mf_rlefont_s));
|
||
|
if (*font == NULL) {
|
||
|
return VG_LITE_OUT_OF_MEMORY;
|
||
|
}
|
||
|
memset(*font, 0, sizeof(struct mf_rlefont_s));
|
||
|
|
||
|
/* Load font from file */
|
||
|
ret = read_rle_font_from_buffer(data,
|
||
|
data_len, *font);
|
||
|
if (ret < 0) {
|
||
|
return ret;
|
||
|
}
|
||
|
|
||
|
/* Update generic char width pointers of mculib */
|
||
|
uint8_t mf_rlefont_character_width(const struct mf_font_s* font,
|
||
|
uint16_t character);
|
||
|
uint8_t mf_rlefont_render_character(const struct mf_font_s* font,
|
||
|
int16_t x0, int16_t y0,
|
||
|
uint16_t character,
|
||
|
mf_pixel_callback_t callback,
|
||
|
void* state);
|
||
|
|
||
|
(*font)->character_width = &mf_rlefont_character_width;
|
||
|
(*font)->render_character = &mf_rlefont_render_character;
|
||
|
|
||
|
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int free_rle_font_memory(struct mf_font_s** font)
|
||
|
{
|
||
|
struct mf_rlefont_s* mfont = (struct mf_rlefont_s*)(*font);
|
||
|
|
||
|
RCD_FREE(mfont->font.full_name);
|
||
|
RCD_FREE(mfont->font.short_name);
|
||
|
RCD_FREE(mfont->dictionary_data);
|
||
|
RCD_FREE(mfont->dictionary_offsets);
|
||
|
for (int r = 0; r < mfont->char_range_count; r++) {
|
||
|
RCD_FREE(mfont->char_ranges[r].glyph_offsets);
|
||
|
RCD_FREE(mfont->char_ranges[r].glyph_data);
|
||
|
}
|
||
|
#ifdef DEBUG_RESET_DATASTRUCTURE_ON_FREE
|
||
|
memset(mfont->char_ranges);
|
||
|
#endif
|
||
|
RCD_FREE(mfont->char_ranges);
|
||
|
|
||
|
#ifdef DEBUG_RESET_DATASTRUCTURE_ON_FREE
|
||
|
memset(mfont);
|
||
|
#endif
|
||
|
RCD_FREE(mfont);
|
||
|
|
||
|
*font = NULL;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
void vg_lite_unload_font_data(void)
|
||
|
{
|
||
|
for(int i=0; i<MAX_SYSTEM_FONTS; i++)
|
||
|
{
|
||
|
vg_lite_free_font_memory(i);
|
||
|
}
|
||
|
|
||
|
return;
|
||
|
}
|