1 #include <stdlib.h>
2 #include <string.h>
3 #include <stdio.h>
4 #include <stdarg.h>
5 #include <limits.h>
6 #include <zlib.h>
7 #include <ft2build.h>
8 #include FT_FREETYPE_H
9 #include FT_STROKER_H
10 #include FT_GLYPH_H
11
12 typedef unsigned char uchar;
13 typedef unsigned short ushort;
14 typedef unsigned int uint;
15
imin(int a,int b)16 int imin(int a, int b) { return a < b ? a : b; }
imax(int a,int b)17 int imax(int a, int b) { return a > b ? a : b; }
18
fatal(const char * fmt,...)19 void fatal(const char *fmt, ...)
20 {
21 va_list v;
22 va_start(v, fmt);
23 vfprintf(stderr, fmt, v);
24 va_end(v);
25 fputc('\n', stderr);
26
27 exit(EXIT_FAILURE);
28 }
29
bigswap(uint n)30 uint bigswap(uint n)
31 {
32 const int islittleendian = 1;
33 return *(const uchar *)&islittleendian ? (n<<24) | (n>>24) | ((n>>8)&0xFF00) | ((n<<8)&0xFF0000) : n;
34 }
35
writebig(FILE * f,uint n)36 size_t writebig(FILE *f, uint n)
37 {
38 n = bigswap(n);
39 return fwrite(&n, 1, sizeof(n), f);
40 }
41
writepngchunk(FILE * f,const char * type,uchar * data,uint len)42 void writepngchunk(FILE *f, const char *type, uchar *data, uint len)
43 {
44 uint crc;
45 writebig(f, len);
46 fwrite(type, 1, 4, f);
47 fwrite(data, 1, len, f);
48
49 crc = crc32(0, Z_NULL, 0);
50 crc = crc32(crc, (const Bytef *)type, 4);
51 if(data) crc = crc32(crc, data, len);
52 writebig(f, crc);
53 }
54
55 struct pngihdr
56 {
57 uint width, height;
58 uchar bitdepth, colortype, compress, filter, interlace;
59 };
60
savepng(const char * filename,uchar * data,int w,int h,int bpp,int flip)61 void savepng(const char *filename, uchar *data, int w, int h, int bpp, int flip)
62 {
63 const uchar signature[] = { 137, 80, 78, 71, 13, 10, 26, 10 };
64 struct pngihdr ihdr;
65 FILE *f;
66 long idat;
67 uint len, crc;
68 z_stream z;
69 uchar buf[1<<12];
70 int i, j;
71
72 memset(&ihdr, 0, sizeof(ihdr));
73 ihdr.width = bigswap(w);
74 ihdr.height = bigswap(h);
75 ihdr.bitdepth = 8;
76 switch(bpp)
77 {
78 case 1: ihdr.colortype = 0; break;
79 case 2: ihdr.colortype = 4; break;
80 case 3: ihdr.colortype = 2; break;
81 case 4: ihdr.colortype = 6; break;
82 default: fatal("Cube2font: invalid PNG bpp"); return;
83 }
84 f = fopen(filename, "wb");
85 if(!f) { fatal("Cube2font: could not write to %s", filename); return; }
86
87 fwrite(signature, 1, sizeof(signature), f);
88
89 writepngchunk(f, "IHDR", (uchar *)&ihdr, 13);
90
91 idat = ftell(f);
92 len = 0;
93 fwrite("\0\0\0\0IDAT", 1, 8, f);
94 crc = crc32(0, Z_NULL, 0);
95 crc = crc32(crc, (const Bytef *)"IDAT", 4);
96
97 z.zalloc = NULL;
98 z.zfree = NULL;
99 z.opaque = NULL;
100
101 if(deflateInit(&z, Z_BEST_COMPRESSION) != Z_OK)
102 goto error;
103
104 z.next_out = (Bytef *)buf;
105 z.avail_out = sizeof(buf);
106
107 for(i = 0; i < h; i++)
108 {
109 uchar filter = 0;
110 for(j = 0; j < 2; j++)
111 {
112 z.next_in = j ? (Bytef *)data + (flip ? h-i-1 : i)*w*bpp : (Bytef *)&filter;
113 z.avail_in = j ? w*bpp : 1;
114 while(z.avail_in > 0)
115 {
116 if(deflate(&z, Z_NO_FLUSH) != Z_OK) goto cleanuperror;
117 #define FLUSHZ do { \
118 int flush = sizeof(buf) - z.avail_out; \
119 crc = crc32(crc, buf, flush); \
120 len += flush; \
121 fwrite(buf, 1, flush, f); \
122 z.next_out = (Bytef *)buf; \
123 z.avail_out = sizeof(buf); \
124 } while(0)
125 FLUSHZ;
126 }
127 }
128 }
129
130 for(;;)
131 {
132 int err = deflate(&z, Z_FINISH);
133 if(err != Z_OK && err != Z_STREAM_END) goto cleanuperror;
134 FLUSHZ;
135 if(err == Z_STREAM_END) break;
136 }
137
138 deflateEnd(&z);
139
140 fseek(f, idat, SEEK_SET);
141 writebig(f, len);
142 fseek(f, 0, SEEK_END);
143 writebig(f, crc);
144
145 writepngchunk(f, "IEND", NULL, 0);
146
147 fclose(f);
148 return;
149
150 cleanuperror:
151 deflateEnd(&z);
152
153 error:
154 fclose(f);
155
156 fatal("Cube2font: failed saving PNG to %s", filename);
157 }
158
159 enum
160 {
161 CT_PRINT = 1<<0,
162 CT_SPACE = 1<<1,
163 CT_DIGIT = 1<<2,
164 CT_ALPHA = 1<<3,
165 CT_LOWER = 1<<4,
166 CT_UPPER = 1<<5,
167 CT_UNICODE = 1<<6
168 };
169 #define CUBECTYPE(s, p, d, a, A, u, U) \
170 0, U, U, U, U, U, U, U, U, s, s, s, s, s, U, U, \
171 U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, \
172 s, p, p, p, p, p, p, p, p, p, p, p, p, p, p, p, \
173 d, d, d, d, d, d, d, d, d, d, p, p, p, p, p, p, \
174 p, A, A, A, A, A, A, A, A, A, A, A, A, A, A, A, \
175 A, A, A, A, A, A, A, A, A, A, A, p, p, p, p, p, \
176 p, a, a, a, a, a, a, a, a, a, a, a, a, a, a, a, \
177 a, a, a, a, a, a, a, a, a, a, a, p, p, p, p, U, \
178 U, u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, \
179 u, u, u, u, u, u, u, u, u, u, u, u, u, u, u, U, \
180 u, U, u, U, u, U, u, U, u, U, u, U, u, U, u, U, \
181 u, U, u, U, u, U, u, U, u, U, u, U, u, U, u, U, \
182 u, U, u, U, u, U, u, U, U, u, U, u, U, u, U, U, \
183 U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, U, \
184 U, U, U, U, u, u, u, u, u, u, u, u, u, u, u, u, \
185 u, u, u, u, u, u, u, u, u, u, u, u, u, u, U, u
186 const uchar cubectype[256] =
187 {
188 CUBECTYPE(CT_SPACE,
189 CT_PRINT,
190 CT_PRINT|CT_DIGIT,
191 CT_PRINT|CT_ALPHA|CT_LOWER,
192 CT_PRINT|CT_ALPHA|CT_UPPER,
193 CT_PRINT|CT_UNICODE|CT_ALPHA|CT_LOWER,
194 CT_PRINT|CT_UNICODE|CT_ALPHA|CT_UPPER)
195 };
iscubeprint(uchar c)196 int iscubeprint(uchar c) { return cubectype[c]&CT_PRINT; }
iscubespace(uchar c)197 int iscubespace(uchar c) { return cubectype[c]&CT_SPACE; }
iscubealpha(uchar c)198 int iscubealpha(uchar c) { return cubectype[c]&CT_ALPHA; }
iscubealnum(uchar c)199 int iscubealnum(uchar c) { return cubectype[c]&(CT_ALPHA|CT_DIGIT); }
iscubelower(uchar c)200 int iscubelower(uchar c) { return cubectype[c]&CT_LOWER; }
iscubeupper(uchar c)201 int iscubeupper(uchar c) { return cubectype[c]&CT_UPPER; }
202 const int cube2unichars[256] =
203 {
204 0, 192, 193, 194, 195, 196, 197, 198, 199, 9, 10, 11, 12, 13, 200, 201,
205 202, 203, 204, 205, 206, 207, 209, 210, 211, 212, 213, 214, 216, 217, 218, 219,
206 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47,
207 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63,
208 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
209 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95,
210 96, 97, 98, 99, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111,
211 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123, 124, 125, 126, 220,
212 221, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237,
213 238, 239, 241, 242, 243, 244, 245, 246, 248, 249, 250, 251, 252, 253, 255, 0x104,
214 0x105, 0x106, 0x107, 0x10C, 0x10D, 0x10E, 0x10F, 0x118, 0x119, 0x11A, 0x11B, 0x11E, 0x11F, 0x130, 0x131, 0x141,
215 0x142, 0x143, 0x144, 0x147, 0x148, 0x150, 0x151, 0x152, 0x153, 0x158, 0x159, 0x15A, 0x15B, 0x15E, 0x15F, 0x160,
216 0x161, 0x164, 0x165, 0x16E, 0x16F, 0x170, 0x171, 0x178, 0x179, 0x17A, 0x17B, 0x17C, 0x17D, 0x17E, 0x404, 0x411,
217 0x413, 0x414, 0x416, 0x417, 0x418, 0x419, 0x41B, 0x41F, 0x423, 0x424, 0x426, 0x427, 0x428, 0x429, 0x42A, 0x42B,
218 0x42C, 0x42D, 0x42E, 0x42F, 0x431, 0x432, 0x433, 0x434, 0x436, 0x437, 0x438, 0x439, 0x43A, 0x43B, 0x43C, 0x43D,
219 0x43F, 0x442, 0x444, 0x446, 0x447, 0x448, 0x449, 0x44A, 0x44B, 0x44C, 0x44D, 0x44E, 0x44F, 0x454, 0x490, 0x491
220 };
cube2uni(uchar c)221 int cube2uni(uchar c)
222 {
223 return cube2unichars[c];
224 }
225
encodeutf8(int uni)226 const char *encodeutf8(int uni)
227 {
228 static char buf[7];
229 char *dst = buf;
230 if(uni <= 0x7F) { *dst++ = uni; goto uni1; }
231 else if(uni <= 0x7FF) { *dst++ = 0xC0 | (uni>>6); goto uni2; }
232 else if(uni <= 0xFFFF) { *dst++ = 0xE0 | (uni>>12); goto uni3; }
233 else if(uni <= 0x1FFFFF) { *dst++ = 0xF0 | (uni>>18); goto uni4; }
234 else if(uni <= 0x3FFFFFF) { *dst++ = 0xF8 | (uni>>24); goto uni5; }
235 else if(uni <= 0x7FFFFFFF) { *dst++ = 0xFC | (uni>>30); goto uni6; }
236 else goto uni1;
237 uni6: *dst++ = 0x80 | ((uni>>24)&0x3F);
238 uni5: *dst++ = 0x80 | ((uni>>18)&0x3F);
239 uni4: *dst++ = 0x80 | ((uni>>12)&0x3F);
240 uni3: *dst++ = 0x80 | ((uni>>6)&0x3F);
241 uni2: *dst++ = 0x80 | (uni&0x3F);
242 uni1: *dst++ = '\0';
243 return buf;
244 }
245
246 struct fontchar { int code, uni, tex, x, y, w, h, offx, offy, offset, advance; FT_BitmapGlyph color, alpha; };
247
248 const char *texdir = "";
249
texfilename(const char * name,int texnum)250 const char *texfilename(const char *name, int texnum)
251 {
252 static char file[256];
253 snprintf(file, sizeof(file), "%s%d.png", name, texnum);
254 return file;
255 }
256
texname(const char * name,int texnum)257 const char *texname(const char *name, int texnum)
258 {
259 static char file[512];
260 snprintf(file, sizeof(file), "<grey>%s%s", texdir, texfilename(name, texnum));
261 return file;
262 }
263
writetexs(const char * name,struct fontchar * chars,int numchars,int numtexs,int tw,int th)264 void writetexs(const char *name, struct fontchar *chars, int numchars, int numtexs, int tw, int th)
265 {
266 int tex;
267 uchar *pixels = (uchar *)malloc(tw*th*2);
268 if(!pixels) fatal("Cube2font: failed allocating textures");
269 for(tex = 0; tex < numtexs; tex++)
270 {
271 const char *file = texfilename(name, tex);
272 int texchars = 0, i;
273 uchar *dst, *src;
274 memset(pixels, 0, tw*th*2);
275 for(i = 0; i < numchars; i++)
276 {
277 struct fontchar *c = &chars[i];
278 uint x, y;
279 if(c->tex != tex) continue;
280 texchars++;
281 dst = &pixels[2*((c->y + c->offy - c->color->top)*tw + c->x + c->color->left - c->offx)];
282 src = (uchar *)c->color->bitmap.buffer;
283 for(y = 0; y < c->color->bitmap.rows; y++)
284 {
285 for(x = 0; x < c->color->bitmap.width; x++)
286 dst[2*x] = src[x];
287 src += c->color->bitmap.pitch;
288 dst += 2*tw;
289 }
290 dst = &pixels[2*((c->y + c->offy - c->alpha->top)*tw + c->x + c->alpha->left - c->offx)];
291 src = (uchar *)c->alpha->bitmap.buffer;
292 for(y = 0; y < c->alpha->bitmap.rows; y++)
293 {
294 for(x = 0; x < c->alpha->bitmap.width; x++)
295 dst[2*x+1] = src[x];
296 src += c->alpha->bitmap.pitch;
297 dst += 2*tw;
298 }
299 }
300 printf("cube2font: writing %d chars to %s\n", texchars, file);
301 savepng(file, pixels, tw, th, 2, 0);
302 }
303 free(pixels);
304 }
305
writecfg(const char * name,struct fontchar * chars,int numchars,int x1,int y1,int x2,int y2,int sw,int sh,int argc,char ** argv)306 void writecfg(const char *name, struct fontchar *chars, int numchars, int x1, int y1, int x2, int y2, int sw, int sh, int argc, char **argv)
307 {
308 FILE *f;
309 char file[256];
310 int i, lastcode = 0, lasttex = 0;
311 snprintf(file, sizeof(file), "%s.cfg", name);
312 f = fopen(file, "w");
313 if(!f) fatal("Cube2font: failed writing %s", file);
314 printf("cube2font: writing %d chars to %s\n", numchars, file);
315 fprintf(f, "//");
316 for(i = 1; i < argc; i++)
317 fprintf(f, " %s", argv[i]);
318 fprintf(f, "\n");
319 fprintf(f, "font \"%s\" \"%s\" %d %d\n", name, texname(name, 0), sw, sh);
320 for(i = 0; i < numchars; i++)
321 {
322 struct fontchar *c = &chars[i];
323 if(!lastcode && lastcode < c->code)
324 {
325 fprintf(f, "fontoffset \"%s\"\n", encodeutf8(c->uni));
326 lastcode = c->code;
327 }
328 else if(lastcode < c->code)
329 {
330 if(lastcode + 1 == c->code)
331 fprintf(f, "fontskip // %d\n", lastcode);
332 else
333 fprintf(f, "fontskip %d // %d .. %d\n", c->code - lastcode, lastcode, c->code-1);
334 lastcode = c->code;
335 }
336 if(lasttex != c->tex)
337 {
338 fprintf(f, "\nfonttex \"%s\"\n", texname(name, c->tex));
339 lasttex = c->tex;
340 }
341 if(c->code != c->uni)
342 fprintf(f, "fontchar %d %d %d %d %d %d %d // %s (%d -> 0x%X)\n", c->x, c->y, c->w, c->h, c->offx+c->offset, y2-c->offy, c->advance, encodeutf8(c->uni), c->code, c->uni);
343 else
344 fprintf(f, "fontchar %d %d %d %d %d %d %d // %s (%d)\n", c->x, c->y, c->w, c->h, c->offx+c->offset, y2-c->offy, c->advance, encodeutf8(c->uni), c->code);
345 lastcode++;
346 }
347 fclose(f);
348 }
349
groupchar(int c)350 int groupchar(int c)
351 {
352 switch(c)
353 {
354 case 0x152: case 0x153: case 0x178: return 1;
355 }
356 if(c < 127 || c >= 0x2000) return 0;
357 if(c < 0x100) return 1;
358 if(c < 0x400) return 2;
359 return 3;
360 }
361
sortchars(const void * x,const void * y)362 int sortchars(const void *x, const void *y)
363 {
364 const struct fontchar *xc = *(const struct fontchar **)x, *yc = *(const struct fontchar **)y;
365 int xg = groupchar(xc->uni), yg = groupchar(yc->uni);
366 if(xg < yg) return -1;
367 if(xg > yg) return 1;
368 if(xc->h != yc->h) return yc->h - xc->h;
369 if(xc->w != yc->w) return yc->w - xc->w;
370 return yc->uni - xc->uni;
371 }
372
scorechar(struct fontchar * f,int pad,int tw,int th,int rw,int rh,int ry)373 int scorechar(struct fontchar *f, int pad, int tw, int th, int rw, int rh, int ry)
374 {
375 int score = 0;
376 if(rw + f->w > tw) { ry += rh + pad; score = 1; }
377 if(ry + f->h > th) score = 2;
378 return score;
379 }
380
main(int argc,char ** argv)381 int main(int argc, char **argv)
382 {
383 FT_Library l;
384 FT_Face f;
385 FT_Stroker s, s2;
386 int i, pad, offset, advance, w, h, tw, th, c, trial = -2, rw = 0, rh = 0, ry = 0, x1 = INT_MAX, x2 = INT_MIN, y1 = INT_MAX, y2 = INT_MIN, w2 = 0, h2 = 0, sw = 0, sh = 0;
387 float outborder = 0, inborder = 0;
388 struct fontchar chars[256];
389 struct fontchar *order[256];
390 int numchars = 0, numtex = 0;
391 if(argc < 11)
392 fatal("Usage: cube2font infile outfile outborder[:inborder] pad offset advance charwidth charheight texwidth texheight [spacewidth spaceheight texdir]");
393 sscanf(argv[3], "%f:%f", &outborder, &inborder);
394 pad = atoi(argv[4]);
395 offset = atoi(argv[5]);
396 advance = atoi(argv[6]);
397 w = atoi(argv[7]);
398 h = atoi(argv[8]);
399 tw = atoi(argv[9]);
400 th = atoi(argv[10]);
401 if(argc > 11) sw = atoi(argv[11]);
402 if(argc > 12) sh = atoi(argv[12]);
403 if(argc > 13) texdir = argv[13];
404 if(FT_Init_FreeType(&l))
405 fatal("Cube2font: failed initing freetype");
406 if(FT_New_Face(l, argv[1], 0, &f) ||
407 FT_Set_Charmap(f, f->charmaps[0]) ||
408 FT_Set_Pixel_Sizes(f, w, h) ||
409 FT_Stroker_New(l, &s) ||
410 FT_Stroker_New(l, &s2))
411 fatal("Cube2font: failed loading font %s", argv[1]);
412 if(outborder > 0) FT_Stroker_Set(s, (FT_Fixed)(outborder * 64), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
413 if(inborder > 0) FT_Stroker_Set(s2, (FT_Fixed)(inborder * 64), FT_STROKER_LINECAP_ROUND, FT_STROKER_LINEJOIN_ROUND, 0);
414 for(c = 0; c < 256; c++) if(iscubeprint(c))
415 {
416 FT_Glyph p, p2;
417 FT_BitmapGlyph b, b2;
418 struct fontchar *dst = &chars[numchars];
419 dst->code = c;
420 dst->uni = cube2uni(c);
421 if(FT_Load_Char(f, dst->uni, FT_LOAD_DEFAULT))
422 fatal("Cube2font: failed loading character %s", encodeutf8(dst->uni));
423 FT_Get_Glyph(f->glyph, &p);
424 p2 = p;
425 if(outborder > 0) FT_Glyph_StrokeBorder(&p, s, 0, 0);
426 if(inborder > 0) FT_Glyph_StrokeBorder(&p2, s2, 1, 0);
427 FT_Glyph_To_Bitmap(&p, FT_RENDER_MODE_NORMAL, 0, 1);
428 if(inborder > 0 || outborder > 0) FT_Glyph_To_Bitmap(&p2, FT_RENDER_MODE_NORMAL, 0, 1);
429 else p2 = p;
430 b = (FT_BitmapGlyph)p;
431 b2 = (FT_BitmapGlyph)p2;
432 dst->tex = -1;
433 dst->x = INT_MIN;
434 dst->y = INT_MIN;
435 dst->offx = imin(b->left, b2->left);
436 dst->offy = imax(b->top, b2->top);
437 dst->offset = offset;
438 dst->advance = offset + ((p->advance.x+0xFFFF)>>16) + advance;
439 dst->w = imax(b->left + b->bitmap.width, b2->left + b2->bitmap.width) - dst->offx;
440 dst->h = dst->offy - imin(b->top - b->bitmap.rows, b2->top - b2->bitmap.rows);
441 dst->alpha = b;
442 dst->color = b2;
443 order[numchars++] = dst;
444 }
445 qsort(order, numchars, sizeof(order[0]), sortchars);
446 for(i = 0; i < numchars;)
447 {
448 struct fontchar *dst;
449 int j, k, trial0, prevscore, dstscore, fitscore;
450 for(trial0 = trial, prevscore = -1; (trial -= 2) >= trial0-512;)
451 {
452 int g, fw = rw, fh = rh, fy = ry, curscore = 0, reused = 0;
453 for(j = i; j < numchars; j++)
454 {
455 dst = order[j];
456 if(dst->tex >= 0 || dst->tex <= trial) continue;
457 g = groupchar(dst->uni);
458 dstscore = scorechar(dst, pad, tw, th, fw, fh, fy);
459 for(k = j; k < numchars; k++)
460 {
461 struct fontchar *fit = order[k];
462 if(fit->tex >= 0 || fit->tex <= trial) continue;
463 if(fit->tex >= trial0 && groupchar(fit->uni) != g) break;
464 fitscore = scorechar(fit, pad, tw, th, fw, fh, fy);
465 if(fitscore < dstscore || (fitscore == dstscore && fit->h > dst->h))
466 {
467 dst = fit;
468 dstscore = fitscore;
469 }
470 }
471 if(fw + dst->w > tw)
472 {
473 fy += fh + pad;
474 fw = fh = 0;
475 }
476 if(fy + dst->h > th)
477 {
478 fy = fw = fh = 0;
479 if(curscore > 0) break;
480 }
481 if(dst->tex >= trial+1 && dst->tex <= trial+2) { dst->tex = trial; reused++; }
482 else dst->tex = trial;
483 fw += dst->w + pad;
484 fh = imax(fh, dst->h);
485 if(dst != order[j]) --j;
486 curscore++;
487 }
488 if(reused < prevscore || curscore <= prevscore) break;
489 prevscore = curscore;
490 }
491 for(; i < numchars; i++)
492 {
493 dst = order[i];
494 if(dst->tex >= 0) continue;
495 dstscore = scorechar(dst, pad, tw, th, rw, rh, ry);
496 for(j = i; j < numchars; j++)
497 {
498 struct fontchar *fit = order[j];
499 if(fit->tex < trial || fit->tex > trial+2) continue;
500 fitscore = scorechar(fit, pad, tw, th, rw, rh, ry);
501 if(fitscore < dstscore || (fitscore == dstscore && fit->h > dst->h))
502 {
503 dst = fit;
504 dstscore = fitscore;
505 }
506 }
507 if(dst->tex < trial || dst->tex > trial+2) break;
508 if(rw + dst->w > tw)
509 {
510 ry += rh + pad;
511 rw = rh = 0;
512 }
513 if(ry + dst->h > th)
514 {
515 ry = rw = rh = 0;
516 numtex++;
517 }
518 dst->tex = numtex;
519 dst->x = rw;
520 dst->y = ry;
521 rw += dst->w + pad;
522 rh = imax(rh, dst->h);
523 y1 = imin(y1, dst->offy - dst->h);
524 y2 = imax(y2, dst->offy);
525 x1 = imin(x1, dst->offx);
526 x2 = imax(x2, dst->offx + dst->w);
527 w2 = imax(w2, dst->w);
528 h2 = imax(h2, dst->h);
529 if(dst != order[i]) --i;
530 }
531 }
532 if(rh > 0) numtex++;
533 #if 0
534 if(sw <= 0)
535 {
536 if(FT_Load_Char(f, ' ', FT_LOAD_DEFAULT))
537 fatal("Cube2font: failed loading space character");
538 sw = (f->glyph->advance.x+0x3F)>>6;
539 }
540 #endif
541 if(sh <= 0) sh = y2 - y1;
542 if(sw <= 0) sw = sh/3;
543 writetexs(argv[2], chars, numchars, numtex, tw, th);
544 writecfg(argv[2], chars, numchars, x1, y1, x2, y2, sw, sh, argc, argv);
545 for(i = 0; i < numchars; i++)
546 {
547 if(chars[i].alpha != chars[i].color) FT_Done_Glyph((FT_Glyph)chars[i].alpha);
548 FT_Done_Glyph((FT_Glyph)chars[i].color);
549 }
550 FT_Stroker_Done(s);
551 FT_Stroker_Done(s2);
552 FT_Done_FreeType(l);
553 printf("cube2font: (%d, %d) .. (%d, %d) = (%d, %d) / (%d, %d), %d texs\n", x1, y1, x2, y2, x2 - x1, y2 - y1, w2, h2, numtex);
554 return EXIT_SUCCESS;
555 }
556
557