File: bixofont.cpp | Size: 10,435 bytes | Download file | Back to directory listing | BWPOW's homepage
/***********************************************************************************
    Bixofont - Utility for converting TTF fonts to Bixolon format
    Copyright (C) 2012 SAGE team s.r.o.
 
    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/.
***********************************************************************************/
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <limits.h>
 
#include <allegro.h>
#include <winalleg.h>
 
#include <ft2build.h>
#include FT_FREETYPE_H
 
FT_Library ftl;
FT_Face face;
volatile int is_end=FALSE;
int threshold=127;
 
uint32_t iso88592[256]={
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,
0x001F,0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,
0x003E,0x003F,0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005A,0x005B,0x005C,
0x005D,0x005E,0x005F,0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007A,0x007B,
0x007C,0x007D,0x007E,0x007F,0x0080,0x0081,0x0082,0x0083,0x0084,0x0085,0x0086,0x0087,0x0088,0x0089,0x008A,0x008B,0x008C,0x008D,0x008E,0x008F,0x0090,0x0091,0x0092,0x0093,0x0094,0x0095,0x0096,0x0097,0x0098,0x0099,0x009A,
0x009B,0x009C,0x009D,0x009E,0x009F,0x00A0,0x0104,0x02D8,0x0141,0x00A4,0x013D,0x015A,0x00A7,0x00A8,0x0160,0x015E,0x0164,0x0179,0x00AD,0x017D,0x017B,0x00B0,0x0105,0x02DB,0x0142,0x00B4,0x013E,0x015B,0x02C7,0x00B8,0x0161,
0x015F,0x0165,0x017A,0x02DD,0x017E,0x017C,0x0154,0x00C1,0x00C2,0x0102,0x00C4,0x0139,0x0106,0x00C7,0x010C,0x00C9,0x0118,0x00CB,0x011A,0x00CD,0x00CE,0x010E,0x0110,0x0143,0x0147,0x00D3,0x00D4,0x0150,0x00D6,0x00D7,0x0158,
0x016E,0x00DA,0x0170,0x00DC,0x00DD,0x0162,0x00DF,0x0155,0x00E1,0x00E2,0x0103,0x00E4,0x013A,0x0107,0x00E7,0x010D,0x00E9,0x0119,0x00EB,0x011B,0x00ED,0x00EE,0x010F,0x0111,0x0144,0x0148,0x00F3,0x00F4,0x0151,0x00F6,0x00F7,
0x0159,0x016F,0x00FA,0x0171,0x00FC,0x00FD,0x0163,0x02D9
};
 
uint32_t win1250[256]={
0x0000,0x0001,0x0002,0x0003,0x0004,0x0005,0x0006,0x0007,0x0008,0x0009,0x000A,0x000B,0x000C,0x000D,0x000E,0x000F,0x0010,0x0011,0x0012,0x0013,0x0014,0x0015,0x0016,0x0017,0x0018,0x0019,0x001A,0x001B,0x001C,0x001D,0x001E,
0x001F,0x0020,0x0021,0x0022,0x0023,0x0024,0x0025,0x0026,0x0027,0x0028,0x0029,0x002A,0x002B,0x002C,0x002D,0x002E,0x002F,0x0030,0x0031,0x0032,0x0033,0x0034,0x0035,0x0036,0x0037,0x0038,0x0039,0x003A,0x003B,0x003C,0x003D,
0x003E,0x003F,0x0040,0x0041,0x0042,0x0043,0x0044,0x0045,0x0046,0x0047,0x0048,0x0049,0x004A,0x004B,0x004C,0x004D,0x004E,0x004F,0x0050,0x0051,0x0052,0x0053,0x0054,0x0055,0x0056,0x0057,0x0058,0x0059,0x005A,0x005B,0x005C,
0x005D,0x005E,0x005F,0x0060,0x0061,0x0062,0x0063,0x0064,0x0065,0x0066,0x0067,0x0068,0x0069,0x006A,0x006B,0x006C,0x006D,0x006E,0x006F,0x0070,0x0071,0x0072,0x0073,0x0074,0x0075,0x0076,0x0077,0x0078,0x0079,0x007A,0x007B,
0x007C,0x007D,0x007E,0x007F,0x20AC,0x0000,0x201A,0x0000,0x201E,0x2026,0x2020,0x2021,0x0000,0x2030,0x0160,0x2039,0x015A,0x0164,0x017D,0x0179,0x0000,0x2018,0x2019,0x201C,0x201D,0x2022,0x2013,0x2014,0x0000,0x2122,0x0161,
0x203A,0x015B,0x0165,0x017E,0x017A,0x00A0,0x02C7,0x02D8,0x0141,0x00A4,0x0104,0x00A6,0x00A7,0x00A8,0x00A9,0x015E,0x00AB,0x00AC,0x00AD,0x00AE,0x017B,0x00B0,0x00B1,0x02DB,0x0142,0x00B4,0x00B5,0x00B6,0x00B7,0x00B8,0x0105,
0x015F,0x00BB,0x013D,0x02DD,0x013E,0x017C,0x0154,0x00C1,0x00C2,0x0102,0x00C4,0x0139,0x0106,0x00C7,0x010C,0x00C9,0x0118,0x00CB,0x011A,0x00CD,0x00CE,0x010E,0x0110,0x0143,0x0147,0x00D3,0x00D4,0x0150,0x00D6,0x00D7,0x0158,
0x016E,0x00DA,0x0170,0x00DC,0x00DD,0x0162,0x00DF,0x0155,0x00E1,0x00E2,0x0103,0x00E4,0x013A,0x0107,0x00E7,0x010D,0x00E9,0x0119,0x00EB,0x011B,0x00ED,0x00EE,0x010F,0x0111,0x0144,0x0148,0x00F3,0x00F4,0x0151,0x00F6,0x00F7,
0x0159,0x016F,0x00FA,0x0171,0x00FC,0x00FD,0x0163,0x02D9
};
 
