aboutsummaryrefslogtreecommitdiff
path: root/source/nds/bdf_font.c
diff options
context:
space:
mode:
authorKitty Draper2011-03-05 21:39:25 -0500
committerKitty Draper2011-03-05 21:39:25 -0500
commitd40ae99422e118188a7f48055dc340c6aca022aa (patch)
tree83ab93f49fd9e66e43bcd824091ae1dbcaa0c173 /source/nds/bdf_font.c
downloadsnes9x2005-d40ae99422e118188a7f48055dc340c6aca022aa.tar.gz
snes9x2005-d40ae99422e118188a7f48055dc340c6aca022aa.tar.bz2
snes9x2005-d40ae99422e118188a7f48055dc340c6aca022aa.zip
first commit
Diffstat (limited to 'source/nds/bdf_font.c')
-rw-r--r--source/nds/bdf_font.c1112
1 files changed, 1112 insertions, 0 deletions
diff --git a/source/nds/bdf_font.c b/source/nds/bdf_font.c
new file mode 100644
index 0000000..5da57e3
--- /dev/null
+++ b/source/nds/bdf_font.c
@@ -0,0 +1,1112 @@
+/* bdf_font.c
+ *
+ * Copyright (C) 2010 dking <dking024@gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licens e as
+ * published by the Free Software Foundation; either version 2 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, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+//v1.1
+
+#include <string.h>
+#include "ds2_types.h"
+#include "ds2_malloc.h"
+#include "ds2io.h"
+#include "fs_api.h"
+#include "bdf_font.h"
+#include "gui.h"
+
+
+#define BDF_VERDANA "SYSTEM/verdana.bdf"
+#define BDF_SONG "SYSTEM/song.bdf"
+#define ODF_VERDANA "SYSTEM/verdana.odf"
+#define ODF_SONG "SYSTEM/song.odf"
+
+#define HAVE_ODF
+//#define DUMP_ODF
+
+#define BDF_LIB_NUM 2
+#define ODF_VERSION "1.0"
+
+struct bdflibinfo bdflib_info[BDF_LIB_NUM];
+struct bdffont *bdf_font; //ASCII charactor
+struct bdffont *bdf_nasci; //non-ASCII charactor
+static u32 font_height;
+static u32 fonts_max_height;
+
+/*-----------------------------------------------------------------------------
+------------------------------------------------------------------------------*/
+static u32 bitmap_code(unsigned char *code, unsigned char *bitmap)
+{
+ unsigned char *map;
+ u32 a, b, len;
+
+ len= 0;
+ map= (unsigned char*)bitmap;
+ while(*map)
+ {
+ //character to number, we assume the character can convert to number!
+ if(*map != 0x0A)
+ {
+ if(*map <= 0x39) a= *map - 0x30;
+ else a= *map - 0x37;
+ map++;
+
+ if(*map <= 0x39) b= *map - 0x30;
+ else b= *map - 0x37;
+
+ *code++ = (a << 4) | b;
+ len++;
+ }
+ map++;
+ }
+
+ return len;
+}
+
+/*-----------------------------------------------------------------------------
+------------------------------------------------------------------------------*/
+static u32 hatoi(char *string)
+{
+ char *pt;
+ u32 ret, num;
+
+ pt= string;
+ ret= 0;
+ while(*pt)
+ {
+ num= (((u32)*pt) & 0xFF) - 0x30;
+ if(num <= 0x9)
+ ret= (ret<<4) | num;
+ else if(num <= 0x16)
+ {
+ if(num >= 0x11)
+ ret= (ret<<4) | (num-0x7);
+ else
+ break;
+ }
+ else
+ break;
+ pt++;
+ }
+
+ return ret;
+}
+
+/*-----------------------------------------------------------------------------
+------------------------------------------------------------------------------*/
+/*
+* example
+*
+* STARTCHAR 2264
+* ENCODING 8804
+* SWIDTH 840 0
+* DWIDTH 14 0
+* BBX 10 12 2 1
+* BITMAP
+* 00C0
+* 0300
+* 1C00
+* 6000
+* 8000
+* 6000
+* 1C00
+* 0300
+* 00C0
+* 0000
+* 0000
+* FFC0
+* ENDCHAR
+*/
+
+/*-----------------------------------------------------------------------------
+* filename: bdf file's name, including path
+* start: the coding of first font to parse
+* span: number of fonts begin at start to parse
+* *bdflibinfop: font library information
+* method: font index method; 0-absolut sequence; 1-relative sequence; 2-compact;
+* others reserved
+* return: if error return < 0; else return= char numbers
+------------------------------------------------------------------------------*/
+static int parse_bdf(char *filename, u32 start, u32 span, struct bdflibinfo *bdflibinfop, u32 method)
+{
+ FILE *fp;
+ char string[256];
+ char map[256];
+ char *pt;
+ unsigned char *bitbuff;
+ int num, x_off, y_off, ret;
+ u32 tmp, i, end, length, index;
+ struct bdffont *bdffontp;
+
+ //initial bdflibinfo
+ bdflibinfop -> width= 0;
+ bdflibinfop -> height= 0;
+ bdflibinfop -> start= 0;
+ bdflibinfop -> span= 0;
+ bdflibinfop -> maplen= 0;
+ bdflibinfop -> mapmem= NULL;
+ bdflibinfop -> fonts= NULL;
+
+ fp= fopen(filename, "r"); //Open bdf font library
+ if(fp == NULL)
+ return -1;
+
+ ret= 0;
+ //SIZE
+ while(1)
+ {
+ pt= fgets(string, 255, fp);
+ if(pt == NULL)
+ {
+ ret= -2;
+ goto parse_bdf_error;
+ }
+ if(!(strncasecmp(string, "SIZE ", 5)))
+ break;
+ }
+
+ //FONTBOUNDINGBOX
+ pt= fgets(string, 255, fp);
+ pt += 16;
+ bdflibinfop -> width= atoi(pt);
+ pt = 1 + strchr(pt, ' ');
+ bdflibinfop -> height= atoi(pt);
+ pt = 1 + strchr(pt, ' ');
+ x_off= atoi(pt);
+ pt = 1 + strchr(pt, ' ');
+ y_off= atoi(pt);
+
+ //CHARS
+ while(1)
+ {
+ pt= fgets(string, 255, fp);
+ if(pt == NULL)
+ {
+ ret= -3;
+ goto parse_bdf_error;
+ }
+ if(!(strncasecmp(string, "CHARS ", 6)))
+ break;
+ }
+ pt += 6;
+ ret= atoi(pt);
+
+ bdflibinfop -> start= start;
+ bdflibinfop -> span= span;
+
+ //construct bdf font information
+ bdffontp= (struct bdffont*)malloc(span * sizeof(struct bdffont));
+ if(bdffontp == NULL)
+ {
+ ret= -4;
+ goto parse_bdf_error;
+ }
+ bdflibinfop -> fonts= bdffontp;
+
+ bitbuff= (unsigned char*)malloc((bdflibinfop -> width * bdflibinfop -> height * span) >> 3);
+ if(bitbuff == NULL)
+ {
+ ret= -5;
+ goto parse_bdf_error;
+ }
+ bdflibinfop -> mapmem= bitbuff;
+
+ tmp= bdflibinfop -> width << 16;
+ for(i= 0; i < span; i++)
+ {
+ bdffontp[i].dwidth= tmp;
+ bdffontp[i].bbx= 0;
+ }
+
+ end= start + span;
+ //STARTCHAR START
+ while(1)
+ {
+ pt= fgets(string, 255, fp);
+ if(pt == NULL)
+ {
+ ret= -6;
+ goto parse_bdf_error;
+ }
+ if(!(strncasecmp(string, "STARTCHAR ", 10)))
+ {
+ i= hatoi(pt +10);
+ if(i < start) continue;
+ else if(i < end) break;
+ else //Not found the start
+ {
+ ret= -7;
+ goto parse_bdf_error;
+ }
+ }
+ }
+
+ i= 0;
+ length= 0;
+ while(1)
+ {
+ //ENCODING
+ while(1)
+ {
+ pt= fgets(string, 255, fp);
+ if(pt == NULL) goto parse_bdf_error;
+ if(!(strncasecmp(string, "ENCODING ", 9))) break;
+ }
+
+ pt= string + 9;
+ index= atoi(pt);
+ if(index >= end) break;
+
+ if(method == 0) i= index;
+ else if(method == 1) i= index-start;
+ else i++;
+
+ //SWIDTH
+ pt= fgets(string, 255, fp);
+ if(pt == NULL) {ret= -8; goto parse_bdf_error;}
+
+ //DWIDTH
+ pt= fgets(string, 255, fp);
+ if(pt == NULL) {ret= -9; goto parse_bdf_error;}
+
+ pt += 7;
+ num= atoi(pt);
+ tmp= num << 16;
+ pt= 1+ strchr(pt, ' ');
+ num= atoi(pt);
+ tmp |= num & 0xFFFF;
+
+ bdffontp[i].dwidth= tmp;
+
+ //BBX
+ pt= fgets(string, 255, fp);
+ if(pt == NULL) {ret= -10; goto parse_bdf_error;}
+
+ pt += 4;
+ num= atoi(pt);
+ tmp= num & 0xFF;
+
+ pt= 1+ strchr(pt, ' ');
+ num= atoi(pt);
+ tmp= tmp<<8 | (num & 0xFF);
+
+ pt= 1+ strchr(pt, ' ');
+ num= atoi(pt);
+ num= num - x_off;
+ tmp= tmp<<8 | (num & 0xFF);
+
+ pt= 1+ strchr(pt, ' ');
+ num= atoi(pt);
+ num= num - y_off;
+ tmp= tmp <<8 | (num & 0xFF);
+
+ bdffontp[i].bbx= tmp;
+
+ //BITMAP
+ pt= fgets(string, 255, fp);
+ if(pt == NULL) {ret= -11; goto parse_bdf_error;}
+
+ map[0]= '\0';
+ while(1)
+ {
+ pt= fgets(string, 255, fp);
+ if(pt == NULL) {ret= -12; goto parse_bdf_error;}
+ if(!strncasecmp(pt, "ENDCHAR", 7)) break;
+ strcat(map, pt);
+ }
+
+ tmp = bitmap_code(bitbuff, (unsigned char*)map);
+
+ if(tmp)
+ bdffontp[i].bitmap = bitbuff;
+ else
+ bdffontp[i].bitmap = NULL;
+
+ bitbuff += tmp;
+ length += tmp;
+ }
+
+parse_bdf_error:
+ fclose(fp);
+ if(ret < 0)
+ {
+ if(bdflibinfop -> fonts != NULL)
+ free((void*)bdflibinfop -> fonts);
+ if(bdflibinfop -> mapmem != NULL)
+ free((void*)bdflibinfop -> mapmem);
+ bdflibinfop -> fonts = NULL;
+ bdflibinfop -> mapmem = NULL;
+ }
+ else
+ {
+ bdflibinfop -> maplen = length;
+ bdflibinfop -> mapmem = (unsigned char*)realloc((void*)bdflibinfop -> mapmem, length);
+ }
+
+ return ret;
+}
+
+/*-----------------------------------------------------------------------------
+------------------------------------------------------------------------------*/
+int dump2odf(char *filename, struct bdflibinfo *bdflibinfop)
+{
+ char *pt;
+ char string[256];
+ FILE *fp;
+ u32 mapaddr;
+ u32 fontaddr;
+ u32 num;
+ char buff[1024];
+ u32 i, j;
+
+
+ strcpy(string, filename);
+ pt= strrchr(string, '.');
+ if(!strcasecmp(pt, ".bdf"))
+ strcpy(pt, ".odf");
+ else
+ return -1;
+
+ fp= fopen(string, "wb");
+ if(fp == NULL)
+ return -2;
+
+ pt= buff;
+ strcpy(pt, "ODF");
+ pt += 4;
+ strcpy(pt, ODF_VERSION);
+ pt += 4;
+
+ struct bdflibinfo *bdflibinfo_i;
+
+ memcpy(pt, (char*)bdflibinfop, sizeof(struct bdflibinfo));
+ bdflibinfo_i= (struct bdflibinfo *)pt;
+ bdflibinfo_i -> mapmem= NULL;
+ bdflibinfo_i -> fonts= NULL;
+ pt += sizeof(struct bdflibinfo);
+
+ num= pt-buff;
+ fwrite(buff, num, 1, fp); //write odf file header
+
+ num= (u32)bdflibinfop -> span;
+ mapaddr= (u32)bdflibinfop -> mapmem;
+ fontaddr= (u32)bdflibinfop -> fonts;
+
+ while(num)
+ {
+ struct bdffont *bdffontp;
+
+ i= 1024/sizeof(struct bdffont);
+ if(num > i) num -= i;
+ else i= num, num= 0;
+
+ memcpy(buff, (char*)fontaddr, i*sizeof(struct bdffont));
+ fontaddr += i*sizeof(struct bdffont);
+ bdffontp= (struct bdffont*)buff;
+
+ for(j= 0; j< i; j++)
+ bdffontp[j].bitmap -= mapaddr;
+
+ fwrite(buff, i*sizeof(struct bdffont), 1, fp);
+ }
+
+ fwrite((char*)mapaddr, bdflibinfop -> maplen, 1, fp);
+
+ fclose(fp);
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------
+------------------------------------------------------------------------------*/
+int init_from_odf(char *filename, struct bdflibinfo *bdflibinfop)
+{
+ FILE *fp;
+ char buff[512];
+ char *pt;
+ u32 len, tmp;
+ u32 span, maplen;
+ struct bdffont *bdffontp;
+
+ //initial bdflibinfo
+ bdflibinfop -> width= 0;
+ bdflibinfop -> height= 0;
+ bdflibinfop -> start= 0;
+ bdflibinfop -> span= 0;
+ bdflibinfop -> maplen= 0;
+ bdflibinfop -> mapmem= NULL;
+ bdflibinfop -> fonts= NULL;
+
+ fp= fopen(filename, "rb");
+ if(fp == NULL)
+ return -1;
+
+ tmp= 8 + sizeof(struct bdflibinfo);
+ len= fread(buff, 1, tmp, fp);
+ if(len < tmp)
+ {
+ fclose(fp);
+ return -2;
+ }
+
+ pt= buff;
+ if(strcmp(pt, "ODF"))
+ {
+ fclose(fp);
+ return -2;
+ }
+
+ pt += 4;
+ if(strcmp(pt, ODF_VERSION))
+ {
+ fclose(fp);
+ return -3;
+ }
+
+ pt += 4;
+ memcpy((char*)bdflibinfop, pt, sizeof(struct bdflibinfo));
+
+ span= bdflibinfop -> span;
+ if(span == 0)
+ {
+ fclose(fp);
+ return -4;
+ }
+
+ maplen= bdflibinfop -> maplen;
+ if(maplen == 0)
+ {
+ fclose(fp);
+ return -5;
+ }
+
+ bdffontp= (struct bdffont*)malloc(span * sizeof(struct bdffont));
+ if(bdffontp == NULL)
+ {
+ fclose(fp);
+ return -6;
+ }
+
+ len= fread((char*)bdffontp, 1, span * sizeof(struct bdffont), fp);
+ if(len != span * sizeof(struct bdffont))
+ {
+ free((void*)bdffontp);
+ fclose(fp);
+ return -7;
+ }
+
+ pt= (char*)malloc(maplen);
+ len= fread(pt, 1, maplen, fp);
+ if(len != maplen)
+ {
+ free((void*)bdffontp);
+ free((void*)pt);
+ fclose(fp);
+ return -8;
+ }
+
+ bdflibinfop -> mapmem = (unsigned char*)pt;
+ bdflibinfop -> fonts = bdffontp;
+
+ u32 i, j;
+ j= (u32)bdflibinfop -> mapmem;
+ for(i= 0; i < span; i++)
+ bdffontp[i].bitmap += j;
+
+ fclose(fp);
+ return 0;
+}
+
+int BDF_font_init(void)
+{
+ int err;
+ char tmp_path[MAX_PATH];
+
+ fonts_max_height= 0;
+#ifndef HAVE_ODF
+ sprintf(tmp_path, "%s/%s", main_path, BDF_VERDANA);
+ err= parse_bdf(tmp_path, 0, 128, &bdflib_info[0], 0);
+ if(err < 0)
+ {
+ printf("BDF 0 initial error: %d\n", err);
+ return -1;
+ }
+#else
+ sprintf(tmp_path, "%s/%s", main_path, ODF_VERDANA);
+ err= init_from_odf(tmp_path, &bdflib_info[0]);
+ if(err < 0)
+ {
+ printf("ODF 0 initial error: %d\n", err);
+ return -1;
+ }
+#endif
+ bdf_font= bdflib_info[0].fonts;
+ font_height= bdflib_info[0].height;
+ if(fonts_max_height < bdflib_info[0].height)
+ fonts_max_height = bdflib_info[0].height;
+
+#ifdef DUMP_ODF
+ sprintf(tmp_path, "%s/%s", main_path, BDF_VERDANA);
+ err= dump2odf(tmp_path, &bdflib_info[0]);
+ if(err < 0)
+ {
+ printf("BDF dump odf 0 error: %d\n", err);
+ }
+#endif
+
+#ifndef HAVE_ODF
+ sprintf(tmp_path, "%s/%s", main_path, BDF_SONG);
+ err= parse_bdf(tmp_path, 0x4E00, 20902, &bdflib_info[1], 1);
+ if(err < 0)
+ {
+ printf("BDF 1 initial error: %d\n", err);
+ return -1;
+ }
+#else
+ sprintf(tmp_path, "%s/%s", main_path, ODF_SONG);
+ err= init_from_odf(tmp_path, &bdflib_info[1]);
+ if(err < 0)
+ {
+ printf("ODF 1 initial error: %d\n", err);
+ return -1;
+ }
+#endif
+ bdf_nasci= bdflib_info[1].fonts;
+ if(fonts_max_height < bdflib_info[1].height)
+ fonts_max_height = bdflib_info[1].height;
+
+#ifdef DUMP_ODF
+ sprintf(tmp_path, "%s/%s", main_path, BDF_SONG);
+ err= dump2odf(tmp_path, &bdflib_info[1]);
+ if(err < 0)
+ {
+ printf("BDF dump odf 1 error: %d\n", err);
+ }
+#endif
+
+ return 0;
+}
+
+/*-----------------------------------------------------------------------------
+// release resource of BDF fonts
+------------------------------------------------------------------------------*/
+void BDF_font_release(void)
+{
+ u32 i;
+
+ for(i= 0; i < BDF_LIB_NUM; i++)
+ {
+ if(bdflib_info[i].fonts)
+ free((void*)bdflib_info[i].fonts);
+ if(bdflib_info[i].mapmem)
+ free((void*)bdflib_info[i].mapmem);
+ }
+}
+
+/*-----------------------------------------------------------------------------
+//16-bit color
+// Unicode Character
+// back is background, 0x8000 is transparence, other are visable colors
+------------------------------------------------------------------------------*/
+u32 BDF_render16_ucs(void* screen_address, u32 screen_w, u32 v_align, u32 back, u32 front, u16 ch)
+{
+ unsigned short *screen, *screenp;
+ unsigned char *map;
+ u32 width, height, x_off, y_off, i, k, m, ret, fonts_height;
+ unsigned char cc;
+ struct bdffont *bdffontp;
+
+ if(ch < 128)
+ {
+ bdffontp= bdflib_info[0].fonts;
+ fonts_height= bdflib_info[0].height;
+ }
+ else if(bdflib_info[1].fonts != NULL)
+ {
+ k= bdflib_info[1].start;
+ m= k + bdflib_info[1].span;
+ if(ch >= k && ch < m)
+ {
+ ch -= k;
+ bdffontp= bdflib_info[1].fonts;
+ fonts_height= bdflib_info[0].height;
+ }
+ else
+ return 8;
+ }
+ else
+ return 8;
+
+ width= bdffontp[ch].dwidth >> 16;
+ ret= width;
+ height= fonts_max_height;
+ //if charactor is not transparent
+ if(!(back & 0x8000))
+ {
+ for(k= 0; k < height; k++)
+ {
+ screenp= (unsigned short*)screen_address + k *screen_w;
+ for(i= 0; i < width; i++)
+ *screenp++ = back;
+ }
+ }
+
+ width= bdffontp[ch].bbx >> 24;
+ if(width == 0)
+ return ret;
+
+ height= (bdffontp[ch].bbx >> 16) & 0xFF;
+ x_off= (bdffontp[ch].bbx >> 8) & 0xFF;
+ y_off= bdffontp[ch].bbx & 0xFF;
+
+ if(v_align== 0) //v align bottom
+ screen= (unsigned short*)screen_address + x_off + (fonts_max_height - height - y_off) *screen_w;
+ else if(v_align== 1) //v align center
+ screen= (unsigned short*)screen_address + x_off + (fonts_max_height - height - y_off)/2 *screen_w;
+ else //v align top
+ screen= (unsigned short*)screen_address + x_off;
+
+ x_off= width >> 3;
+ y_off= width & 7;
+
+ map= bdffontp[ch].bitmap;
+ for(k= 0; k < height; k++)
+ {
+ screenp = screen + k *screen_w;
+ i= x_off;
+ while(i--)
+ {
+ m= 0x80;
+ cc= *map++;
+ while(m)
+ {
+ if(m & cc) *screenp = front;
+ screenp++;
+ m >>= 1;
+ }
+ }
+
+ i= y_off;
+ if(i)
+ {
+ i= 8 - y_off;
+ cc= *map++;
+ cc >>= i;
+ m= 0x80 >> i;
+ while(m)
+ {
+ if(m & cc) *screenp = front;
+ screenp++;
+ m >>= 1;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/*-----------------------------------------------------------------------------
+//16-bit color
+// ASCII Character
+// back is background, 0x8000 is transparence, other are visable colors
+------------------------------------------------------------------------------*/
+static u32 BDF_render16_font(char *screen_address, u32 back, u32 front, u16 ch)
+{
+ unsigned short *screen, *screenp;
+ unsigned char *map;
+ u32 width, height, x_off, y_off, i, k, m, ret;
+ unsigned char cc;
+
+ if(ch > 127)
+ return 8;
+
+ width= bdf_font[ch].dwidth >> 16;
+ ret= width;
+ height= font_height;
+ //if charactor is not transparent
+ if(!(back & 0x8000))
+ {
+ for(k= 0; k < height; k++)
+ {
+ screenp= (unsigned short*)screen_address + k *SCREEN_WIDTH;
+ for(i= 0; i < width; i++)
+ *screenp++ = back;
+ }
+ }
+
+ width= bdf_font[ch].bbx >> 24;
+ if(width == 0)
+ return ret;
+ height= (bdf_font[ch].bbx >> 16) & 0xFF;
+ x_off= (bdf_font[ch].bbx >> 8) & 0xFF;
+ y_off= bdf_font[ch].bbx & 0xFF;
+ screen= (unsigned short*)screen_address + x_off + (font_height - height -y_off) *SCREEN_WIDTH;
+
+ x_off= width >> 3;
+ y_off= width & 7;
+
+ map= bdf_font[ch].bitmap;
+ for(k= 0; k < height; k++)
+ {
+ screenp = screen + k *SCREEN_WIDTH;
+ i= x_off;
+ while(i--)
+ {
+ m= 0x80;
+ cc= *map++;
+ while(m)
+ {
+ if(m & cc) *screenp = front;
+ screenp++;
+ m >>= 1;
+ }
+ }
+
+ i= y_off;
+ if(i)
+ {
+ i= 8 - y_off;
+ cc= *map++;
+ cc >>= i;
+ m= 0x80 >> i;
+ while(m)
+ {
+ if(m & cc) *screenp = front;
+ screenp++;
+ m >>= 1;
+ }
+ }
+ }
+
+ return ret;
+}
+
+/*-----------------------------------------------------------------------------
+// ASCII Code Only
+------------------------------------------------------------------------------*/
+void BDF_render_string(void* screen_address, u32 x, u32 y, u32 back, u32 front, char *string)
+{
+ char *pt;
+ u32 screenp, line_start;
+ u32 width, line, cmp;
+
+ pt= string;
+ screenp= (u32)screen_address + (x + y *SCREEN_WIDTH)*2;
+ line= 1 + y;
+ line_start= (u32)screen_address + line *SCREEN_WIDTH *2;
+
+ width= 0;
+ while(*pt)
+ {
+ if(*pt == 0x0D)
+ {
+ pt++;
+ continue;
+ }
+ if(*pt == 0x0A)
+ {
+ line += font_height;
+ line_start= (u32)screen_address + line *SCREEN_WIDTH *2;
+ screenp = line_start - SCREEN_WIDTH *2;
+ pt++;
+ continue;
+ }
+
+ cmp = (bdf_font[(u32)(*pt)].dwidth >> 16) << 1;
+ if((screenp+cmp) >= line_start)
+ {
+ line += font_height;
+ line_start= (u32)screen_address + line *SCREEN_WIDTH *2;
+ screenp = line_start - SCREEN_WIDTH *2;
+ }
+ width= BDF_render16_font((char*)screenp, back, front, (u32)(*pt));
+ screenp += width*2;
+ pt++;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+------------------------------------------------------------------------------*/
+char* utf8decode(char *utf8, u16 *ucs)
+{
+ unsigned char c = *utf8++;
+ unsigned long code;
+ int tail = 0;
+
+ if ((c <= 0x7f) || (c >= 0xc2)) {
+ /* Start of new character. */
+ if (c < 0x80) { /* U-00000000 - U-0000007F, 1 byte */
+ code = c;
+ } else if (c < 0xe0) { /* U-00000080 - U-000007FF, 2 bytes */
+ tail = 1;
+ code = c & 0x1f;
+ } else if (c < 0xf0) { /* U-00000800 - U-0000FFFF, 3 bytes */
+ tail = 2;
+ code = c & 0x0f;
+ } else if (c < 0xf5) { /* U-00010000 - U-001FFFFF, 4 bytes */
+ tail = 3;
+ code = c & 0x07;
+ } else {
+ /* Invalid size. */
+ code = 0;
+ }
+
+ while (tail-- && ((c = *utf8++) != 0)) {
+ if ((c & 0xc0) == 0x80) {
+ /* Valid continuation character. */
+ code = (code << 6) | (c & 0x3f);
+
+ } else {
+ /* Invalid continuation char */
+ code = 0xfffd;
+ utf8--;
+ break;
+ }
+ }
+ } else {
+ /* Invalid UTF-8 char */
+ code = 0;
+ }
+ /* currently we don't support chars above U-FFFF */
+ *ucs = (code < 0x10000) ? code : 0;
+ return utf8;
+}
+
+static u8 utf8_ucs2(const char *utf8, u16 *ucs)
+{
+ char *pt = (char*)utf8;
+
+ while(*pt !='\0')
+ {
+ pt = utf8decode(pt, ucs++);
+ }
+ *ucs = '\0';
+ return 0;
+}
+
+static u32 ucslen(const u16 *ucs)
+{
+ u32 len = 0;
+
+ while(ucs[len] != '\0')
+ len++;
+ return len;
+}
+
+unsigned char* skip_utf8_unit(unsigned char* utf8, unsigned int num)
+{
+ while(num--)
+ {
+ unsigned char c = *utf8++;
+ int tail = 0;
+ if ((c <= 0x7f) || (c >= 0xc2)) {
+ /* Start of new character. */
+ if (c < 0x80) { /* U-00000000 - U-0000007F, 1 byte */
+ } else if (c < 0xe0) { /* U-00000080 - U-000007FF, 2 bytes */
+ tail = 1;
+ } else if (c < 0xf0) { /* U-00000800 - U-0000FFFF, 3 bytes */
+ tail = 2;
+ } else if (c < 0xf5) { /* U-00010000 - U-001FFFFF, 4 bytes */
+ tail = 3;
+ } else { /* Invalid size. */
+ }
+
+ while (tail-- && ((c = *utf8++) != 0)) {
+ if ((c & 0xc0) != 0x80) {
+ /* Invalid continuation char */
+ utf8--;
+ break;
+ }
+ }
+ }
+ }
+
+ /* currently we don't support chars above U-FFFF */
+ return utf8;
+}
+
+/*-----------------------------------------------------------------------------
+// UTF8 Code String
+------------------------------------------------------------------------------*/
+void BDF_render_mix(void* screen_address, u32 screen_w, u32 x, u32 y, u32 v_align,
+ u32 back, u32 front, char *string)
+{
+ char *pt;
+ u32 screenp, line_start;
+ u32 width, line, cmp, start, end;
+ u16 unicode;
+ struct bdffont *bdf_fontp[2];
+
+ bdf_fontp[0]= bdflib_info[0].fonts;
+ start= bdflib_info[1].start;
+ end= start + bdflib_info[1].span;
+ bdf_fontp[1]= bdflib_info[1].fonts;
+
+ pt= string;
+ screenp= (u32)screen_address + (x + y *screen_w)*2;
+ line= 1 + y;
+ line_start= (u32)screen_address + line *screen_w *2;
+
+ width= 0;
+ while(*pt)
+ {
+ pt= utf8decode(pt, &unicode);
+
+ if(unicode == 0x0D) continue;
+ if(unicode == 0x0A)
+ {
+ line += font_height;
+ line_start= (u32)screen_address + line *screen_w *2;
+ screenp = line_start - screen_w *2;
+ continue;
+ }
+
+ if(unicode < 128)
+ cmp = bdf_fontp[0][unicode].dwidth>>16;
+ else if(unicode >= start && unicode < end)
+ cmp = bdf_fontp[1][unicode -start].dwidth>>16;
+
+ if((screenp+cmp) >= line_start)
+ {
+ line += font_height;
+ line_start= (u32)screen_address + line *screen_w *2;
+ screenp = line_start - screen_w *2;
+ }
+
+ width= BDF_render16_ucs((unsigned short*)screenp, screen_w, v_align, back, front, unicode);
+ screenp += width*2;
+ }
+}
+
+/*-----------------------------------------------------------------------------
+- count UNICODE charactor numbers in width pixels, input are UTF8, not UNICODE-16
+- direction 0: count UNICODE charactor numbers in width pixels, from end,
+- return bytes numbers
+- direction 1: count UNICODE charactor numbers in width pixels, from front,
+- return bytes numbers
+- direction 2: count total pixel width of the string
+------------------------------------------------------------------------------*/
+u32 BDF_cut_string(char *string, u32 width, u32 direction)
+{
+ char *pt;
+ u16 unicode[256];
+ u32 len, xw;
+
+ if(direction > 2) return -1;
+
+ pt= string;
+ len= 0;
+ while(*pt)
+ {
+ pt= utf8decode(pt, &unicode[len]);
+ if(unicode[len] != 0x0A)
+ {
+ len++;
+ if(len >= 256) break;
+ }
+ }
+
+ if(len >= 256) return -1;
+
+ u16 *unicodep;
+ if(direction == 0)
+ unicodep= &unicode[len-1];
+ else
+ unicodep= &unicode[0];
+
+ if(direction == 2) direction = 3;
+ xw= BDF_cut_unicode(unicodep, len, width, direction);
+
+ if(direction < 2)
+ {
+ if(direction < 1)
+ xw= len - xw;
+
+ pt= string;
+ while(xw)
+ {
+ pt= utf8decode(pt, unicodep);
+ if(unicode[xw] != 0x0A) xw--;
+ }
+
+ xw= pt -string;
+ }
+
+ return xw;
+}
+
+/*-----------------------------------------------------------------------------
+- count UNICODE charactor numbers in width pixels
+- direction 0: count UNICODE charactor numbers in width pixels, from front
+- direction 1: count UNICODE charactor numbers in width pixels, from end
+- direction 2: conut total pixel width of len UNICODE charachtors, from end
+- direction 3: conut total pixel width of len UNICODE charachtors, from front
+------------------------------------------------------------------------------*/
+u32 BDF_cut_unicode(u16 *unicodes, u32 len, u32 width, u32 direction)
+{
+ u32 i, xw, num;
+ u16 unicode;
+ u32 start, end;
+ struct bdffont *bdf_fontp[2];
+
+ bdf_fontp[0]= bdflib_info[0].fonts;
+ start= bdflib_info[1].start;
+ end= start + bdflib_info[1].span;
+ bdf_fontp[1]= bdflib_info[1].fonts;
+
+ if(direction < 2)
+ {
+ if(direction < 1) direction = -1;
+
+ i= 0;
+ xw = 0;
+ num= len;
+ while(len > 0)
+ {
+ unicode= unicodes[i];
+ if(unicode < 128)
+ xw += bdf_fontp[0][unicode].dwidth>>16;
+ else if(unicode >= start && unicode < end)
+ xw += bdf_fontp[1][unicode -start].dwidth>>16;
+
+ if(xw >= width) break;
+ i += direction;
+ len--;
+ }
+
+ num -= len;
+ }
+ else
+ {
+ if(direction < 3) direction = -1;
+ else direction = 1;
+
+ i= 0;
+ xw = 0;
+ while(len-- > 0)
+ {
+ unicode= unicodes[i];
+ if(unicode < 128)
+ xw += bdf_fontp[0][unicode].dwidth>>16;
+ else if(unicode >= start && unicode < end)
+ xw += bdf_fontp[1][unicode -start].dwidth>>16;
+ i += direction;
+ }
+
+ num= xw;
+ }
+
+ return num;
+}
+
+