freetype
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[ft] setting the X*Y size and positioning the bitmaps


From: Albert Cahalan
Subject: [ft] setting the X*Y size and positioning the bitmaps
Date: Sun, 15 Apr 2007 12:53:32 -0400

I'm trying to convert vector fonts for console use. This should be
really easy. :-)

For this purpose, both points and dpi are nonsense. I can't feed
those values to freetype and read back the resulting pixel size.
I already have a non-negotiable size, and the size of a point seems
to depend on the font designer's whim anyway.

Then there is the matter of positioning the bitmaps. Freetype makes
this really difficult by giving me only partial bitmaps. I've been
throwing wild guess at the problem, using things like ascender and
bitmap_top to position this as best as I can. Things are getting
cut off, despite not filling the character cells.

Here is the current code, outputting a PGM file on stdout.

#define _GNU_SOURCE
#include <ctype.h>
#include <langinfo.h>
#include <locale.h>
#include <stdio.h>
#include <stdlib.h>  /* MB_CUR_MAX */
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <wchar.h>
#include <wctype.h>

#include <ft2build.h>
#include FT_FREETYPE_H

static unsigned short charlist[1024] = {
// PC VT100 Latin1 Nigeria Windows ISO-8859-15 groff WGL4 html4
0x0000, 0x263a, 0x263b, 0x2665, 0x2666, 0x2663, 0x2660, 0x2022,
0x25d8, 0x25cb, 0x25d9, 0x2642, 0x2640, 0x266a, 0x266b, 0x263c,
0x25b6, 0x25c0, 0x2195, 0x203c, 0x00b6, 0x00a7, 0x25ac, 0x21a8,
0x2191, 0x2193, 0x2192, 0x2190, 0x221f, 0x2194, 0x25b2, 0x25bc,
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, 0x2302,
0x00c7, 0x00fc, 0x00e9, 0x00e2, 0x00e4, 0x00e0, 0x00e5, 0x00e7,
0x00ea, 0x00eb, 0x00e8, 0x00ef, 0x00ee, 0x00ec, 0x00c4, 0x00c5,
0x00c9, 0x00e6, 0x00c6, 0x00f4, 0x00f6, 0x00f2, 0x00fb, 0x00f9,
0x00ff, 0x00d6, 0x00dc, 0x00a2, 0x00a3, 0x00a5, 0x20a7, 0x0192,
0x00e1, 0x00ed, 0x00f3, 0x00fa, 0x00f1, 0x00d1, 0x00aa, 0x00ba,
0x00bf, 0x2310, 0x00ac, 0x00bd, 0x00bc, 0x00a1, 0x00ab, 0x00bb,
0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556,
0x2555, 0x2563, 0x2551, 0x2557, 0x255d, 0x255c, 0x255b, 0x2510,
0x2514, 0x2534, 0x252c, 0x251c, 0x2500, 0x253c, 0x255e, 0x255f,
0x255a, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256c, 0x2567,
0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256b,
0x256a, 0x2518, 0x250c, 0x2588, 0x2584, 0x258c, 0x2590, 0x2580,
0x03b1, 0x00df, 0x0393, 0x03c0, 0x03a3, 0x03c3, 0x00b5, 0x03c4,
0x03a6, 0x0398, 0x03a9, 0x03b4, 0x221e, 0x03c6, 0x03b5, 0x2229,
0x2261, 0x00b1, 0x2265, 0x2264, 0x2320, 0x2321, 0x00f7, 0x2248,
0x00b0, 0x2219, 0x00b7, 0x221a, 0x207f, 0x00b2, 0x25a0, 0x00a0,

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, 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,
0x00a4, 0x00a6, 0x00a8, 0x00a9, 0x00ad, 0x00ae, 0x00af, 0x00b3,
0x00b4, 0x00b8, 0x00b9, 0x00be, 0x00c0, 0x00c1, 0x00c2, 0x00c3,
0x00c8, 0x00ca, 0x00cb, 0x00cc, 0x00cd, 0x00ce, 0x00cf, 0x00d0,
0x00d2, 0x00d3, 0x00d4, 0x00d5, 0x00d7, 0x00d8, 0x00d9, 0x00da,
0x00db, 0x00dd, 0x00de, 0x00e3, 0x00f0, 0x00f5, 0x00f8, 0x00fd,
0x00fe, 0x2260, 0x23ba, 0x23bb, 0x23bc, 0x23bd, 0x2409, 0x240a,
0x240b, 0x240c, 0x240d, 0x25c6, 0xfffd,

0x0100, 0x0101, 0x0112, 0x0113, 0x012a, 0x012b, 0x014c, 0x014d,
0x016a, 0x016b, 0x0181, 0x018a, 0x018e, 0x0198, 0x0199, 0x01dd,
0x0253, 0x0257, 0x0300, 0x0301, 0x0304, 0x0329, 0x05d1, 0x05d9,
0x05e2, 0x05e8, 0x05ea, 0x1e62, 0x1e63, 0x1eb8, 0x1eb9, 0x1eca,
0x1ecb, 0x1ecc, 0x1ecd, 0x1ee4, 0x1ee5, 0x2013, 0x20a6,

0x0152, 0x0153, 0x0160, 0x0161, 0x0178, 0x017d, 0x017e, 0x02c6,
0x02dc, 0x2014, 0x2018, 0x2019, 0x201a, 0x201c, 0x201d, 0x201e,
0x2020, 0x2021, 0x2026, 0x2030, 0x2039, 0x203a, 0x20ac, 0x2122,

0x0391, 0x0392, 0x0394, 0x0395, 0x0396, 0x0397, 0x0399, 0x039a,
0x039b, 0x039c, 0x039d, 0x039e, 0x039f, 0x03a0, 0x03a1, 0x03a4,
0x03a5, 0x03a7, 0x03a8, 0x03b2, 0x03b3, 0x03b6, 0x03b7, 0x03b8,
0x03b9, 0x03ba, 0x03bb, 0x03bc, 0x03bd, 0x03be, 0x03bf, 0x03c1,
0x03c2, 0x03c5, 0x03c7, 0x03c8, 0x03c9, 0x03d1, 0x03d6, 0x2032,
0x2033, 0x203e, 0x2044, 0x2111, 0x2118, 0x211c, 0x2135, 0x21d0,
0x21d1, 0x21d2, 0x21d3, 0x21d4, 0x2200, 0x2202, 0x2203, 0x2205,
0x2207, 0x2208, 0x2209, 0x220b, 0x220f, 0x2211, 0x2212, 0x2217,
0x221d, 0x2220, 0x2227, 0x2228, 0x222a, 0x222b, 0x2234, 0x223c,
0x2245, 0x2282, 0x2283, 0x2284, 0x2286, 0x2287, 0x2295, 0x2297,
0x22a5, 0x22c5, 0x2308, 0x2309, 0x230a, 0x230b, 0x2329, 0x232a,
0x25ca,

0x0102, 0x0103, 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109,
0x010a, 0x010b, 0x010c, 0x010d, 0x010e, 0x010f, 0x0110, 0x0111,
0x0114, 0x0115, 0x0116, 0x0117, 0x0118, 0x0119, 0x011a, 0x011b,
0x011c, 0x011d, 0x011e, 0x011f, 0x0120, 0x0121, 0x0122, 0x0123,
0x0124, 0x0125, 0x0126, 0x0127, 0x0128, 0x0129, 0x012c, 0x012d,
0x012e, 0x012f, 0x0130, 0x0131, 0x0132, 0x0133, 0x0134, 0x0135,
0x0136, 0x0137, 0x0138, 0x0139, 0x013a, 0x013b, 0x013c, 0x013d,
0x013e, 0x013f, 0x0140, 0x0141, 0x0142, 0x0143, 0x0144, 0x0145,
0x0146, 0x0147, 0x0148, 0x0149, 0x014a, 0x014b, 0x014e, 0x014f,
0x0150, 0x0151, 0x0154, 0x0155, 0x0156, 0x0157, 0x0158, 0x0159,
0x015a, 0x015b, 0x015c, 0x015d, 0x015e, 0x015f, 0x0162, 0x0163,
0x0164, 0x0165, 0x0166, 0x0167, 0x0168, 0x0169, 0x016c, 0x016d,
0x016e, 0x016f, 0x0170, 0x0171, 0x0172, 0x0173, 0x0174, 0x0175,
0x0176, 0x0177, 0x0179, 0x017a, 0x017b, 0x017c, 0x017f, 0x01fa,
0x01fb, 0x01fc, 0x01fd, 0x01fe, 0x01ff, 0x02c7, 0x02c9, 0x02d8,
0x02d9, 0x02da, 0x02db, 0x02dd, 0x0384, 0x0385, 0x0386, 0x0387,
0x0388, 0x0389, 0x038a, 0x038c, 0x038e, 0x038f, 0x0390, 0x03aa,
0x03ab, 0x03ac, 0x03ad, 0x03ae, 0x03af, 0x03b0, 0x03ca, 0x03cb,
0x03cc, 0x03cd, 0x03ce, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405,
0x0406, 0x0407, 0x0408, 0x0409, 0x040a, 0x040b, 0x040c, 0x040e,
0x040f, 0x0410, 0x0411, 0x0412, 0x0413, 0x0414, 0x0415, 0x0416,
0x0417, 0x0418, 0x0419, 0x041a, 0x041b, 0x041c, 0x041d, 0x041e,
0x041f, 0x0420, 0x0421, 0x0422, 0x0423, 0x0424, 0x0425, 0x0426,
0x0427, 0x0428, 0x0429, 0x042a, 0x042b, 0x042c, 0x042d, 0x042e,
0x042f, 0x0430, 0x0431, 0x0432, 0x0433, 0x0434, 0x0435, 0x0436,
0x0437, 0x0438, 0x0439, 0x043a, 0x043b, 0x043c, 0x043d, 0x043e,
0x043f, 0x0440, 0x0441, 0x0442, 0x0443, 0x0444, 0x0445, 0x0446,
0x0447, 0x0448, 0x0449, 0x044a, 0x044b, 0x044c, 0x044d, 0x044e,
0x044f, 0x0451, 0x0452, 0x0453, 0x0454, 0x0455, 0x0456, 0x0457,
0x0458, 0x0459, 0x045a, 0x045b, 0x045c, 0x045e, 0x045f, 0x0490,
0x0491, 0x1e80, 0x1e81, 0x1e82, 0x1e83, 0x1e84, 0x1e85, 0x1ef2,
0x1ef3, 0x2015, 0x2017, 0x201b, 0x20a3, 0x20a4, 0x2105, 0x2113,
0x2116, 0x2126, 0x212e, 0x215b, 0x215c, 0x215d, 0x215e, 0x2206,
0x2215, 0x25a1, 0x25aa, 0x25ab, 0x25ba, 0x25c4, 0x25cf, 0x25e6,
0xf001, 0xf002, 0xfb01, 0xfb02,

0x01ce, 0x01cd, 0x1ec7, 0x1ec6, 0x01d0, 0x01cf, 0x01d2, 0x01d1,
0x0303, 0x030c,

0x03d5, 0x2010, 0x25ef, 0x261c, 0x261e, 0xfb00, 0xfb03, 0xfb04,

0x03d2, 0x21b5,

0x23b7, 0x23b8, 0x23b9,
};

