Mercurial > projects > mde
view 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 source
/* 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; }