graphics

experiments with opengl3.2/ogles3.3 on linux and win7
git clone http://frotz.net/git/graphics.git
Log | Files | Refs

mkfont.cc (4813B)


      1 /* Copyright 2013 Brian Swetland <swetland@frotz.net>
      2  *
      3  * Licensed under the Apache License, Version 2.0 (the "License");
      4  * you may not use this file except in compliance with the License.
      5  * You may obtain a copy of the License at
      6  *
      7  *     http://www.apache.org/licenses/LICENSE-2.0
      8  *
      9  * Unless required by applicable law or agreed to in writing, software
     10  * distributed under the License is distributed on an "AS IS" BASIS,
     11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     12  * See the License for the specific language governing permissions and
     13  * limitations under the License.
     14  */
     15 
     16 #include <ft2build.h>
     17 #include FT_FREETYPE_H
     18 #include FT_OUTLINE_H
     19 #include FT_BITMAP_H
     20 #include FT_GLYPH_H
     21 
     22 #include <util.h>
     23 #include <io.h>
     24 
     25 #include <texturefont.h>
     26 
     27 #include <algorithm>
     28 
     29 /* from internal header... */
     30 #define FT_PIX_FLOOR(x) ((x) & ~63)
     31 #define FT_PIX_CEIL(x) FT_PIX_FLOOR((x) + 63)
     32 
     33 struct Glyph {
     34 	unsigned c;
     35 	unsigned h;
     36 };
     37 
     38 void get_bbox(FT_Outline *outline, FT_BBox *bb) {
     39 	FT_Outline_Get_CBox(outline, bb);
     40 	/* grid fit */
     41 	bb->xMin = FT_PIX_FLOOR(bb->xMin);
     42 	bb->yMin = FT_PIX_FLOOR(bb->yMin);
     43 	bb->xMax = FT_PIX_CEIL(bb->xMax);
     44 	bb->yMax = FT_PIX_CEIL(bb->yMax);
     45 	/* convert from 26.6 to pixel coords */
     46 	bb->xMin >>= 6;
     47 	bb->yMin >>= 6;
     48 	bb->xMax >>= 6;
     49 	bb->yMax >>= 6;
     50 }
     51 
     52 bool compare_glyphs(Glyph const &left, Glyph const &right) {
     53 	return left.h < right.h;
     54 }
     55 
     56 #define FIRST 0x20
     57 #define LAST 0x7F
     58 #define MAXDIM 1024
     59 
     60 int main(int argc, char **argv) {
     61 	FT_Library ftl;
     62 	FT_Face face;
     63 	FT_Bitmap *bitmap;
     64 	unsigned i, n;
     65 	void *x;
     66 	
     67 	FT_BBox bb;
     68 	FT_Bitmap bm;
     69 	unsigned char data[MAXDIM * MAXDIM];
     70 	int w, h, tx, ty, nx, ny, rh, max;
     71 	CharInfo info[128];
     72 	Glyph list[LAST];
     73 	char tmp[256];
     74 
     75 	io_ignore_asset_paths();
     76 
     77 	if (argc < 4)
     78 		return error("usage: mkfont <truetypefont> <height> <outputname>");
     79 
     80 	if (FT_Init_FreeType(&ftl))
     81 		return -1;
     82 
     83 	x = load_file(argv[1], &n);
     84 	if (x == 0)
     85 		return -1;
     86 
     87 	if (FT_New_Memory_Face(ftl, (FT_Byte*) x, n, 0, &face))
     88 		return error("cannot load font '%s'", argv[1]);
     89 
     90 	if (FT_Set_Pixel_Sizes(face, 0, atoi(argv[2])))
     91 		return error("cannot set font size to %s\n", argv[2]);
     92 
     93 	for (n = FIRST; n < LAST; n++) {
     94 		if (FT_Load_Char(face, n, FT_LOAD_NO_BITMAP)) {
     95 			error("missing glyph for %d\n", n);
     96 			continue;
     97 		}
     98 		get_bbox(&face->glyph->outline, &bb);
     99 		list[n - FIRST].c = n;
    100 		list[n - FIRST].h = bb.yMax - bb.yMin;
    101 		
    102 	}
    103 	std::sort(list, list + LAST - FIRST, compare_glyphs);
    104 
    105 	max = 128;
    106 retry:
    107 	memset(data, 0, sizeof(data));
    108 	memset(info, 0, sizeof(info));
    109 
    110 	bm.rows = max;
    111 	bm.width = max;
    112 	bm.pitch = max;
    113 	bm.buffer = data;
    114 	bm.num_grays = 256;
    115 	bm.pixel_mode = FT_PIXEL_MODE_GRAY;
    116 	bm.palette_mode = 0;
    117 	bm.palette = NULL;
    118 
    119 	nx = ny = 1;
    120 	rh = 0;
    121 
    122 	int ascent, descent;
    123 	int ascent_max = 0;
    124 	int descent_max = 0;
    125 	int height_max = 0;
    126 
    127 	printf("%dx%d texture...\n", max, max);
    128 	for (i = 0; i < (LAST - FIRST); i++) {
    129 		n = list[i].c;
    130 		if (FT_Load_Char(face, n, FT_LOAD_NO_BITMAP)) {
    131 			error("missing glyph for %d\n", n);
    132 			continue;
    133 		}
    134 		get_bbox(&face->glyph->outline, &bb);
    135 		w = bb.xMax - bb.xMin + 1;
    136 		h = bb.yMax - bb.yMin + 1;
    137 		tx = -bb.xMin;
    138 		ty = -bb.yMin;
    139 		if ((nx + w) >= max) {
    140 			nx = 1;
    141 			ny += rh + 1;
    142 			rh = 0;
    143 		}
    144 		if ((ny + h) >= max) {
    145 			max *= 2;
    146 			if (max > MAXDIM) {
    147 				fprintf(stderr,"oops! out of space\n");
    148 				return -1;
    149 			}
    150 			goto retry;
    151 		}
    152 		info[n].x = nx;
    153 		info[n].y = max - ny - h + 1;
    154 		info[n].w = w - 1;
    155 		info[n].h = h - 1;
    156 		info[n].dx = bb.xMin;
    157 		info[n].dy = bb.yMin;
    158 		info[n].advance = face->glyph->advance.x >> 6;
    159 
    160 		if (bb.yMin < 0) {
    161 			descent = -bb.yMin;
    162 		} else {
    163 			descent = 0;
    164 		}
    165 		ascent = h + bb.yMin;
    166 		if (ascent < 0)
    167 			ascent = 0;
    168 		if (ascent > ascent_max)
    169 			ascent_max = ascent;
    170 		if (descent > descent_max)
    171 			descent_max = descent;
    172 		if ((ascent + descent) > height_max)
    173 			height_max = ascent + descent;
    174 		
    175 		FT_Outline_Translate(&face->glyph->outline, nx * 64 + tx * 64, ny * 64 + ty * 64);
    176 		FT_Outline_Get_Bitmap(ftl, &face->glyph->outline, &bm);
    177 		nx += w;
    178 		if (h > rh)
    179 			rh = h;
    180 	}
    181 	bitmap = &bm;
    182 
    183 	sprintf(tmp, "%s.png", argv[3]);
    184 	save_png_gray(tmp, bitmap->buffer, bitmap->width, bitmap->rows);
    185 	FontInfo header;
    186 	memset(&header, 0, sizeof(header));
    187 	header.magic = TEXTUREFONT_MAGIC;
    188 	header.first = FIRST;
    189 	header.count = LAST - FIRST;
    190 	header.ascent_max = ascent_max;
    191 	header.descent_max = descent_max;
    192 	header.height_max = height_max;
    193 
    194 	sprintf(tmp, "%s.dat", argv[3]);
    195 	FILE *fp = fopen(tmp, "wb");
    196 	if (!fp)
    197 		return error("cannot write font data");
    198 	if (fwrite(&header, sizeof(header), 1, fp) != 1)
    199 		return error("failed to write font header");
    200 	if (fwrite(info + header.first, sizeof(FontInfo), header.count, fp) != header.count)
    201 		return error("failed to write character info");
    202 	fclose(fp);
    203 	return 0;
    204 }