mirror of
https://github.com/tpunix/HMCLOCK.git
synced 2025-12-07 08:32:50 +08:00
575 lines
11 KiB
C
575 lines
11 KiB
C
|
||
#include <stdio.h>
|
||
#include <string.h>
|
||
#include <stdlib.h>
|
||
|
||
|
||
#include <ft2build.h>
|
||
#include FT_FREETYPE_H
|
||
#include FT_GLYPH_H
|
||
|
||
/******************************************************************************/
|
||
|
||
typedef signed int s32;
|
||
typedef signed short s16;
|
||
typedef signed char s8;
|
||
typedef unsigned int u32;
|
||
typedef unsigned short u16;
|
||
typedef unsigned char u8;
|
||
|
||
|
||
typedef struct {
|
||
int unicode;
|
||
|
||
/* Glyph bitmap infomation */
|
||
int bw, bh;
|
||
int bx, by;
|
||
int advance;
|
||
u8 *bitmap;
|
||
int bsize;
|
||
} GLYPH;
|
||
|
||
|
||
int clist[65536];
|
||
GLYPH *ctab[65536];
|
||
int total_chars;
|
||
|
||
int pixel_size;
|
||
int font_ascent;
|
||
int base_adj = 0;
|
||
int font_size = 14;
|
||
|
||
u8 font_buf[0x1000000];
|
||
int font_buf_size;
|
||
|
||
/******************************************************************************/
|
||
|
||
|
||
int ucs2utf8(u16 ucs, char *p)
|
||
{
|
||
if(ucs<=0x7f){
|
||
p[0] = ucs;
|
||
return 1;
|
||
}else if(ucs<=0x7ff){
|
||
p[0] = 0xc0 | ((ucs>>6)&0x1f);
|
||
p[1] = 0x80 | ((ucs>>0)&0x3f);
|
||
return 2;
|
||
}else if(ucs<=0xffff){
|
||
p[0] = 0xe0 | ((ucs>>12)&0x0f);
|
||
p[1] = 0x80 | ((ucs>>6)&0x3f);
|
||
p[2] = 0x80 | ((ucs>>0)&0x3f);
|
||
return 3;
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
/******************************************************************************/
|
||
|
||
#if 0
|
||
GLYPH *bdf_load_char(FILE *fp)
|
||
{
|
||
int bmp, lsize, x;
|
||
char lbuf[128];
|
||
GLYPH *pg;
|
||
|
||
pg = NULL;
|
||
bmp = -1;
|
||
while(1){
|
||
if(fgets(lbuf, 128, fp)==NULL)
|
||
break;
|
||
|
||
if(strncmp(lbuf, "STARTCHAR", 9)==0){
|
||
pg = (GLYPH*)malloc(sizeof(GLYPH));
|
||
memset(pg, 0, sizeof(GLYPH));
|
||
}else if(strncmp(lbuf, "ENCODING", 8)==0){
|
||
pg->unicode = atoi(lbuf+9);
|
||
}else if(strncmp(lbuf, "DWIDTH", 6)==0){
|
||
pg->advance = atoi(lbuf+7);
|
||
}else if(strncmp(lbuf, "BBX", 3)==0){
|
||
sscanf(lbuf+4, "%d %d %d %d", &pg->bw, &pg->bh, &pg->bx, &pg->by);
|
||
#if 1
|
||
int ny = (font_ascent+base_adj-1) - (pg->bh - 1 + pg->by);
|
||
if(ny<0)
|
||
ny = 0;
|
||
pg->by = ny;
|
||
#endif
|
||
if(pg->bx<0){
|
||
pg->advance -= pg->bx;
|
||
pg->bx = 0;
|
||
}
|
||
lsize = (pg->bw+7)/8;
|
||
pg->bsize = lsize*pg->bh;
|
||
pg->bitmap = malloc(pg->bsize);
|
||
}else if(strncmp(lbuf, "BITMAP", 6)==0){
|
||
bmp = 0;
|
||
}else if(strncmp(lbuf, "ENDCHAR", 7)==0){
|
||
break;
|
||
}else if(bmp>=0){
|
||
int len = strlen(lbuf);
|
||
if(lbuf[len-1]=='\n' || lbuf[len-1]=='\r') len -= 1;
|
||
if(lbuf[len-1]=='\n' || lbuf[len-1]=='\r') len -= 1;
|
||
x = 0;
|
||
for(int i=0; i<len; i+=2){
|
||
char tmp[4];
|
||
tmp[0] = lbuf[i+0];
|
||
tmp[1] = lbuf[i+1];
|
||
tmp[2] = 0;
|
||
if(x<lsize){
|
||
pg->bitmap[bmp] = strtoul(tmp, NULL, 16);
|
||
bmp += 1;
|
||
x += 1;
|
||
}
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
return pg;
|
||
}
|
||
|
||
|
||
int load_bdf(char *bdf_name)
|
||
{
|
||
FILE *fp;
|
||
GLYPH *pg;
|
||
char lbuf[128];
|
||
|
||
total_chars = 0;
|
||
memset(ctab, 0, sizeof(ctab));
|
||
|
||
fp = fopen(bdf_name, "r");
|
||
if(fp==NULL)
|
||
return -1;
|
||
|
||
fgets(lbuf, 128, fp);
|
||
if(strncmp(lbuf, "STARTFONT", 9)){
|
||
printf("STARTFONT not found!\n");
|
||
return -1;
|
||
}
|
||
printf("\nLoad BDF: %s\n", bdf_name);
|
||
|
||
pixel_size = 0;
|
||
font_ascent = 0;
|
||
while(1){
|
||
if(fgets(lbuf, 128, fp)==NULL)
|
||
break;
|
||
if(strncmp(lbuf, "PIXEL_SIZE", 10)==0){
|
||
pixel_size = atoi(lbuf+11);
|
||
printf(" PIXEL_SIZE: %d\n", pixel_size);
|
||
}else if(strncmp(lbuf, "FONT_ASCENT", 11)==0){
|
||
font_ascent = atoi(lbuf+12);
|
||
printf(" FONT_ASCENT: %d\n", font_ascent);
|
||
}else if(strncmp(lbuf, "CHARS ", 6)==0){
|
||
break;
|
||
}
|
||
}
|
||
if(pixel_size==0){
|
||
printf("Wrong PIXEL_SIZE: %d\n", pixel_size);
|
||
return -1;
|
||
}
|
||
|
||
|
||
while(1){
|
||
pg = bdf_load_char(fp);
|
||
if(pg==NULL)
|
||
break;
|
||
|
||
if(clist[pg->unicode]==0){
|
||
free(pg->bitmap);
|
||
free(pg);
|
||
continue;
|
||
}
|
||
ctab[pg->unicode] = pg;
|
||
total_chars += 1;
|
||
}
|
||
printf(" Chars load: %d\n", total_chars);
|
||
|
||
fclose(fp);
|
||
return 0;
|
||
}
|
||
|
||
#endif
|
||
|
||
/******************************************************************************/
|
||
|
||
FT_Library ft_lib;
|
||
FT_Face ft_face;
|
||
|
||
|
||
GLYPH *ttf_load_char(int ucs)
|
||
{
|
||
FT_Glyph glyph;
|
||
int index, retv;
|
||
|
||
index = FT_Get_Char_Index(ft_face, ucs);
|
||
if(index==0){
|
||
//printf("FT_Get_Char_Index(%04x): not found!\n", ucs);
|
||
return NULL;
|
||
}
|
||
|
||
//retv = FT_Load_Glyph(tt->face, index, FT_LOAD_DEFAULT|FT_LOAD_NO_HINTING);
|
||
retv = FT_Load_Glyph(ft_face, index, FT_LOAD_DEFAULT);
|
||
if(retv){
|
||
printf("FT_Load_Gluph(%04x): error=%08x\n", ucs, retv);
|
||
return NULL;
|
||
}
|
||
|
||
FT_Get_Glyph(ft_face->glyph, &glyph);
|
||
|
||
if(ft_face->glyph->format!=FT_GLYPH_FORMAT_BITMAP){
|
||
retv = FT_Glyph_To_Bitmap(&glyph, FT_RENDER_MODE_MONO, 0, 1);
|
||
if(retv){
|
||
printf("FT_Render_Glyph(%04x): error=%08x\n", ucs, retv);
|
||
return NULL;
|
||
}
|
||
}
|
||
|
||
FT_BitmapGlyph bit = (FT_BitmapGlyph)glyph;
|
||
FT_Bitmap bm = bit->bitmap;
|
||
|
||
GLYPH *pg = (GLYPH*)malloc(sizeof(GLYPH));
|
||
memset(pg, 0, sizeof(GLYPH));
|
||
|
||
pg->unicode = ucs;
|
||
pg->bw = bm.width;
|
||
pg->bh = bm.rows;
|
||
pg->bx = bit->left;
|
||
pg->by = font_size-bit->top;
|
||
pg->advance = (glyph->advance.x+0x00008000)>>16;
|
||
|
||
int lsize = (pg->bw+7)/8;
|
||
pg->bsize = lsize*pg->bh;
|
||
pg->bitmap = malloc(pg->bsize);
|
||
|
||
for(int y=0; y<bm.rows; y++){
|
||
memcpy(pg->bitmap+y*lsize, bm.buffer+y*bm.pitch, lsize);
|
||
}
|
||
|
||
return pg;
|
||
}
|
||
|
||
|
||
|
||
int load_ttf(char *ttf_name)
|
||
{
|
||
int retv, i;
|
||
|
||
retv = FT_Init_FreeType(&ft_lib);
|
||
if(retv){
|
||
printf("FT_Init_Freetype failed! error=%08x\n", retv);
|
||
return retv;
|
||
}
|
||
|
||
retv = FT_New_Face(ft_lib, ttf_name, 0, &ft_face);
|
||
if(retv){
|
||
printf("FT_New_Face(%s): error=%08x\n", ttf_name, retv);
|
||
return retv;
|
||
}
|
||
|
||
#if 1
|
||
printf("FACE: num_fixed_sizes: %d\n", ft_face->num_fixed_sizes);
|
||
for(i=0; i<ft_face->num_fixed_sizes; i++){
|
||
printf("%2d: %2ld %2dx%2d\n", i, ft_face->available_sizes[i].size/64,
|
||
ft_face->available_sizes[i].width,
|
||
ft_face->available_sizes[i].height);
|
||
}
|
||
#endif
|
||
|
||
retv = FT_Set_Pixel_Sizes(ft_face, font_size, font_size);
|
||
if(retv){
|
||
printf("FT_Set_Pixel_Size: error=%08x\n", retv);
|
||
//return retv;
|
||
}
|
||
|
||
total_chars = 0;
|
||
|
||
for(i=0; i<65536; i++){
|
||
if(clist[i]==0)
|
||
continue;
|
||
ctab[i] = ttf_load_char(i);
|
||
if(ctab[i]){
|
||
total_chars += 1;
|
||
}else{
|
||
//printf("load char %04x failed!\n", i);
|
||
}
|
||
}
|
||
|
||
// 针对7段数字字体的空格,将其宽度处理成和数字一样。
|
||
if(font_size>24 && ctab[0x20] && ctab[0x30]){
|
||
ctab[0x20]->advance = ctab[0x30]->advance;
|
||
}
|
||
|
||
FT_Done_Face(ft_face);
|
||
FT_Done_FreeType(ft_lib);
|
||
|
||
return 0;
|
||
}
|
||
|
||
/******************************************************************************/
|
||
|
||
|
||
|
||
void load_list(char *name)
|
||
{
|
||
FILE *fp;
|
||
int n, ucs;
|
||
|
||
memset(clist, 1, sizeof(clist));
|
||
|
||
if(name==NULL)
|
||
return;
|
||
|
||
fp = fopen(name, "rb");
|
||
if(fp==NULL)
|
||
return;
|
||
|
||
memset(clist, 0, sizeof(clist));
|
||
|
||
fread(&ucs, 2, 1, fp);
|
||
if(ucs!=0xfeff){
|
||
printf("文件[%s]不是UTF16-LE格式!\n", name);
|
||
exit(-1);
|
||
}
|
||
|
||
while(1){
|
||
if(fread(&ucs, 2, 1, fp)<1)
|
||
break;
|
||
if(ucs==0x0d || ucs==0x0a)
|
||
continue;
|
||
|
||
if(clist[ucs]==0){
|
||
clist[ucs] = 1;
|
||
n += 1;
|
||
}
|
||
}
|
||
|
||
printf("Load list form %s: %d\n", name, n);
|
||
}
|
||
|
||
|
||
|
||
/******************************************************************************/
|
||
|
||
|
||
void print_glyph(GLYPH *pg)
|
||
{
|
||
int x, y;
|
||
char ubuf[4];
|
||
|
||
*(u32*)(ubuf) = 0;
|
||
ucs2utf8(pg->unicode, ubuf);
|
||
|
||
printf("\nchar %04x [%s]\n", pg->unicode, ubuf);
|
||
printf(" bw=%-2d bh=%-2d bx=%-2d by=%-2d adv=%d\n", pg->bw, pg->bh, pg->bx, pg->by, pg->advance);
|
||
|
||
int lsize = (pg->bw+7)/8;
|
||
for(y=0; y<pg->bh; y++){
|
||
printf(" ");
|
||
for(x=0; x<pg->bw; x++){
|
||
if(pg->bitmap[y*lsize+(x>>3)]&(0x80>>(x%8)))
|
||
printf("*");
|
||
else
|
||
printf(".");
|
||
}
|
||
printf("\n");
|
||
}
|
||
|
||
}
|
||
|
||
void dump_glyph(void)
|
||
{
|
||
int i;
|
||
|
||
for(i=0; i<65536; i++){
|
||
if(ctab[i]){
|
||
print_glyph(ctab[i]);
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
void dump_list(void)
|
||
{
|
||
int i;
|
||
char ubuf[4];
|
||
|
||
for(i=0; i<65536; i++){
|
||
if(ctab[i]){
|
||
*(u32*)(ubuf) = 0;
|
||
ucs2utf8(i, ubuf);
|
||
printf("%04x=%s\n", i, ubuf);
|
||
}
|
||
}
|
||
|
||
}
|
||
|
||
|
||
/******************************************************************************/
|
||
|
||
|
||
void write_be16(u8 *p, int val)
|
||
{
|
||
p[0] = val&0xff;
|
||
p[1] = (val>>8)&0xff;
|
||
}
|
||
|
||
|
||
void build_font(void)
|
||
{
|
||
int i, p, offset;
|
||
|
||
write_be16(font_buf, total_chars);
|
||
offset = total_chars*4+2;
|
||
|
||
p = 2;
|
||
for(i=0; i<65536; i++){
|
||
if(ctab[i]){
|
||
GLYPH *pg = ctab[i];
|
||
write_be16(font_buf+p, i);
|
||
write_be16(font_buf+p+2, offset);
|
||
p += 4;
|
||
offset += pg->bsize+5;
|
||
}
|
||
}
|
||
|
||
for(i=0; i<65536; i++){
|
||
if(ctab[i]){
|
||
GLYPH *pg = ctab[i];
|
||
font_buf[p+0] = pg->advance;
|
||
font_buf[p+1] = pg->bw;
|
||
font_buf[p+2] = pg->bh;
|
||
font_buf[p+3] = pg->bx;
|
||
font_buf[p+4] = pg->by;
|
||
p += 5;
|
||
memcpy(font_buf+p, pg->bitmap, pg->bsize);
|
||
p += pg->bsize;
|
||
}
|
||
}
|
||
|
||
font_buf_size = p;
|
||
}
|
||
|
||
|
||
/******************************************************************************/
|
||
|
||
|
||
int bin2c(u8 *buffer, int size, char *file_name, char *label_name)
|
||
{
|
||
FILE *dest;
|
||
int i, unit=1;
|
||
|
||
if((dest = fopen(file_name, "w")) == NULL) {
|
||
printf("Failed to open/create %s.\n", file_name);
|
||
return 1;
|
||
}
|
||
|
||
fprintf(dest, "#ifndef __%s__\n", label_name);
|
||
fprintf(dest, "#define __%s__\n\n", label_name);
|
||
fprintf(dest, "#define %s_size %d\n", label_name, size);
|
||
fprintf(dest, "static const unsigned char %s[] __attribute__((aligned(4))) = {", label_name);
|
||
|
||
for(i=0; i<size; i+=unit) {
|
||
if((i % (16/unit)) == 0){
|
||
fprintf(dest, "\n\t");
|
||
}else{
|
||
fprintf(dest, " ");
|
||
}
|
||
if(unit==1){
|
||
fprintf(dest, "0x%02x,", buffer[i]);
|
||
}else if(unit==2){
|
||
fprintf(dest, "0x%04x,", buffer[i]);
|
||
}else{
|
||
fprintf(dest, "0x%08x,", buffer[i]);
|
||
}
|
||
}
|
||
|
||
fprintf(dest, "\n};\n\n#endif\n");
|
||
|
||
fclose(dest);
|
||
|
||
return 0;
|
||
}
|
||
|
||
|
||
/******************************************************************************/
|
||
|
||
|
||
int main(int argc, char *argv[])
|
||
{
|
||
int retv, i;
|
||
int flags = 0;
|
||
char *bdf_name = NULL;
|
||
char *font_name = NULL;
|
||
char *list_name = NULL;
|
||
char *label_name = NULL;
|
||
|
||
if(argc==1){
|
||
printf("\nUsage:\n");
|
||
printf("\tbdfont [-dg] [-dl] [-l list] [-adj base] [-s size] [-c name] [-h name label] font_file\n");
|
||
printf("\t\t-dg dump glyph\n");
|
||
printf("\t\t-dl dump char list\n");
|
||
printf("\t\t-l list load char list\n");
|
||
printf("\t\t-adj base adjust base line\n");
|
||
printf("\t\t-s size set font size(for ttf)\n");
|
||
printf("\t\t-c name\n");
|
||
printf("\t\t output binary font\n");
|
||
printf("\t\t-h name label\n");
|
||
printf("\t\t output c header font\n");
|
||
return 0;
|
||
}
|
||
|
||
for(i=1; i<argc; i++){
|
||
if(strcmp(argv[i], "-dg")==0){
|
||
flags |= 1;
|
||
}else if(strcmp(argv[i], "-dl")==0){
|
||
flags |= 2;
|
||
}else if(strcmp(argv[i], "-l")==0){
|
||
list_name = argv[i+1];
|
||
i += 1;
|
||
}else if(strcmp(argv[i], "-adj")==0){
|
||
base_adj = atoi(argv[i+1]);
|
||
i += 1;
|
||
}else if(strcmp(argv[i], "-s")==0){
|
||
font_size = atoi(argv[i+1]);
|
||
i += 1;
|
||
}else if(strcmp(argv[i], "-c")==0){
|
||
flags |= 4;
|
||
font_name = argv[i+1];
|
||
i += 1;
|
||
}else if(strcmp(argv[i], "-h")==0){
|
||
flags |= 8;
|
||
font_name = argv[i+1];
|
||
label_name = argv[i+2];
|
||
i += 2;
|
||
}else if(bdf_name==NULL){
|
||
bdf_name = argv[i];
|
||
}
|
||
}
|
||
|
||
load_list(list_name);
|
||
|
||
//retv = load_bdf(bdf_name);
|
||
retv = load_ttf(bdf_name);
|
||
if(retv<0)
|
||
return -1;
|
||
|
||
if(flags&1){
|
||
dump_glyph();
|
||
}else if(flags&2){
|
||
dump_list();
|
||
}else if(flags&4){
|
||
build_font();
|
||
FILE *fp = fopen(font_name, "wb");
|
||
fwrite(font_buf, 1, font_buf_size, fp);
|
||
fclose(fp);
|
||
}else if(flags&8){
|
||
build_font();
|
||
bin2c(font_buf, font_buf_size, font_name, label_name);
|
||
}
|
||
|
||
return 0;
|
||
}
|
||
|