u8g2-copy/tools/font/bdfconv/main.c

414 lines
10 KiB
C

#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "bdf_font.h"
#include "fd.h"
/*================================================*/
int get_str_arg(char ***argv, int c, char **result)
{
if ( (**argv)[0] == '-' )
{
if ( (**argv)[1] == c )
{
if ( (**argv)[2] == '\0' )
{
(*argv)++;
*result = **argv;
}
else
{
*result = (**argv)+2;
}
(*argv)++;
return 1;
}
}
return 0;
}
int get_num_arg(char ***argv, int c, unsigned long *result)
{
if ( (**argv)[0] == '-' )
{
if ( (**argv)[1] == c )
{
if ( (**argv)[2] == '\0' )
{
if ( *((*argv)+1) != NULL )
{
(*argv)++;
*result = strtoul((**argv), NULL, 10);
}
}
else
{
*result = strtoul((**argv)+2, NULL, 10);
}
(*argv)++;
return 1;
}
}
return 0;
}
int is_arg(char ***argv, int c)
{
if ( (**argv)[0] == '-' )
{
if ( (**argv)[1] == c )
{
(*argv)++;
return 1;
}
}
return 0;
}
/*================================================*/
void help(void)
{
printf("bdfconv [options] filename\n");
printf("-h Display this help\n");
printf("-v Print log messages\n");
printf("-b <n> Font build mode, 0: proportional, 1: common height, 2: monospace, 3: multiple of 8\n");
printf("-f <n> Font format, 0: ucglib font, 1: u8g2 font, 2: u8g2 uncompressed 8x8 font (enforces -b 3)\n");
printf("-m 'map' Unicode ASCII mapping\n");
printf("-M 'mapfile' Read Unicode ASCII mapping from file 'mapname'\n");
printf("-o <file> C output file\n");
printf("-n <name> C indentifier (font name)\n");
printf("-d <file> Overview picture: Enable generation of bdf.tga and assign BDF font <file> for description\n");
printf("-l <margin> Overview picture: Set left margin\n");
printf("-a Overview picture: Additional font information (background, orange&blue dot)\n");
printf("-t Overview picture: Test string (Woven silk pyjamas exchanged for blue quartz.)\n");
printf("-r Runtime test\n");
printf("\n");
printf("map := <mapcmd> { \",\" <mapcmd> }\n");
printf("mapcmd := <default> | <maprange> | <exclude>\n");
printf("default := \"*\"\n");
printf("maprange := <range> [ \">\" <addexpr> ] Move specified glyph <range> to target code <num>\n");
printf("exclude := \"~\" <range> \n");
printf("range := <addexpr> [ \"-\" <addexpr> ] Select glyphs within specified range\n");
printf("addexpr := <mulexpr> [ \"+\" <mulexpr> ]\n");
printf("mulexpr := <num> [ \"*\" <num> ]\n");
printf("num := <hexnum> | <decnum>\n");
printf("hexnum := \"$\" <hexdigit> { <hexdigit> }\n");
printf("decnum := <decdigit> { <decdigit> }\n");
printf("decdigit := \"0\" | \"1\" | \"2\" | \"3\" | \"4\" | \"5\" | \"6\" | \"7\" | \"8\" | \"9\"\n");
printf("hexdigit := \"a\" | \"b\" | \"c\" | \"d\" | \"e\" | \"f\" | \"A\" | \"B\" | \"C\" | \"D\" | \"E\" | \"F\" | <decdigit>\n");
printf("{ } zero, one ore more, [ ] zero or once, | alternative\n");
printf("example:\n");
printf(" -m '32-255' select gylphs from encoding 32 to 255\n");
printf(" -m '32-255,~64' select gylphs from encoding 32 to 255, exclude '@'\n");
printf(" -m '32,48-57' select space, '1', '2', ... '9'\n");
printf("build modes:\n");
printf(" -b 0: Most compact, glyph bitmap is minimal\n");
printf(" -b 1: Like -b 0, but glyph bitmap is extended to the height of the largest glyph within the selected glyph list.\n");
printf(" Also the width of the gylphs is extended to cover the delta x advance.\n");
printf(" -b 2: Like -b 1, but glyph width is set to the width of the largest glyph within the selected gylph list.\n");
printf(" -b 3: Like -b 2, but width and height are forced to be a multiple of 8.\n");
}
/*================================================*/
unsigned long left_margin = 1;
unsigned long build_bbx_mode = 0;
unsigned long font_format = 0;
int font_picture_extra_info = 0;
int font_picture_test_string = 0;
int runtime_test = 0;
char *c_filename = NULL;
char *target_fontname = "bdf_font";
/*================================================*/
unsigned tga_get_line_height(bf_t *bf_desc_font, bf_t *bf)
{
unsigned h;
tga_set_font(bf_desc_font->target_data);
h = tga_get_char_height();
tga_set_font(bf->target_data);
if ( h < tga_get_char_height() )
return tga_get_char_height();
return h;
}
unsigned tga_draw_font_line(unsigned y, long enc_start, bf_t *bf_desc_font, bf_t *bf)
{
long i;
unsigned x;
int is_empty;
char pre[32];
is_empty = 1;
for( i = 0; i< 16 && is_empty != 0; i++ )
{
if ( tga_get_glyph_data(i+enc_start) != NULL )
is_empty = 0;
}
if ( is_empty != 0 )
return 0;
sprintf(pre, "%5ld/0x%04lx", enc_start, enc_start);
x = left_margin;
if ( bf_desc_font != NULL )
{
if ( bf_desc_font->target_data != NULL )
{
tga_set_font(bf_desc_font->target_data);
x += tga_draw_string(x, y, pre, 0, 0);
}
}
x += 4;
tga_set_font(bf->target_data);
for( i = 0; i< 16; i++ )
{
tga_draw_glyph(x + (tga_get_char_width()+2)*i,y,enc_start+i, font_picture_extra_info);
}
return left_margin + x + (tga_get_char_width()+2)*16;
}
unsigned tga_draw_font_info(unsigned y, const char *fontname, bf_t *bf_desc_font, bf_t *bf)
{
unsigned x;
int cap_a, cap_a_height;
static char s[256];
cap_a_height = 0;
cap_a = bf_GetIndexByEncoding(bf, 'A');
if ( cap_a >= 0 )
{
cap_a_height = bf->glyph_list[cap_a]->bbx.h+bf->glyph_list[cap_a]->bbx.y;
}
if ( bf_desc_font != NULL )
{
if ( bf_desc_font->target_data != NULL )
{
tga_set_font(bf_desc_font->target_data);
y += tga_get_char_height()+1;
x = left_margin;
x += tga_draw_string(x, y, fontname, 0, 0);
y += tga_get_char_height()+1;
sprintf(s, "Max width %u, max height %u", tga_get_char_width(), tga_get_char_height());
x = left_margin;
x += tga_draw_string(x, y, s, 0, 0);
y += tga_get_char_height()+1;
sprintf(s, "'A' height %d, font size %d ", cap_a_height, bf->target_cnt);
x = left_margin;
x += tga_draw_string(x, y, s, 0, 0);
return (tga_get_char_height()+1)*3;
}
}
return 0;
}
unsigned tga_draw_font(unsigned y, const char *fontname, bf_t *bf_desc_font, bf_t *bf)
{
long i;
unsigned x, xmax;
xmax = 0;
y += tga_draw_font_info( y, fontname, bf_desc_font, bf);
y += tga_get_line_height(bf_desc_font, bf)+1;
for( i = 0; i <= 0x0ffff; i+=16 )
{
x = tga_draw_font_line(y, i, bf_desc_font, bf);
if ( x > 0 )
{
if ( xmax < x )
xmax = x;
y += tga_get_line_height(bf_desc_font, bf)+1;
}
}
tga_set_font(bf->target_data);
//tga_draw_string(0, y, "Woven silk pyjamas exchanged for blue quartz", 1, xmax);
//y += tga_get_char_height()+1;
if ( font_picture_test_string != 0 )
{
tga_draw_string(left_margin, y, "Woven silk pyjamas exchanged for blue quartz.", 0, xmax);
y += tga_get_line_height(bf_desc_font, bf)+1;
}
return y;
}
/*================================================*/
/* main */
int main(int argc, char **argv)
{
bf_t *bf_desc_font;
bf_t *bf;
char *bdf_filename = NULL;
int is_verbose = 0;
char *map_str ="*";
char *map_filename ="";
char *desc_font_str = "";
unsigned y;
argv++;
/*
if ( *argv == NULL )
{
help();
exit(1);
}
*/
for(;;)
{
if ( *argv == NULL )
break;
if ( is_arg(&argv, 'h') != 0 )
{
help();
exit(1);
}
else if ( is_arg(&argv, 'v') != 0 )
{
is_verbose = 1;
}
else if ( is_arg(&argv, 'a') != 0 )
{
font_picture_extra_info = 1;
}
else if ( is_arg(&argv, 't') != 0 )
{
font_picture_test_string = 1;
}
else if ( is_arg(&argv, 'r') != 0 )
{
runtime_test = 1;
}
else if ( get_num_arg(&argv, 'b', &build_bbx_mode) != 0 )
{
}
else if ( get_num_arg(&argv, 'f', &font_format) != 0 )
{
}
else if ( get_num_arg(&argv, 'l', &left_margin) != 0 )
{
}
else if ( get_str_arg(&argv, 'd', &desc_font_str) != 0 )
{
}
else if ( get_str_arg(&argv, 'o', &c_filename) != 0 )
{
}
else if ( get_str_arg(&argv, 'n', &target_fontname) != 0 )
{
}
else if ( get_str_arg(&argv, 'm', &map_str) != 0 )
{
}
else if ( get_str_arg(&argv, 'M', &map_filename) != 0 )
{
}
else
{
bdf_filename = *argv;
argv++;
}
}
if ( bdf_filename == NULL )
{
help();
exit(1);
}
bf_desc_font = NULL;
if ( desc_font_str[0] != '\0' )
{
bf_desc_font = bf_OpenFromFile(desc_font_str, 0, BDF_BBX_MODE_MINIMAL, "*", "", 0); /* assume format 0 for description */
if ( bf_desc_font == NULL )
{
exit(1);
}
}
if ( font_format == 2 )
{
build_bbx_mode = BDF_BBX_MODE_M8;
/* issue the following log message later, when there is a valid bf object */
/* bf_Log(bf, "Font mode 1: BBX mode set to 3"); */
}
bf = bf_OpenFromFile(bdf_filename, is_verbose, build_bbx_mode, map_str, map_filename, font_format);
if ( bf == NULL )
{
exit(1);
}
if ( font_format == 2 )
{
/* now generate the log message */
bf_Log(bf, "Note: For font format 1 BBX mode has been set to 3");
}
if ( bf_desc_font != NULL )
{
tga_init(1024, 1024*9);
if ( target_fontname[0] != '\0' )
y = tga_draw_font(0, target_fontname, bf_desc_font, bf);
else
y = tga_draw_font(0, bdf_filename, bf_desc_font, bf);
if ( runtime_test != 0 )
{
long i;
clock_t c = clock();
fd_t fd;
fd_init(&fd);
fd_set_font(&fd, bf->target_data);
for( i = 0; i < 10000; i++ )
fd_draw_string(&fd, left_margin, y, "Woven silk pyjamas exchanged for blue quartz.");
bf_Log(bf, "Runtime test: %.2lf sec", (double)(clock()-c)/(double)CLOCKS_PER_SEC);
}
tga_save("bdf.tga");
}
if ( c_filename != NULL )
{
/* write the encoded data in bf->target_data */
if ( font_format == 0 )
{
bf_WriteUCGCByFilename(bf, c_filename, target_fontname, " ");
}
else
{
/* font format >= 1 are for u8g2 */
bf_WriteU8G2CByFilename(bf, c_filename, target_fontname, " ");
}
}
bf_Close(bf);
return 0;
}