Mercurial > projects > mde
diff mde/resource/font.d @ 44:07bd1a09e161
Started implementing text rendering.
Can now position glyphs accurately and render them, in a very basic way.
A basic TextWidget.
committer: Diggory Hardy <diggory.hardy@gmail.com>
author | Diggory Hardy <diggory.hardy@gmail.com> |
---|---|
date | Fri, 16 May 2008 12:22:10 +0100 |
parents | |
children | 0fd51d2c6c8a |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mde/resource/font.d Fri May 16 12:22:10 2008 +0100 @@ -0,0 +1,128 @@ +/* LICENSE BLOCK +Part of mde: a Modular D game-oriented Engine +Copyright © 2007-2008 Diggory Hardy + +This program is free software: you can redistribute it and/or modify it under the terms +of the GNU General Public License as published by the Free Software Foundation, either +version 2 of the License, or (at your option) any later version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; +without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see <http://www.gnu.org/licenses/>. */ + +/// Sets up freetype (in a basic way). +module mde.resource.font; + +import mde.resource.exception; + +import derelict.freetype.ft; +import derelict.opengl.gl; + +import tango.stdc.stringz; +import tango.util.log.Log : Log, Logger; + +private Logger logger; +static this () { + logger = Log.getLogger ("mde.resource.font"); +} + +/** Font class. + * + * Particular to a font and size. (Maybe not size?) */ +class Font +{ + //BEGIN Static: manager + static { + /** Load the freetype library. */ + void initialize () { + if (FT_Init_FreeType (&library)) + throw new fontException ("error initialising the FreeType library"); + } + + //FIXME: don't use GC for Font resources + /** Cleanup: delete all fonts. */ + void cleanup () { + if (font) + delete font; + + FT_Done_FreeType (library); + } + + /** Get a font. + * + * Later specify font/size. + * + * Throws: + * fontLoadException when unable to load the font. */ + Font get(char[] path) { + if (font is null) font = new Font(path); + return font; + } + + private: + FT_Library library; + Font font; + } + //END Static + + + /** Load & cache a new font. */ + this (char[] path) + in { + assert (library !is null, "font: library is null"); + } body { + if (FT_New_Face (library, toStringz(path), 0, &face)) + throw new fontLoadException ("Unable to read font: "~path); + + if (FT_Set_Pixel_Sizes (face, 12,12)) + throw new fontLoadException ("Unable to set pixel size"); + } + + void drawStr (int x, int y, char[] str) { + FT_Vector pen = { x*64, y*64 }; + auto g = face.glyph; + + FT_Matrix m; + m.xx = 0x10000; + m.xy = m.yx = 0; + m.yy = -0x10000; + + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + FT_Pos y_adj = 0; // y adjustment (for height) + + foreach (chr; str) { + FT_Set_Transform(face, &m, &pen); + if (FT_Load_Char(face, chr, FT_LOAD_RENDER)) + return; // give up + + if (y_adj < g.metrics.height) y_adj = g.metrics.height; + + auto b = g.bitmap; + if (b.pixel_mode != FT_Pixel_Mode.FT_PIXEL_MODE_GRAY || b.num_grays != 256) { + char[128] tmp; + logger.warn (logger.format (tmp,"Unsupported freetype bitmap format: {}, {}", b.pixel_mode, b.num_grays)); + return; + } + if (b.pitch != b.width) + logger.info ("b.pitch != b.width"); + + //NOTE: y direction! + glRasterPos2i (g.bitmap_left,g.bitmap_top + y_adj/64); + glDrawPixels (b.width, b.rows, GL_LUMINANCE, GL_UNSIGNED_BYTE, cast(void*) b.buffer); + + pen.x += g.advance.x; + pen.y += g.advance.y; + } + } + + ~this () { + FT_Done_Face (face); + } + +private: + FT_Face face; +}