mkfn: unify freetype and stb support
[fbpad_mkfn.git] / mkfn_ft.c
blob85e71781181f8597de107f5dcc1851d95ae1aa31
1 #include <ctype.h>
2 #include <unistd.h>
3 #include <string.h>
5 #include <ft2build.h>
6 #include FT_FREETYPE_H
7 #include FT_BITMAP_H
8 #include "mkfn.h"
10 #define MIN(a, b) ((a) < (b) ? (a) : (b))
11 #define MAX(a, b) ((a) > (b) ? (a) : (b))
12 #define LIMIT(n, a, b) ((n) < (a) ? (a) : ((n) > (b) ? (b) : (n)))
14 static FT_Library library;
15 static FT_Face fn[NFONTS];
16 static int fn_desc[NFONTS];
17 static int fn_bold[NFONTS];
18 static int fn_hint[NFONTS];
19 static int fn_sc[NFONTS];
20 static int fn_sr[NFONTS];
21 static int fn_cnt;
23 static int glyphload(FT_Face face, int c, int autohint)
25 int flags = FT_LOAD_RENDER;
26 if (autohint)
27 flags |= FT_LOAD_FORCE_AUTOHINT;
28 return !FT_Get_Char_Index(face, c) ||
29 FT_Load_Char(face, c, flags);
32 static int facedescender(FT_Face face)
34 char *s = "gy_pj/\\|Q";
35 int ret = 0;
36 for (; *s; s++)
37 if (!glyphload(face, *s, 0))
38 ret = MAX(ret, face->glyph->bitmap.rows -
39 face->glyph->bitmap_top);
40 return ret;
43 int mkfn_font(char *path, char *spec)
45 FT_Face *face = &fn[fn_cnt];
46 int hdpi = 196;
47 int vdpi = 196;
48 float size = 10;
49 if (FT_New_Face(library, path, 0, face))
50 return 1;
51 while (spec && *spec) {
52 if (spec[0] == 'a')
53 fn_hint[fn_cnt] = atoi(spec + 1);
54 if (spec[0] == 'b')
55 fn_bold[fn_cnt] = atoi(spec + 1);
56 if (spec[0] == 'v')
57 vdpi = atoi(spec + 1);
58 if (spec[0] == 'c')
59 fn_sc[fn_cnt] = atof(spec + 1);
60 if (spec[0] == 'r')
61 fn_sr[fn_cnt] = atof(spec + 1);
62 if (spec[0] == 'h')
63 hdpi = atoi(spec + 1);
64 if (spec[0] == 's')
65 size = atof(spec + 1);
66 if (isdigit((unsigned char) spec[0]))
67 size = atof(spec);
68 spec++;
69 while (*spec && strchr("0123456789.-+", (unsigned char) *spec))
70 spec++;
72 if (FT_Set_Char_Size(*face, 0, size * 64, hdpi, vdpi))
73 return 1;
74 fn_desc[fn_cnt] = facedescender(*face);
75 fn_cnt++;
76 return 0;
79 static void fn_embolden(unsigned char *bits, int rows, int cols)
81 int i, j, k;
82 int n = 2;
83 for (i = 0; i < rows; i++) {
84 for (j = cols - n; j >= 0; j--) {
85 int idx = i * cols + j;
86 int val = 0;
87 for (k = 0; k < n; k++)
88 if (bits[idx + k] > val)
89 val = bits[idx + k];
90 bits[idx + n - 1] = val;
95 int mkfn_bitmap(char *dst, int c, int rows, int cols)
97 unsigned char *bits = (void *) dst;
98 int sr, sc; /* the starting and the number of rows in bits */
99 int nr, nc; /* the starting and the number of cols in bits */
100 int br; /* the starting column of glyph bitmap */
101 int bc; /* the starting row of glyph bitmap */
102 int bw; /* the number of columns in glyph bitmap */
103 int i, j;
104 int bold;
105 unsigned char *src;
106 FT_Face face = NULL;
107 for (i = 0; i < fn_cnt; i++) {
108 if (!glyphload(fn[i], c & ~DWCHAR, fn_hint[i])) {
109 face = fn[i];
110 bold = fn_bold[i];
111 break;
114 if (!face)
115 return 1;
116 if (!dst)
117 return 0;
118 bc = c & DWCHAR ? cols : 0;
119 nc = LIMIT(face->glyph->bitmap.width - bc, 0, cols);
120 sc = LIMIT(face->glyph->bitmap_left - bc + fn_sc[i], 0, cols - nc);
121 sr = rows + fn_sr[i] - fn_desc[i] - face->glyph->bitmap_top;
122 br = MAX(0, -sr);
123 sr = LIMIT(sr, 0, rows);
124 nr = MIN(rows - sr, face->glyph->bitmap.rows - br);
125 memset(bits, 0, rows * cols);
126 src = face->glyph->bitmap.buffer;
127 bw = face->glyph->bitmap.pitch;
128 if (face->glyph->bitmap.pixel_mode == FT_PIXEL_MODE_MONO) {
129 for (i = 0; i < nr; i++) {
130 for (j = 0; j < nc; j++) {
131 int num = (br + i) * bw * 8 + bc + j;
132 int val = src[num / 8] & (1 << (7 - num % 8));
133 bits[(i + sr) * cols + j + sc] = val ? 255 : 0;
136 return 0;
138 for (i = 0; i < nr; i++)
139 memcpy(&bits[(sr + i) * cols + sc], src + (br + i) * bw + bc, nc);
140 if (bold)
141 fn_embolden(bits, rows, cols);
142 return 0;
145 void mkfn_dim(int *r, int *c)
147 *r = fn[0]->size->metrics.height >> 6;
148 *c = fn[0]->size->metrics.max_advance >> 6;
151 void mkfn_init(void)
153 FT_Init_FreeType(&library);
156 void mkfn_free(void)
158 int i;
159 for (i = 0; i < fn_cnt; i++)
160 FT_Done_Face(fn[i]);
161 FT_Done_FreeType(library);