TTF font rasterizer to use with links2

"Sergey V. Karpov" <[email protected]>
Newsgroups gmane.comp.web.links.list
Message-ID <[email protected]>
Hi all.

Due to frequent requests of ttf-to-png fonts rasterizer on this list I
decided to post source code of my solution for this problem. It is dirty
and a bit hackish, but sotetimes works as it has to ;-)

Source code of rasterizer.c attached. You may compile it by typing
something like this:

gcc rasterizer.c -o rasterizer -lgd -lfreetype -I/usr/include/freetype2

You need to have freetype2 and libgd
(http://www.boutell.com/gd/http/gd-2.0.15.tar.gz) installed.

Usage is very simple - ./rasterizer dump_all=1 fontfile.ttf
It will create ./tmp dir and place all available chars from your ttf in it
as properly named pngs.

Thanks,

Sergey

_______________________________________________
Links-list mailing list
[email protected]
http://linuxfromscratch.org/mailman/listinfo/links-list
rasterizer.c (text/plain, 10.7 KB)
/*

 Simple Unicode TTF rasterizer

 (part of Hacked Links project)

Usage: ./rasterizer <options> font_file.ttf
Where options are:
	height=120
	transform_x=1
	transform_y=1
	blur_pix=1
	blurs=1
	dump_all=0
	dump_first=0
	dump_last=65535

 it will create directory tmp/ and place char pngs to it

 */

#include <ft2build.h>
#include FT_FREETYPE_H
#include FT_GLYPH_H
#include FT_TRUETYPE_TABLES_H

/* You need libGD to compile this! */

#include <gd.h>
#include <stdio.h>
#include <stdlib.h>

/* Dump to text files instead of PNG */
#undef TEXT


/* Pixmap size */
#define HEIGHT 120

/* Transformation coefficients */
#define TRANSFORM_X 1
#define TRANSFORM_Y 1

/* Additional smoothing */
#define BLUR_PIX 1
#define BLURS 1

/* Whether to dump all lower Unicode */
#define DUMP_ALL 0

int height=HEIGHT;
double transform_x=TRANSFORM_X;
double transform_y=TRANSFORM_Y;
int blur_pix=BLUR_PIX;
int blurs=BLURS;
int dump_all=DUMP_ALL;
int dump_first=0;
int dump_last=65535;


int pixel_height;
int baseline;

struct chars_to_dump {
        int n1;
        int n2;
};

/* UNICODE sets to rasterize, just comment out or add what you want */
struct chars_to_dump chars[]={
        { 0x0000,0x00ff },        /* Latin-1 */
        { 0x0100,0x024f },        /* Latin Extended */
        { 0x0250,0x02af },        /* IPA Extensions */
        { 0x02b0,0x036f },        /* Spacings and Diacritics */
        { 0x0370,0x0400 },        /* Greek */
        { 0x0401,0x052f },        /* Cyrillic */
        { 0x0590,0x05ff },        /* Hebrew */
        { 0x0600,0x06ff },        /* Arabic */
        { 0x1e00,0x06ff },        /* Latin extended additional */
        { 0x1f00,0x1fff },        /* Greek extended */
        { 0x2000,0x20ff },        /* Punctuations, sub/supscripts, currencies */
        { 0x2100,0x21ff },        /* misc. */
        { 0,0 },    /* Must be the last!!! */
};

void blur_x(int *buffer,int width, int height)
{
        int x,y;
        int *buf=(int*)malloc(width*height*sizeof(int));

        for(y=0;y<height;y++)
                for(x=0;x<width;x++){
                        int sum=0;
                        int xmin=(x-blur_pix>0)?(x-blur_pix):0;
                        int xmax=(x+blur_pix<width)?(x+blur_pix):width-1;
                        double k=1./(xmax-xmin+1);
                        int xxx;
                        for(xxx=xmin;xxx<=xmax;xxx++)
                                sum+=k*buffer[y*width+xxx];
                        buf[y*width+x]=sum;
                }

        memcpy(buffer,buf,sizeof(int)*width*height);
        free(buf);
}

void blur_y(int *buffer,int width, int height)
{
        int x,y;
        int *buf=(int*)malloc(width*height*sizeof(int));

        for(x=0;x<width;x++)
                for(y=0;y<height;y++){
                        int sum=0;
                        int ymin=(y-blur_pix>0)?(y-blur_pix):0;
                        int ymax=(y+blur_pix<height)?(y+blur_pix):height-1;
                        double k=1./(ymax-ymin+1);
                        int yyy;
                        for(yyy=ymin;yyy<=ymax;yyy++)
                                sum+=k*buffer[yyy*width+x];
                        buf[y*width+x]=sum;
                }

        memcpy(buffer,buf,sizeof(int)*width*height);
        free(buf);
}

void dump_bitmap(int ch,unsigned char *buffer, int width, int height, int x0, int y0, int cols, int rows)
{
        char *filename=(char*)malloc(50);
        int x,y,i;
        int *bitmap=(int*)calloc(height*width,sizeof(int));

        snprintf(filename,49,"tmp/%04x.png",ch);
        printf(" -> %s\n",filename);
        
        if(width>0 && !(ch!=32 && rows==0)) {
                for(y=0;y<rows;y++){
                        for(x=0;x<cols;x++){
                                int l=y*cols+x;
                                int d=(y+y0)*width+x+x0;
                                if(buffer[l] && x+x0>0 && x+x0<width && y+y0>0 && y+y0<height)
                                        bitmap[d]=buffer[l];
                        }
                }
                for(i=0;i<BLURS;i++){
                        blur_x(bitmap,width,height);
                        blur_y(bitmap,width,height);
                }

#ifdef TEXT
                {
                        FILE *f=fopen(filename,"w");
                        for(y=0;y<height;y++){
                                for(x=0;x<width;x++){
                                        fprintf(f,"%d ",bitmap[y*width+x]);
                                }
                                fprintf(f,"\n");
                        }
                        fclose(f);
                }
#else
                {
                        gdImagePtr im=gdImageCreate(width,height);
                        FILE *f;
                        int *color=(int*)malloc(256*sizeof(int));
                        int d;
                        int x,y;

                        for(d=0;d<256;d++)
                                color[d]=gdImageColorAllocate(im,d,d,d);

                        for(y=0;y<height;y++)
                                for(x=0;x<width;x++)
                                        gdImageSetPixel(im,x,y,color[bitmap[y*width+x]]);

                        f=fopen(filename,"wb");
                        gdImagePng(im,f);
                        fclose(f);

                        gdImageDestroy(im);
                        free(color);
                }
#endif
        }

        free(filename);
        free(bitmap);
}

void look_at_char(FT_Face face,int ch)
{
        FT_GlyphSlot  slot = face->glyph;  // a small shortcut
        int glyph = FT_Get_Char_Index( face, ch );
        int width;

        if(glyph==0) return;
        printf("char %d -> glyph %d  ",ch,glyph);

        FT_Load_Char(face, ch, FT_LOAD_DEFAULT|FT_LOAD_RENDER|FT_LOAD_NO_HINTING);

        width=slot->advance.x >> 6;

        {
		FT_GlyphSlot  slot = face->glyph;  // a small shortcut
                FT_Bitmap bitmap=slot->bitmap;
                int rows=bitmap.rows;
                int pitch=bitmap.pitch;
                int cols=bitmap.width;
                int bitmap_top=slot->bitmap_top;
                int bitmap_left=slot->bitmap_left;
                int x0=bitmap_left;
                int y0=baseline-bitmap_top;
                int ngrays=bitmap.num_grays;

                printf("%d %d, %d %d, %d %d, %d", width, height, cols, rows, x0, y0, ngrays);
                dump_bitmap(ch,bitmap.buffer,width,height,x0,y0,cols,rows);
        }
}

int main(int argc, char** argv)
{
        FT_Library  library;
        FT_Face face;
        char *filename=NULL;
        int d;
        int font_ascend;
        int font_descend;
        int font_height;
	TT_HoriHeader   *hhea;

	if(FT_Init_FreeType( &library ))
                return 1;

        if(argc<2){
                printf("Usage: %s <options> font_file\n",argv[0]);
                printf("Where options are:\n");
                printf("\theight=%d\n",height);
                printf("\ttransform_x=%g\n",transform_x);
                printf("\ttransform_y=%g\n",transform_y);
                printf("\tblur_pix=%d\n",blur_pix);
                printf("\tblurs=%d\n",blurs);
                printf("\tdump_all=%d\n",dump_all);
                printf("\tdump_first=%d\n",dump_first);
                printf("\tdump_last=%d\n",dump_last);
                return 1;
        }

        for(d=1;d<argc;d++)
                if(!strncmp(argv[d],"height=",7))
                        sscanf(argv[d],"height=%d",&height);
                else if(!strncmp(argv[d],"transform_x=",12))
                        sscanf(argv[d],"transform_x=%lf",&transform_x);
                else if(!strncmp(argv[d],"transform_y=",12))
                        sscanf(argv[d],"transform_y=%lf",&transform_x);
                else if(!strncmp(argv[d],"blur_pix=",9))
                        sscanf(argv[d],"blur_pix=%d",&blur_pix);
                else if(!strncmp(argv[d],"blurs=",6))
                        sscanf(argv[d],"blurs=%d",&blurs);
                else if(!strncmp(argv[d],"dump_all=",9))
                        sscanf(argv[d],"dump_all=%d",&dump_all);
                else if(!strncmp(argv[d],"dump_first=",11))
                        sscanf(argv[d],"dump_first=%d",&dump_first);
                else if(!strncmp(argv[d],"dump_last=",10))
                        sscanf(argv[d],"dump_last=%d",&dump_last);
                else
                        filename=argv[d];

        if(!filename)
                return 1;

        printf("Trying %s\n",filename);
        if(FT_New_Face(library, filename,0,&face))
                return;
        printf("Ok, %s, %s\n",face->family_name,face->style_name);

	hhea = FT_Get_Sfnt_Table(face, ft_sfnt_hhea);

	font_ascend  = face->ascender;
        font_descend = face->descender;
        font_height  = face->height;

        /* Quick fix for freetype 2.1.5 un-handling of zero line_gap */
        if(font_height == font_ascend - font_descend)
            font_height *= 1.15;

        printf("Ascend %d, descend %d, height %d\n",font_ascend,font_descend,font_height);
        printf("Vertical BBox is %d - %d\n",face->bbox.yMin,face->bbox.yMax);

        pixel_height=(double)height*(font_ascend-font_descend)/(double)font_height;

        baseline=(double)height*(font_height+font_descend)/(double)font_height;

        printf("Our baseline will be at %d\n",baseline);

        FT_Set_Pixel_Sizes(face,0,pixel_height);

        {
                FT_Matrix     matrix;              // transformation matrix
                FT_Vector     origin;

                matrix.xx=(FT_Fixed)(transform_x*0x10000);
                matrix.xy=0;
                matrix.yx=0;
                matrix.yy=(FT_Fixed)(transform_y*0x10000);

                origin.x=0;
                origin.y=0;
                FT_Set_Transform(face,&matrix,&origin);
        }

        system("rm -rf tmp");
        system("mkdir tmp");

        if(dump_all){
                /* Dumping all lower Unicode */
                printf("Dumping all available UNICODE range...\n");
                for(d=dump_first;d<=dump_last;d++)
                        look_at_char(face,d);
        }
        else {
                d=0;
                while(chars[d].n2){
                        int ch;
                        int n1=chars[d].n1;
                        int n2=chars[d].n2;
                        printf("Processing UNICODE chars from %d till %d...\n",n1,n2);
                        for(ch=n1;ch<=n2;ch++)
                                look_at_char(face,ch);
                        d++;
                }
        }
        return 1;
}
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.