Files
MiniGUI/src/font/scripteasy.c
T

747 lines
18 KiB
C

///////////////////////////////////////////////////////////////////////////////
//
// IMPORTANT NOTICE
//
// The following open source license statement does not apply to any
// entity in the Exception List published by FMSoft.
//
// For more information, please visit:
//
// https://www.fmsoft.cn/exception-list
//
//////////////////////////////////////////////////////////////////////////////
/*
* This file is part of MiniGUI, a mature cross-platform windowing
* and Graphics User Interface (GUI) support system for embedded systems
* and smart IoT devices.
*
* Copyright (C) 2002~2018, Beijing FMSoft Technologies Co., Ltd.
* Copyright (C) 1998~2002, WEI Yongming
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Or,
*
* As this program is a library, any link to this program must follow
* GNU General Public License version 3 (GPLv3). If you cannot accept
* GPLv3, you need to be licensed from FMSoft.
*
* If you have got a commercial license of this program, please use it
* under the terms and conditions of the commercial license.
*
* For more information about the commercial license, please refer to
* <http://www.minigui.com/blog/minigui-licensing-policy/>.
*/
#include <assert.h>
#include <string.h>
#include "common.h"
#include "minigui.h"
#include "gdi.h"
#include "misc.h"
#include "devfont.h"
#include "charset.h"
#include "fontname.h"
#ifdef _MGFONT_SEF
#include "palette.h"
#include "se_minigui.h"
static const unsigned char* PALETTE_TABLE[34] =
{
0,
PALETTE1A, PALETTE1B, PALETTE1C, PALETTE1D,
PALETTE2A, PALETTE2B, PALETTE2C, PALETTE2D,
PALETTE3A, PALETTE3B, PALETTE3C, PALETTE3D,
PALETTE4A, PALETTE4B, PALETTE4C, PALETTE4D,
PALETTE5A, PALETTE5B, PALETTE5C, PALETTE5D,
PALETTE6A, PALETTE6B, PALETTE6C, PALETTE6D,
PALETTE7A, PALETTE7B, PALETTE7C, PALETTE7D,
PALETTE8A, PALETTE8B, PALETTE8C, PALETTE8D
};
#define PALETTE_TABLE_SIZE (sizeof(PALETTE_TABLE) / sizeof(unsigned char*))
static int current_palette_index = 0;
#ifdef SE_PALETTE_AUTO_ADJUST
static const unsigned char *current_palette = 0;
#define SE_PALETTE_BW PALETTEBW
#define SE_PALETTE_WB 0
#endif
static DEVFONT *se_dev_fonts = NULL;
static FONTOPS scripteasy_font_ops;
static unsigned char is_se_initialized = 0;
static pthread_mutex_t se_mutex;
#define SE_MINIGUI_TRACE 0
static void init_lock(void)
{
assert(!is_se_initialized);
pthread_mutex_init(&se_mutex, NULL);
}
static void destroy_lock(void)
{
assert(is_se_initialized);
pthread_mutex_destroy(&se_mutex);
}
static void lock(void)
{
assert(is_se_initialized);
pthread_mutex_lock(&se_mutex);
}
static void unlock(void)
{
assert(is_se_initialized);
pthread_mutex_unlock(&se_mutex);
}
static BOOL load_fonts(void)
{
int i;
int font_table_size = se_font_desc.font_name_map_size;
BOOL result = FALSE;
#if SE_MINIGUI_TRACE
printf("load_fonts, font_table_size: %d...\n", font_table_size);
#endif
se_dev_fonts = calloc (font_table_size, sizeof (DEVFONT));
for (i = 0; i < font_table_size; i++) {
char charset[LEN_LOGFONT_NAME_FIELD + 1];
CHARSETOPS *charset_ops;
const char *font_name;
int font_id;
font_name = se_font_desc.name_map[i].font_name;
font_id = se_font_desc.name_map[i].font_id;
if (!fontGetCharsetFromName (font_name, charset)) {
fprintf (stderr, "GDI: Invalid font name (charset): %s.\n",
font_name);
goto exit;
}
if ((charset_ops = GetCharsetOps (charset)) == NULL) {
fprintf (stderr, "GDI: Not supported charset: %s.\n", charset);
goto exit;
}
strncpy (se_dev_fonts[i].name, font_name, LEN_DEVFONT_NAME);
se_dev_fonts[i].name [LEN_DEVFONT_NAME] = '\0';
se_dev_fonts[i].font_ops = &scripteasy_font_ops;
se_dev_fonts[i].charset_ops = charset_ops;
se_dev_fonts[i].data = (void*)font_id;
#if 1
fprintf (stderr, "GDI: TTFDevFont %i: %s.\n", i, se_dev_fonts[i].name);
#endif
}
/* houhh 20090112, surport the other GB2312,UTF-8 such font setting.*/
for (i = 0; i < font_table_size; i++) {
int nr_charsets;
char charsets [LEN_UNIDEVFONT_NAME + 1];
if (se_dev_fonts [i].charset_ops->bytes_maxlen_char > 1) {
font_AddMBDevFont (se_dev_fonts + i);
font_AddSBDevFont (se_dev_fonts + i);
}
else
font_AddSBDevFont (se_dev_fonts + i);
fontGetCharsetPartFromName (se_dev_fonts[i].name, charsets);
if ((nr_charsets = charsetGetCharsetsNumber (charsets)) > 1) {
int j;
for (j = 1; j < nr_charsets; j++) {
char charset [LEN_LOGFONT_NAME_FIELD + 1];
CHARSETOPS* charset_ops;
DEVFONT* new_devfont;
charsetGetSpecificCharset (charsets, j, charset);
if ((charset_ops = GetCharsetOpsEx (charset)) == NULL)
continue;
new_devfont = calloc (1, sizeof (DEVFONT));
memcpy (new_devfont, se_dev_fonts + i, sizeof (DEVFONT));
new_devfont->charset_ops = charset_ops;
new_devfont->relationship = se_dev_fonts + i;
if (new_devfont->charset_ops->bytes_maxlen_char > 1)
font_AddMBDevFont (new_devfont);
else
font_AddSBDevFont (new_devfont);
}
}
}
result = TRUE;
exit:
#if SE_MINIGUI_TRACE
printf("load_fonts complete, result: %s...\n", result ? "success" : "fail");
#endif
return result;
}
static BOOL init(
void *mem_pool,
int mem_pool_size,
void *cache_mem_pool,
int cache_mem_pool_size)
{
SeInitInfo init_info;
int result;
se_minigui_init_fonts();
//
// SeInitInfo initialization
//
memset( &init_info,0,sizeof(init_info) );
init_info.language = SE_LANG_ZH_CN;
init_info.mem_pool = (void*)mem_pool;
init_info.mem_pool_size = mem_pool_size;
init_info.font_table = se_font_desc.font_table;
init_info.logical_font_table = se_font_desc.logical_font_table;
#ifdef SE_FONT_DYNAMIC_LOADING_SUPPORT
init_info.font_access_callback = se_minigui_read_font;
#endif
init_info.cache_mem_pool = (void*)cache_mem_pool;
init_info.cache_mem_pool_size = cache_mem_pool_size;
result = se_minigui_initialize( &init_info );
if(result != SE_STATUS_OK)
return FALSE;
return TRUE;
}
#ifdef __NOUNIX__
typedef struct{
unsigned int get_imei_value;
unsigned int read_nvram;
unsigned int get_copyright;
unsigned int trace;
}se_ip_param;
int tp_nvram_read_u8(unsigned int offset, unsigned char *data, unsigned char as);
int app_svr_get_imei_str (char *imei);
char * GetSystemCopyRightStr (char * pBuf);
static void initialize_cert(void)
{
se_ip_param param = {0};
param.get_copyright = (unsigned int)GetSystemCopyRightStr;
param.get_imei_value = (unsigned int)app_svr_get_imei_str;
param.read_nvram = (unsigned int)tp_nvram_read_u8;
se_minigui_set_chip_param(&param);
}
#endif
SE_EXPORT BOOL font_InitializeScripteasy(void)
{
#if SE_MINIGUI_TRACE
printf("in font_InitializeScripteasy...\n");
#endif
if(is_se_initialized)
return TRUE;
if(se_font_desc.font_table_size < 1)
return TRUE;
if(!load_fonts())
return FALSE;
if(!init(se_minigui_mem_pool, se_minigui_mem_pool_size, se_minigui_cache_mem_pool, se_minigui_cache_mem_pool_size))
return FALSE;
init_lock();
is_se_initialized = 1;
#if SE_MINIGUI_TRACE
printf("font_InitializeScripteasy complete...\n");
#endif
#ifdef __NOUNIX__
initialize_cert();
#endif
return TRUE;
}
SE_EXPORT void font_UninitializeScripteasy(void)
{
#ifndef SE_OPT_ARM
printf("in font_UninitializeScripteasy...\n");
#endif
if(!is_se_initialized)
return;
se_minigui_cleanup();
se_minigui_destroy_fonts();
if(se_dev_fonts != NULL)
{
free(se_dev_fonts);
se_dev_fonts = NULL;
}
destroy_lock();
is_se_initialized = 0;
}
static void convert_log_font(SeLogFont *selogfont, const LOGFONT *logfont, const DEVFONT *devfont)
{
selogfont->size = logfont->size;
selogfont->id = (unsigned char)(int)devfont->data;
selogfont->attr = 0;
if(selogfont->id > 0)
selogfont->attr |= SE_LOGFONT_PREFERRED;
/*
if(logfont->style & FS_WEIGHT_BOLD)
selogfont->attr |= SE_LOGFONT_BOLD;
if(logfont->style & FS_SLANT_ITALIC)
selogfont->attr |= SE_LOGFONT_ITALIC;
*/
if(logfont->style & FS_UNDERLINE_LINE)
selogfont->attr |= SE_LOGFONT_UNDERLINE;
if(logfont->style & FS_STRUCKOUT_LINE)
selogfont->attr |= SE_LOGFONT_STRIKETHROUGH;
#if 0// SE_MINIGUI_TRACE
printf("logfont >>> size: %d id: %d attr: 0x%02X\n", selogfont->size, selogfont->id, selogfont->attr);
#endif
}
#if 0
static int get_glyph_width (LOGFONT* logfont, DEVFONT* devfont,
Glyph32 glyph_value, int* px, int* py)
{
seunichar16 wc;
SeLogFont selogfont;
int width;
glyph_value = REAL_GLYPH(glyph_value);
if (devfont->charset_ops->conv_to_uc32)
wc = (*devfont->charset_ops->conv_to_uc32)(glyph_value);
else
wc = glyph_value;
#if SE_MINIGUI_TRACE
printf("in get_glyph_width...\n");
#endif
convert_log_font(&selogfont, logfont, devfont);
lock();
width = se_minigui_get_char_width(&selogfont, wc);
unlock();
#if SE_MINIGUI_TRACE
printf("get_glyph_width complete...\n");
#endif
return width;
}
#endif
static int get_max_width (LOGFONT* logfont, DEVFONT* devfont)
{
return logfont->size;
}
static DWORD get_feature (LOGFONT* logfont, DEVFONT* devfont,
enum devfont_feature feature)
{
switch (feature) {
case DEVFONT_FEATURE_MARK_BBOX:
return 0;
}
return 0;
}
static DWORD get_glyph_bmptype (LOGFONT* logfont, DEVFONT* devfont)
{
if (logfont->style & FS_WEIGHT_BOOK)
return DEVFONTGLYPHTYPE_GREYBMP;
return DEVFONTGLYPHTYPE_MONOBMP;
}
static int get_ave_width (LOGFONT* logfont, DEVFONT* devfont)
{
return logfont->size;
}
static int get_font_height (LOGFONT* logfont, DEVFONT* devfont)
{
return logfont->size;
}
static int get_font_size (LOGFONT* logfont, DEVFONT* devfont, int expect)
{
return logfont->size;
}
static int get_font_ascent (LOGFONT* logfont, DEVFONT* devfont)
{
SeLogFont selogfont;
int ascent;
convert_log_font(&selogfont, logfont, devfont);
lock();
// ascent = se_minigui_get_font_ascent(&selogfont);
ascent = selogfont.size - selogfont.size / 4;
unlock();
#if SE_MINIGUI_TRACE
printf("get_font_ascent complete. ascent: %d...\n", ascent);
#endif
return ascent;
}
static int get_font_descent (LOGFONT* logfont, DEVFONT* devfont)
{
SeLogFont selogfont;
int descent;
convert_log_font(&selogfont, logfont, devfont);
lock();
// descent = se_minigui_get_font_descent(&selogfont);
descent = selogfont.size / 4;
unlock();
#if SE_MINIGUI_TRACE
printf("get_font_descent complete. descent: %d...\n", descent);
#endif
return descent;
//return logfont->size - get_font_ascent (logfont, devfont);
}
static const void* get_glyph_greybitmap (LOGFONT* logfont, DEVFONT* devfont,
Glyph32 glyph_value, int* pitch, unsigned short* scale)
{
seunichar16 wc;
SeLogFont selogfont;
const void *result;
#if SE_MINIGUI_TRACE
printf("in get_glyph_greybitmap....\n");
#endif
glyph_value = REAL_GLYPH(glyph_value);
if (devfont->charset_ops->conv_to_uc32)
wc = (*devfont->charset_ops->conv_to_uc32)(glyph_value);
else
wc = glyph_value;
convert_log_font(&selogfont, logfont, devfont);
lock();
result = se_minigui_get_char_pixmap(&selogfont, wc, pitch);
unlock();
#if SE_MINIGUI_TRACE
printf("[GET_CHAR_PIXMAP_RESULT] wc: 0x%04X size: %d attr: %d id: %d pitch: %d\n",
wc,
selogfont.size,
selogfont.attr,
selogfont.id,
pitch);
#endif
if(scale)
*scale = 1;
return result;
}
static const void* get_glyph_monobitmap (LOGFONT* logfont, DEVFONT* devfont,
Glyph32 glyph_value, int* pitch, unsigned short* scale)
{
seunichar16 wc;
SeLogFont selogfont;
const void *result = NULL;
#if SE_MINIGUI_TRACE
printf("in get_char_bitmap....\n");
#endif
glyph_value = REAL_GLYPH(glyph_value);
if (devfont->charset_ops->conv_to_uc32)
wc = (*devfont->charset_ops->conv_to_uc32)(glyph_value);
else
wc = glyph_value;
convert_log_font(&selogfont, logfont, devfont);
selogfont.attr |= SE_LOGFONT_MONO;
lock();
result = se_minigui_get_char_pixmap(&selogfont, wc, pitch);
unlock();
if(scale)
*scale = 1;
return result;
}
static int get_glyph_bbox (LOGFONT* logfont, DEVFONT* devfont,
Glyph32 glyph_value, int* px, int* py,
int* pwidth, int* pheight)
{
seunichar16 wc;
SeLogFont selogfont;
int result = 0;
if(px == 0 && py == 0 && pwidth == 0 && pheight == 0)
return 1;
glyph_value = REAL_GLYPH(glyph_value);
if (devfont->charset_ops->conv_to_uc32)
wc = (*devfont->charset_ops->conv_to_uc32)(glyph_value);
else
wc = glyph_value;
convert_log_font(&selogfont, logfont, devfont);
lock();
result = se_minigui_get_char_bbox(&selogfont, wc, px, py, pwidth, pheight);
unlock();
#if SE_MINIGUI_TRACE
printf("get_char_bbox result. wc: 0x%04X x: %d y: %d w: %d h: %d\n", wc, px ? *px : 0, py ? *py : 0,
pwidth ? *pwidth : 0, pheight ? *pheight : 0);
#endif
return result;
}
static int get_glyph_advance (LOGFONT* logfont, DEVFONT* devfont,
Glyph32 glyph_value, int* px, int* py)
{
seunichar16 wc;
SeLogFont selogfont;
int x = 0, y = 0;
glyph_value = REAL_GLYPH(glyph_value);
if (devfont->charset_ops->conv_to_uc32)
wc = (*devfont->charset_ops->conv_to_uc32)(glyph_value);
else
wc = glyph_value;
convert_log_font(&selogfont, logfont, devfont);
lock();
se_minigui_get_char_advance(&selogfont, wc, &x, &y);
unlock();
#if SE_MINIGUI_TRACE
printf("get_glyph_advance result. wc: 0x%04X x: %d y: %d\n", wc, x, y);
#endif
if (px)
*px += x;
return x;
}
static BOOL is_glyph_existed (LOGFONT* logfont, DEVFONT* devfont, Glyph32 glyph_value)
{
int uni_char;
int x, y, width, height;
glyph_value = REAL_GLYPH(glyph_value);
if(devfont->charset_ops->conv_to_uc32)
uni_char = (*devfont->charset_ops->conv_to_uc32) (glyph_value);
else
uni_char = glyph_value;
if (!get_glyph_bbox (logfont, devfont,
glyph_value, &x, &y, &width, &height))
return FALSE;
else
return TRUE;
}
static int is_rotatable (LOGFONT* logfont, DEVFONT* devfont, int rot_desired)
{
return rot_desired;
}
/**************************** Global data ************************************/
static FONTOPS scripteasy_font_ops = {
get_feature,
get_glyph_bmptype,
get_ave_width,
get_max_width,
get_font_height,
get_font_size,
get_font_ascent,
get_font_descent,
is_glyph_existed,
get_glyph_advance,
get_glyph_bbox,
get_glyph_monobitmap,
get_glyph_greybitmap,
NULL,
NULL,
NULL,
NULL,
is_rotatable,
NULL,
NULL
};
/***********************************Pallete Processing*************************/
SE_EXPORT int se_set_palette_index(int index)
{
if(index >= 0 && index <= PALETTE_TABLE_SIZE)
{
current_palette_index = index;
}
return current_palette_index;
}
SE_EXPORT int se_next_palette(void)
{
current_palette_index++;
if(current_palette_index >= PALETTE_TABLE_SIZE)
current_palette_index = 0;
return current_palette_index;
}
SE_EXPORT int se_previous_palette(void)
{
current_palette_index--;
if(current_palette_index < 0)
current_palette_index = PALETTE_TABLE_SIZE - 1;
return current_palette_index;
}
SE_EXPORT int se_get_current_palette_index(void)
{
return current_palette_index;
}
SE_EXPORT const unsigned char * se_get_current_palette(void)
{
#ifdef SE_PALETTE_AUTO_ADJUST
return current_palette;
#else
return PALETTE_TABLE[current_palette_index];
#endif
}
/* Palette auto adjust routines */
#define YUV_Y(r, g, b) ((299 * (r) + 587 * (g) + 114 * (b)) >> 10)
//extern gal_pixel SeGetPixel(HDC hdc, int x, int y);
#define SeGetPixel(hdc, x, y) GetPixel(hdc, x, y)
void se_switch_palette(
HDC hdc,
int x,
int y,
int w,
int h)
{
#ifdef SE_PALETTE_AUTO_ADJUST
int bkmode;
gal_pixel bg_color;
gal_pixel fg_color;
int yuv1, yuv2;
int r = 0, g = 0, b = 0;
bkmode = GetBkMode(hdc);
fg_color = GetTextColor(hdc);
if (bkmode == BM_TRANSPARENT)
{
gal_pixel colors[4];
int i = 0;
Uint8 rr, gg, bb;
colors[0] = SeGetPixel(hdc, x + 1, y + 1);
colors[1] = SeGetPixel(hdc, x + w - 1, y + 1);
colors[2] = SeGetPixel(hdc, x + 1, y + h - 1);
colors[3] = SeGetPixel(hdc, x + w - 1, y + h -1);
for ( ; i < 4; ++i)
{
Pixel2RGB(hdc, colors[i], &rr, &gg, &bb);
r += rr;
g += gg;
b += bb;
}
r >>= 2;
g >>= 2;
b >>= 2;
}
else
{
bg_color = GetBkColor(hdc);
Pixel2RGB(hdc, bg_color, (Uint8*)&r, (Uint8*)&g, (Uint8*)&b);
}
yuv2 = YUV_Y(r, g, b);
Pixel2RGB(hdc, fg_color, (Uint8*)&r, (Uint8*)&g, (Uint8*)&b);
yuv1 = YUV_Y(r, g, b);
if(yuv2 < yuv1)
{
current_palette = SE_PALETTE_BW;
}
else
{
current_palette = SE_PALETTE_WB;
}
#endif
}
#endif