void close_button_handler(void)
{
    is_end=TRUE;
}
END_OF_FUNCTION(close_button_handler)
 
void main_koniec(const int e,const char *str)
{
    set_gfx_mode(-1,0,0,0,0);
    if(str!=NULL){
        allegro_message(str);
    }
    allegro_exit();
    exit(e);
}
 
void main_koniec(const int e)
{
    main_koniec(e,NULL);
}
 
void main_koniec(const char *str)
{
    main_koniec(1,str);
}
 
void main_usage(const char *argv0)
{
    char text[4096];
    sprintf(text,"Usage: %s ENCODING TYPE SIZE INPUTFILE OUTPUTFILE [XDPI YDPI] [THRESHOLD]\n",argv0);
    strcat(text,"ENCODING:\n");
    strcat(text,"\twin1250 - windows-1250\n");
    strcat(text,"\tlatin2 - ISO 8859-2 (latin2)\n");
    strcat(text,"TYPE:\n");
    strcat(text,"\t65 - A (12x24) font\n");
    strcat(text,"\t66 - B (9x17) font\n");
    strcat(text,"\t67 - C (9x24) font\n");
    strcat(text,"SIZE - number from 5 to 100\n");
    strcat(text,"INPUTFILE - ttf font file\n");
    strcat(text,"XDPI, YDPI - width and height DPI, default 60 100\n");
    strcat(text,"THRESHOLD - threshold for distinguishing between black and white pixel (0-255), default 127\n");
    main_koniec(1,text);
}
 
void main_draw(BITMAP *bmp,int sx,int sy,uint32_t ch,int pw,int ph,int bl,uint8_t *obuf=NULL)
{
    FT_UInt glyph_index=0;
    glyph_index=FT_Get_Char_Index(face,ch);
    if(FT_Load_Glyph(face,glyph_index,FT_LOAD_DEFAULT)) return;
    if(FT_Render_Glyph(face->glyph,FT_RENDER_MODE_NORMAL)) return;
 
    int shift=(pw&7)?((pw|7)+1):pw;
    int p;
    int xx,yy;
    for(int y=0;y<face->glyph->bitmap.rows;y++){
        for(int x=0;x<face->glyph->bitmap.width;x++){
            if(face->glyph->bitmap.buffer[face->glyph->bitmap.width*y+x]>threshold){
                xx=x+face->glyph->bitmap_left;
                yy=y+bl-face->glyph->bitmap_top;
                if(xx>=0&&yy>=0&&xx<pw&&y<ph){
                    if(obuf!=NULL){
                        p=xx+shift*yy;
                        obuf[p>>3]|=1<<(7-(p&7));
                    }
                    putpixel(bmp,sx+xx,sy+yy,0);
                }
            }
        }
    }
}
 