#define CHAR_X 15
#define CHAR_Y 30
#define NUM_X 64
#define NUM_Y 16

static char outbuf[NUM_X*NUM_Y*CHAR_X*CHAR_Y];

int min_xd = 666;
int min_yd = 666;
int max_xd = -666;
int max_yd = -666;

void laydown(FT_Face face, int table){
       FT_GlyphSlot g = face->glyph;
       fprintf(stderr, "0x%04x at 0x%03x %dx%d pitch %d @ %d,%d
advance %3.6f\n",charlist[table],table,g->bitmap.width,
g->bitmap.rows, g->bitmap.pitch, g->bitmap_left,g->bitmap_top,
g->advance.x/64.0);

       {
               int xd = (int)g->bitmap.width - (int)g->bitmap_left;
               int yd = (int)g->bitmap.rows  - (int)g->bitmap_top;
               if(xd>max_xd)
                       max_xd = xd;
               if(xd<min_xd)
                       min_xd = xd;
               if(yd>max_yd)
                       max_yd = yd;
               if(yd<min_yd)
                       min_yd = yd;
       }

       switch(g->bitmap.pitch){
       default:
               fprintf(stderr, "                strange pitch\n");
               return;
       case 0:
               return;
       case 2:
               ;
       }
       if(g->bitmap.width>CHAR_X){
               fprintf(stderr, "                dims %dx%d on entry
%d\n", g->bitmap.width, g->bitmap.rows, table);
               return;
       }
       if(!g->bitmap.width || !g->bitmap.rows)  // maybe a space
               return;
       int xstart = (table % NUM_X) * CHAR_X;
       int ystart = (table / NUM_X) * CHAR_Y;
       int y = g->bitmap.rows;
       if(y>CHAR_Y){
               fprintf(stderr, "                warning: dims %dx%d
on entry %d\n", g->bitmap.width, g->bitmap.rows, table);
               y = CHAR_Y;
       }
       int complained = 0;
       while(y--){
               int x = g->bitmap.width;
               while(x--){
                       int x2 = g->bitmap.width - x;
                       int pv =
((g->bitmap.buffer[x2/8+y*g->bitmap.pitch]>>(x2&7))&1)*255;
                       int ox = x/*-g->bitmap_left*/;
//                      int oy = y-g->bitmap_top+face->ascender/64;
                       int oy =
y-g->bitmap_top+(face->ascender+face->descender)/64;
                       if((unsigned)ox>=CHAR_X || (unsigned)oy>=CHAR_Y){
                               if(0 && !complained)
                                       fprintf(stderr,"0x%04x @ %d
writes %d,%d based on
%d,%d\n",charlist[table],table,ox,oy,g->bitmap_left,g->bitmap_top);
                               complained = 1;
                               continue;
                       }
                       outbuf[xstart+ox+(ystart+oy)*NUM_X*CHAR_X] = pv;
               }
       }
}

int main(int argc, char *argv[]){
       setlocale(LC_ALL,"en_US.utf8");

       memset(outbuf,0xb0,sizeof outbuf);

       FT_Library library;
       int error = FT_Init_FreeType( &library );
       if (error)
               return 2;
       FT_Face face;
//      error = FT_New_Face(library,
"/usr/share/fonts/truetype/freefont/FreeMono.ttf", 0, &face);
       error = FT_New_Face(library, argv[1], 0, &face);
       if (error)
               return 3;
       if(face->num_glyphs<94 || face->style_flags&FT_STYLE_FLAG_ITALIC)
               return 4;
       if(

((FT_FACE_FLAG_SCALABLE|/*FT_FACE_FLAG_FIXED_WIDTH|*/FT_FACE_FLAG_HORIZONTAL)&face->face_flags)
               !=

(FT_FACE_FLAG_SCALABLE|/*FT_FACE_FLAG_FIXED_WIDTH|*/FT_FACE_FLAG_HORIZONTAL)
       ){
               fprintf(stderr,"flags %08lx\n",face->face_flags);
               return 5;
       }

//      error = FT_Set_Char_Size(face,0,CHAR_Y*5/6,72,72);
       error = FT_Set_Char_Size(face,CHAR_X*64/2,CHAR_Y*64/2,72,72);
//      error = FT_Set_Pixel_Sizes(face,CHAR_X,CHAR_Y);
//      error = FT_Set_Pixel_Sizes(face,0,CHAR_Y*5/6);

       // call FT_Set_Transform here if desired

       int te = sizeof(charlist)/sizeof(charlist[0]);
       while(te--){
               int wcw = wcwidth(charlist[te]);
               if(wcw != 1){
                       fprintf(stderr,"0x%04x at slot %d is %d
wide\n",charlist[te],te,wcw);
                       continue;
               }
               // supposed to translate by this:   -ROUND(xMin),-ROUND(yMin)
               error =
FT_Load_Char(face,charlist[te],FT_LOAD_RENDER|FT_LOAD_MONOCHROME);
//              FT_GlyphSlot glyph = face->glyph;
               laydown(face,te);
       }
#if 0
//      glyph is type FT_GlyphSlot
//      glyph->bitmap is "a simple bitmap descriptor"
//      glyph->bitmap_left
//      glyph->bitmap_top

//      printf("P4 %d %d\n",glyph->bitmap.width,glyph->bitmap.rows);
       printf("P4 15 %d\n",glyph->bitmap.rows);

       int size = glyph->bitmap.pitch;
       if(size<0)
               size = -size;
       size *= glyph->bitmap.rows;

       fflush(stdout);
       write(STDOUT_FILENO,glyph->bitmap.buffer,size);
#endif
       printf("P5\n%u %u\n255\n", NUM_X*CHAR_X, NUM_Y*CHAR_Y);
       fwrite(outbuf, NUM_X*CHAR_X*NUM_Y*CHAR_Y, 1, stdout);

       fprintf(stderr,"xd is %d..%d and yd is
%d..%d\n",min_xd,max_xd,min_yd,max_yd);
       fprintf(stderr,"ascender %d descender %d height
%d\nmax_advance_width %d max_advance_height %d\nsize %d units/M %u\n",

face->ascender,face->descender,face->height,face->max_advance_width,face->max_advance_height,face->size,face->units_per_EM
       );
       fprintf(stderr,"bbox:  x %d..%d  y %d..%d  size %dx%d\n",
               face->bbox.xMin,
               face->bbox.xMax,
               face->bbox.yMin,
               face->bbox.yMax,
               face->bbox.xMax-face->bbox.xMin,
               face->bbox.yMax-face->bbox.yMin
       );
       fprintf(stderr,"bbox:  x %.2f..%.2f  y %.2f..%.2f  size %.2fx%.2f\n",
               face->bbox.xMin/64.0,
               face->bbox.xMax/64.0,
               face->bbox.yMin/64.0,
               face->bbox.yMax/64.0,
               face->bbox.xMax/64.0-face->bbox.xMin/64.0,
               face->bbox.yMax/64.0-face->bbox.yMin/64.0
       );

//      FT_Done_Face(...);
       return 0;
}




reply via email to

[Prev in Thread] Current Thread [Next in Thread]