commit f59306730f160dec8020600b306c15595e583e3c
parent b82d26a75b526101afe8497a1261fb440fdb3abd
Author: Brian Swetland <swetland@frotz.net>
Date: Sat, 22 Jun 2013 02:02:05 -0700
mkfont: simple tool for building texture fonts
Diffstat:
3 files changed, 195 insertions(+), 0 deletions(-)
diff --git a/common/texturefont.h b/common/texturefont.h
@@ -0,0 +1,43 @@
+/* Copyright 2013 Brian Swetland <swetland@frotz.net>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _TEXTUREFONT_H_
+#define _TEXTUREFONT_H_
+
+struct CharInfo {
+ // location in texture
+ u16 x;
+ u16 y;
+ u16 w;
+ u16 h;
+ // adjustment relative to 0,0 baseline
+ s16 dx;
+ s16 dy;
+ // adjustment to the next character;
+ u16 advance;
+ u16 unused;
+};
+
+struct FontInfo {
+ u32 magic;
+ u32 first;
+ u32 count;
+ u32 unused;
+ CharInfo info[0];
+};
+
+#define TEXTUREFONT_MAGIC 0x746E6F46
+
+#endif
diff --git a/tools/mkfont.cc b/tools/mkfont.cc
@@ -0,0 +1,145 @@
+/* Copyright 2013 Brian Swetland <swetland@frotz.net>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_OUTLINE_H
+#include FT_BITMAP_H
+#include FT_GLYPH_H
+
+#include <util.h>
+#include <texturefont.h>
+
+/* from internal header... */
+#define FT_PIX_FLOOR(x) ((x) & ~63)
+#define FT_PIX_CEIL(x) FT_PIX_FLOOR((x) + 63)
+
+int main(int argc, char **argv) {
+ FT_Library ftl;
+ FT_Face face;
+ FT_Bitmap *bitmap;
+ unsigned n;
+ void *x;
+
+ FT_BBox bb;
+ FT_Bitmap bm;
+ unsigned char data[1024 * 1024];
+ int w, h, tx, ty, nx, ny, rh, max;
+ CharInfo info[128];
+
+ io_ignore_asset_paths();
+
+ if (argc < 3)
+ return -1;
+
+ if (FT_Init_FreeType(&ftl))
+ return -1;
+
+ x = load_file(argv[1], &n);
+ if (x == 0)
+ return -1;
+
+ if (FT_New_Memory_Face(ftl, (FT_Byte*) x, n, 0, &face))
+ return error("cannot load font '%s'", argv[1]);
+
+ if (FT_Set_Pixel_Sizes(face, 0, atoi(argv[2])))
+ return error("cannot set font size to %s\n", argv[2]);
+
+ max = 128;
+retry:
+ memset(data, 0, sizeof(data));
+ memset(info, 0, sizeof(info));
+
+ bm.rows = max;
+ bm.width = max;
+ bm.pitch = max;
+ bm.buffer = data;
+ bm.num_grays = 256;
+ bm.pixel_mode = FT_PIXEL_MODE_GRAY;
+ bm.palette_mode = 0;
+ bm.palette = NULL;
+
+ nx = ny = 1;
+ rh = 0;
+
+ printf("%dx%d texture...\n", max, max);
+ for (n = 0x20; n < 0x7F; n++) {
+ if (FT_Load_Char(face, n, FT_LOAD_NO_BITMAP)) {
+ error("missing glyph for %d\n", n);
+ continue;
+ }
+ FT_Outline_Get_CBox(&face->glyph->outline, &bb);
+ /* grid fit */
+ bb.xMin = FT_PIX_FLOOR(bb.xMin);
+ bb.yMin = FT_PIX_FLOOR(bb.yMin);
+ bb.xMax = FT_PIX_CEIL(bb.xMax);
+ bb.yMax = FT_PIX_CEIL(bb.yMax);
+ /* convert from 26.6 to pixel coords */
+ bb.xMin >>= 6;
+ bb.yMin >>= 6;
+ bb.xMax >>= 6;
+ bb.yMax >>= 6;
+ w = bb.xMax - bb.xMin + 1;
+ h = bb.yMax - bb.yMin + 1;
+ tx = -bb.xMin;
+ ty = -bb.yMin;
+#if 0
+ fprintf(stderr,"%d,%d %d,%d adv %d\n",
+ bb.xMin, bb.yMin, bb.xMax, bb.yMax,
+ face->glyph->advance.x >> 6);
+#endif
+ if ((nx + w) >= max) {
+ nx = 1;
+ ny += rh + 1;
+ rh = 0;
+ }
+ if ((ny + h) >= max) {
+ max *= 2;
+ if (max > 1024) {
+ fprintf(stderr,"oops! out of space\n");
+ return -1;
+ }
+ goto retry;
+ }
+ info[n].x = nx;
+ info[n].y = ny;
+ info[n].w = w - 1;
+ info[n].h = h - 1;
+ info[n].dx = bb.xMin;
+ info[n].dy = bb.yMin;
+ info[n].advance = face->glyph->advance.x >> 6;
+ FT_Outline_Translate(&face->glyph->outline, nx * 64 + tx * 64, ny * 64 + ty * 64);
+ FT_Outline_Get_Bitmap(ftl, &face->glyph->outline, &bm);
+ nx += w;
+ if (h > rh)
+ rh = h;
+ }
+ bitmap = &bm;
+ save_png_gray("font.png", bitmap->buffer, bitmap->width, bitmap->rows);
+ FontInfo header;
+ header.magic = TEXTUREFONT_MAGIC;
+ header.first = 0x20;
+ header.count = 0x80;
+ header.unused = 0;
+ FILE *fp = fopen("font.dat", "wb");
+ if (!fp)
+ return error("cannot write font data");
+ if (fwrite(&header, sizeof(header), 1, fp) != 1)
+ return error("failed to write font header");
+ if (fwrite(info + header.first, sizeof(FontInfo), header.count, fp) != header.count)
+ return error("failed to write character info");
+ fclose(fp);
+ return 0;
+}
diff --git a/tools/module.mk b/tools/module.mk
@@ -0,0 +1,7 @@
+M_PATH := $(modulepath)
+
+M_NAME := mkfont
+M_OBJS := mkfont.o
+M_LIBS := freetype common
+
+include build/app.mk