int main(int argc,char *argv[])
{
    int type,sz,xdpi=60,ydpi=100;
    int tw,th;
    char infile[MAX_PATH],outfile[MAX_PATH];
    uint32_t *enc=NULL;
 
    try{
        if(allegro_init()!=0) throw 1;
        set_window_title("Bixofont");
        if(install_keyboard()!=0) throw 2;
        if(install_timer()!=0) throw 3;
        if(install_mouse()==0) throw 4;
        if(FT_Init_FreeType(&ftl)) throw 5;
    }
    catch(int e){
        main_koniec(e,"INIT failed");
    }
 
    if(argc<6) main_usage(argv[0]);
    if(sscanf(argv[2],"%d",&type)!=1) main_usage(argv[0]);
    if(type<65||type>67) main_usage(argv[0]);
    if(type==65){ tw=12; th=24; }
    if(type==66){ tw=9; th=17; }
    if(type==67){ tw=9; th=24; }
 
    if(sscanf(argv[3],"%d",&sz)!=1) main_usage(argv[0]);
    if(sz<5||sz>100) main_usage(argv[0]);
    if(strlen(argv[4])>=MAX_PATH||strlen(argv[5])>=MAX_PATH) main_usage(argv[0]);
    strcpy(infile,argv[4]);
    strcpy(outfile,argv[5]);
 
    if(!strcasecmp(argv[1],"win1250")) enc=&win1250[0];
    if(!strcasecmp(argv[1],"latin2")) enc=&iso88592[0];
    if(enc==NULL) main_usage(argv[0]);
 
    if(argc>=8){
        if(sscanf(argv[6],"%d",&xdpi)!=1||sscanf(argv[7],"%d",&ydpi)!=1) main_usage(argv[0]);
        if(xdpi<10||xdpi>1200) main_usage(argv[0]);
        if(ydpi!=0&&(ydpi<10||ydpi>1200)) main_usage(argv[0]);
    }
 
    if(argc>=9){
        if(sscanf(argv[8],"%d",&threshold)!=1) main_usage(argv[0]);
        if(threshold<0||threshold>255) main_usage(argv[0]);
    }
 
    if(!exists(infile)) main_koniec(1,"Input file missing!");
    if(FT_New_Face(ftl,infile,0,&face)) main_koniec(1,"Can't read font!");
    if(FT_Set_Char_Size(face,sz*64,0,xdpi,ydpi)) main_koniec(1,"Wrong size!");
 
    LOCK_FUNCTION(close_button_handler);
    set_close_button_callback(close_button_handler);
 
    set_color_depth(24);
    if(set_gfx_mode(GFX_AUTODETECT_WINDOWED,480,480,0,0)!=0) main_koniec(1,"Can't set gfx mode!");
    textout_centre_ex(screen,font,"Rendering, please wait...",screen->w/2,screen->h/2-4,makecol(255,255,255),0);
    show_mouse(screen);
 
 
    BITMAP *bmp=create_bitmap(screen->w,screen->h);
    if(bmp==NULL) main_koniec(1,"Alloc error");
    clear_to_color(bmp,makecol(155,155,155));
 
    size_t l,el;
    uint8_t obuf[16000];
 
    memset(obuf,0,sizeof(obuf));
    el=(((tw&7)?((tw|7)+1):tw)*th)>>3;
    l=0;
 
    for(int y=0;y<16;y++){
        for(int x=0;x<16;x++){
            set_clip_rect(bmp,x*30,y*30,x*30+tw,y*30+th);
            rectfill(bmp,x*30,y*30,x*30+tw,y*30+th,makecol(255,255,255));
            main_draw(bmp,x*30,y*30,enc[x+y*16],tw,th,th-th/4,obuf+l);
            l+=el;
        }
    }
 
    FILE *s=fopen(outfile,"wb");
    if(s==0) main_koniec(1,"Can't write to output file!");
 
    fputc(0x08,s);
    fputc(0x46,s);
    fputc(0x57,s);
    fputc(0x0,s);
    fputc(type,s);
    fwrite(obuf,1,l/2,s);
 
    fputc(0x08,s);
    fputc(0x46,s);
    fputc(0x57,s);
    fputc(0x1,s);
    fputc(type,s);
    fwrite(obuf+(l/2),1,l/2,s);
 
    fclose(s);
 
    show_mouse(NULL);
    blit(bmp,screen,0,0,0,0,bmp->w,bmp->h);
    show_mouse(screen);
 
    while(!is_end){
        if(key[KEY_ESC]) is_end=TRUE;
        if(key[KEY_SPACE]) is_end=TRUE;
        rest(0);
    }
    show_mouse(NULL);
 
    main_koniec(0);
    return 0;
}
END_OF_MAIN()