📄 generate_font.c
字号:
#include <sys/types.h>#include <sys/stat.h>#include <unistd.h>#include <dirent.h>#include <stdio.h>#include <errno.h>#include <stdlib.h>#include <fcntl.h>#include <png.h>#ifndef PROGNAME#define PROGNAME "generate_font"#endif /* #ifndef PROGNAME */struct letter{ int begin; /* Begin in the byte stream */ int length; /* Length (in bytes) of the PNG data in the byte stream */ int code; /* Unicode code of the character */ int xsize; int ysize; void *foo; void *bar;};struct font{ unsigned char *family; unsigned char *weight; unsigned char *slant; unsigned char *adstyl; unsigned char *spacing; int n_letters; /* Number of letters in this font */ struct letter *letters; };struct font *fonts;int n_fonts;int n_letters;int stamp;int file_select(const struct dirent * entry){ char *s=entry->d_name; FILE *f; if (strlen(s)!=8) return 0; if (!((s[0]>='0'&&s[0]<='9')||(s[0]>='a'&&s[0]<='f'))) return 0; if (!((s[1]>='0'&&s[1]<='9')||(s[1]>='a'&&s[1]<='f'))) return 0; if (!((s[2]>='0'&&s[2]<='9')||(s[2]>='a'&&s[2]<='f'))) return 0; if (!((s[3]>='0'&&s[3]<='9')||(s[3]>='a'&&s[3]<='f'))) return 0; if (s[4]!='.'||s[5]!='p'||s[6]!='n'||s[7]!='g') return 0; f=fopen(s,"r"); if (!f) return 0; /* If it can't be open as a file then it's probably * a directory */ fclose(f); return 1;}/* If the directory name has bad structure (must have 4 dashes in the name), * then nothing is done * Fills weight, slant, adstyl, spacing with appropriate strings * Returns 1 if the input should be skipped. */int parse_font_name(unsigned char *input, unsigned char **family, unsigned char **weight, unsigned char ** slant, unsigned char ** adstyl, unsigned char ** spacing){ int dashes=0; unsigned char *p, *r; FILE *f; unsigned char alias[256]; p=input; while(*p){ if (*p=='-') dashes++; p++; } if (dashes!=4) return 1; /* Invalid name structure -- ignore this entry */ if (chdir(input)){ /* Is a directory and has appropriate name, but can't * change into. */ fprintf(stderr,"%s: can't change into directory %s.\n", PROGNAME, input); perror(PROGNAME); exit(1); } p=input; r=p; while (*r!='-') r++; *family=malloc(r-p+1); if (!*family){ fprintf(stderr,"Out of memory.\n"); exit(1); } memcpy(*family,p,r-p); (*family)[r-p]=0; r++; p=r; while (*r!='-') r++; *weight=malloc(r-p+1); if (!*weight){ fprintf(stderr,"Out of memory.\n"); exit(1); } memcpy(*weight,p,r-p); (*weight)[r-p]=0; r++; p=r; while (*r!='-') r++; *slant=malloc(r-p+1); if (!*slant){ fprintf(stderr,"Out of memory.\n"); exit(1); } memcpy(*slant,p,r-p); (*slant)[r-p]=0; r++; p=r; while (*r!='-') r++; *adstyl=malloc(r-p+1); if (!*adstyl){ fprintf(stderr,"Out of memory.\n"); exit(1); } memcpy(*adstyl,p,r-p); (*adstyl)[r-p]=0; r++; p=r; while (*r) r++; *spacing=malloc(r-p+1); if (!*spacing){ fprintf(stderr,"Out of memory.\n"); exit(1); } memcpy(*spacing,p,r-p); (*spacing)[r-p]=0; /* Now let's append the aliases file contents */ f=fopen("aliases","r"); if (f){ while(fgets(alias,sizeof(alias),f)){ int length=strlen(alias); while(length>0&&alias[length-1]=='\n')length--; while(length>0&&alias[length-1]==' ')length--; while(length>0&&alias[length-1]=='\t')length--; alias[length]=0; if (!length) continue; *family=realloc(*family,strlen(*family)+2+strlen(alias)); strcpy(*family+strlen(*family),"-"); strcpy(*family+strlen(*family),alias); } fclose(f); } return 0;}/* Doesn't free the strings, just pushes them into the global structure */void add_font_name(unsigned char *family, unsigned char *weight,unsigned char*slant, unsigned char *adstyl, unsigned char *spacing){ struct font *f; n_fonts++; fonts=realloc(fonts,n_fonts*sizeof(*fonts)); if (!fonts){ fprintf(stderr,"%s: Out of memory\n",PROGNAME); exit(1); } f=fonts+n_fonts-1; f->family=family; f->weight=weight; f->slant=slant; f->adstyl=adstyl; f->spacing=spacing;}void get_png_dimensions(int *x, int *y, FILE * stream){ png_structp png_ptr; png_infop info_ptr; png_ptr=png_create_read_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); info_ptr=png_create_info_struct(png_ptr); png_init_io(png_ptr,stream); png_read_info(png_ptr, info_ptr); *x=png_get_image_width(png_ptr,info_ptr); *y=png_get_image_height(png_ptr,info_ptr); png_destroy_read_struct(&png_ptr, &info_ptr, NULL);}/* Returns forbidden_0_to_7 for next char. */int print_char(FILE *output, int c, int forbidden_0_to_7){ static int char_pos=0; /* To not makes lines excessively long. */ if (char_pos>=70){ fputs("\"\n\"",output); char_pos=0; } switch(c){ case '\n': fputs("\\n",output);two: char_pos+=2; forbidden_0_to_7=0; break; case '\t': fputs("\\t",output); goto two; case '\b': fputs("\\b",output); goto two; case '\r': fputs("\\r",output); goto two; case '\f': fputs("\\f",output); goto two; case '\\': fputs("\\\\",output); goto two; case '\'': fputs("\\\'",output); goto two; default: if (c<' '||c=='"'||c=='?'||c>126 ||(c>='0'&&c<='7'&&forbidden_0_to_7)){ fprintf(output,"\\%o",c); if (c>=0100) char_pos+=4; else if (c>=010) char_pos+=3; else char_pos+=2; forbidden_0_to_7=(c<0100); }else{ fprintf(output,"%c",c); char_pos++; forbidden_0_to_7=0; } break; } return forbidden_0_to_7;}/* name: path to file to process * output: where to put the C code * char_number: number of the char. -1 means do not write anything into the tables.*/static inline void process_file(unsigned char *name, FILE*output, int char_number){ FILE *f; int c; int letter_code=letter_code; int count=0; unsigned char btr[5]; int forbidden_0_to_7; f=fopen(name,"r"); if (!f){ fprintf(stderr,"%s can't open file %s.\n",PROGNAME, name); perror(PROGNAME); exit(1); } if (char_number>=0){ memcpy(btr,name,4); btr[4]=0; letter_code=strtoul(btr,NULL,16); fonts[n_fonts-1].letters[char_number].begin=stamp; } fprintf(output,"\""); forbidden_0_to_7=0; while(EOF!=(c=fgetc(f))){ forbidden_0_to_7=print_char(output,c,forbidden_0_to_7); stamp++; count++; } fprintf(output,"\"\n"); rewind(f); fonts[n_fonts-1].letters[char_number].length=count; fonts[n_fonts-1].letters[char_number].code=letter_code; get_png_dimensions(&(fonts[n_fonts-1].letters[char_number].xsize), &(fonts[n_fonts-1].letters[char_number].ysize),f); fclose(f);}void process_letters(FILE *output){ struct dirent **namelist; struct dirent **ptr; int nr,a; nr=scandir(".",&namelist,file_select,alphasort); if (nr<0){ perror(PROGNAME); exit(1); } fonts[n_fonts-1].n_letters=nr; if (!nr) return; if (nr<0){ perror(PROGNAME); exit(1); } n_letters+=nr; fonts[n_fonts-1].letters=malloc(sizeof(struct letter)*nr); if (!(fonts[n_fonts-1].letters)){ fprintf(stderr,"%s: Out of memory", PROGNAME); exit(1); } ptr=namelist; for(a=0;a<nr;a++){ process_file((*ptr)->d_name,output,a); free(*ptr); ptr++; } free(namelist);}/* build_font_table: * scans the font directory * for each directory: * * renews font description structures * * scans the images * * builds a binary search array * * writes the font structure into the ../font_include.c * * releases font description structures * Also prints the font_data byte table. */void build_font_table(FILE *output){ struct dirent *directory_entry; unsigned char *directory_name; DIR *dir; struct stat stat0; unsigned char *family, *weight, *slant, *adstyl, *spacing; directory_name="system_font"; if (0>chdir(directory_name)){ fprintf(stderr,"%s: can't change into directory %s.\n", PROGNAME,directory_name); perror(PROGNAME); exit(1); } add_font_name("","","","",""); process_letters(output); if (0>chdir("..")){ perror(PROGNAME); exit(1); } directory_name="font"; dir=opendir(directory_name); if (0>chdir(directory_name)){ fprintf(stderr,"%s can't change into directory %s.\n", PROGNAME,directory_name); perror(PROGNAME); exit(1); } if (!dir){ fprintf(stderr,"%s can't opendir() directory %s.\n",PROGNAME, directory_name); perror(PROGNAME); exit(1); } while((directory_entry=readdir(dir))){ if (0>stat(directory_entry->d_name,&stat0)) continue; /* Can't be stated */ if (!S_ISDIR(stat0.st_mode)) continue; /* Is no directory */ /* Process the directory */ if (parse_font_name(directory_entry->d_name,&family,&weight,&slant, &adstyl,&spacing)) { continue; /* Inappropriate name */ } /* If the directory is name a-... and in a-../aliases there * is * b * c * d *, then family is a-b-c-d. */ add_font_name(family,weight,slant,adstyl,spacing); process_letters(output); if (0>chdir("..")){ perror(PROGNAME); exit(1); } } fprintf(output,"\n};\n");}void print_string(unsigned char * ptr, FILE * output){ int forbidden_0_to_7; fprintf(output,"\""); forbidden_0_to_7=0; while(*ptr) forbidden_0_to_7=print_char(output,*ptr++,forbidden_0_to_7); fprintf(output,"\"");}void print_letter(struct letter *p, FILE * output){ fprintf(output,"{0x%08x,0x%08x,0x%08x,% 5d,% 5d, 0, 0}",p->begin,p->length, p->code, p->xsize, p->ysize);}void print_font(int a, FILE * output){ struct font *f=fonts+a; fprintf(output,"{\n"); print_string(f->family,output); fprintf(output,",\n"); print_string(f->weight,output); fprintf(output,",\n"); print_string(f->slant,output); fprintf(output,",\n"); print_string(f->adstyl,output); fprintf(output,",\n"); print_string(f->spacing,output); fprintf(output,",\n"); fprintf(output,"%d,\n",n_letters); fprintf(output,"%d,\n",f->n_letters); n_letters+=f->n_letters; fprintf(output,"},\n");}void print_font_table(FILE *output){ int a; int index; fprintf(output,"/* Font data %d bytes */\n\n",stamp); fprintf(output,"struct letter letter_data[%d]={\n",n_letters); for (a=0;a<n_fonts;a++){ struct letter *ptr=fonts[a].letters; int count=fonts[a].n_letters; for(;count;count--){ print_letter(ptr,output); fprintf(output,",\n"); ptr++; } } fprintf(output,"};\n\n"); fprintf(output,"struct font font_table[%d]={\n",n_fonts); n_letters=0; for (a=0,index=0;a<n_fonts;a++){ print_font(a,output); } fprintf(output,"};\n"); fprintf(output,"\nint n_fonts=%d;\n",n_fonts);}int main(int argc, char **argv){ FILE *output; int retval; while(!(output=fopen("font_include.c","w")) &&(errno==EAGAIN||errno==EINTR)); if (!output){ fprintf(stderr,PROGNAME ": "); perror("font_include.c"); exit(1); } fprintf(output,"#include \"cfg.h\"\n\n"); fprintf(output,"#ifdef G\n\n"); fprintf(output,"#include \"links.h\"\n\n"); fprintf(output,"unsigned char font_data[]={\n"); build_font_table(output); print_font_table(output); fprintf(output,"\n\n#endif\n\n"); while ((retval=fclose(output)&&(errno==EAGAIN||errno==EINTR))); if (retval){ perror(PROGNAME); exit(1); } return 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -