# HG changeset patch # User Diggory Hardy # Date 1210936930 -3600 # Node ID 07bd1a09e161c04e567d0ca0cdba81fbc0990731 # Parent 1530d9c04d4dcaf29ddfb6a0e6af63bc2293c9f9 Started implementing text rendering. Can now position glyphs accurately and render them, in a very basic way. A basic TextWidget. committer: Diggory Hardy diff -r 1530d9c04d4d -r 07bd1a09e161 codeDoc/jobs.txt --- a/codeDoc/jobs.txt Thu May 15 10:39:57 2008 +0100 +++ b/codeDoc/jobs.txt Fri May 16 12:22:10 2008 +0100 @@ -3,6 +3,7 @@ In progress: +Implementing font rendering diff -r 1530d9c04d4d -r 07bd1a09e161 data/conf/gui.mtt --- a/data/conf/gui.mtt Thu May 15 10:39:57 2008 +0100 +++ b/data/conf/gui.mtt Fri May 16 12:22:10 2008 +0100 @@ -7,4 +7,4 @@ {W2} - + diff -r 1530d9c04d4d -r 07bd1a09e161 doc/Readme.txt --- a/doc/Readme.txt Thu May 15 10:39:57 2008 +0100 +++ b/doc/Readme.txt Fri May 16 12:22:10 2008 +0100 @@ -21,6 +21,10 @@ Also thanks to: Walter Bright and Digital Mars for D and DMD. The tango team for Tango. +[derelict] +[sdl] +[opengl] +[freetype] diff -r 1530d9c04d4d -r 07bd1a09e161 mde/ft/init.d --- a/mde/ft/init.d Thu May 15 10:39:57 2008 +0100 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -/* 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 . */ - -/// Sets up freetype (in a basic way). -module mde.ft.init; - -import derelict.freetype.ft; - -import tango.stdc.stringz; -import tango.util.log.Log : Log, Logger; - -private Logger logger; -static this () { - logger = Log.getLogger ("mde.ft.init"); -} - -FT_Library library; -FT_Face face; - -// FIXME: use a different exception -const PATH = "/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf"; -void initFreeType () { - if (FT_Init_FreeType (&library)) - throw new Exception ("error initialising the FreeType library"); - - if (FT_New_Face (library, toStringz(PATH), 0, &face)) - throw new Exception ("Unable to read font: "~PATH); - - if (FT_Set_Pixel_Sizes (face, 32,32)) - throw new Exception ("Unable to set pixel size"); -} - -void cleanupFreeType () { - FT_Done_Face (face); - FT_Done_FreeType (library); -} diff -r 1530d9c04d4d -r 07bd1a09e161 mde/gl/basic.d --- a/mde/gl/basic.d Thu May 15 10:39:57 2008 +0100 +++ b/mde/gl/basic.d Fri May 16 12:22:10 2008 +0100 @@ -25,6 +25,10 @@ //BEGIN GL & window setup void glSetup () { glClearColor (0.0f, 0.0f, 0.0f, 0.0f); + glDisable(GL_DEPTH_TEST); + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); } void setProjection (int w, int h) { @@ -38,7 +42,6 @@ //glOrtho (0.0,1.0,0.0,1.0,-1.0,1.0); glMatrixMode(GL_MODELVIEW); - glLoadIdentity(); } //END GL & window setup diff -r 1530d9c04d4d -r 07bd1a09e161 mde/gui/widget/Widget.d --- a/mde/gui/widget/Widget.d Thu May 15 10:39:57 2008 +0100 +++ b/mde/gui/widget/Widget.d Fri May 16 12:22:10 2008 +0100 @@ -20,6 +20,8 @@ import mde.gui.exception; import mde.gui.renderer.IRenderer; +import mde.resource.font; + import tango.io.Stdout; /** An abstract base widget class. @@ -42,6 +44,9 @@ return data; } + bool isWSizable () { return false; } + bool isHSizable () { return false; } + // Widget type should always be the first value. int[] getCreationData () { return [widgetType]; @@ -84,18 +89,15 @@ /** A base for fixed-size widgets. */ class FixedWidget : Widget { this (IWindow wind, int[] data) { + w = wF; + h = hF; super (wind, data); - w = wF = data[1]; - h = hF = data[2]; } int[] getCreationData () { return [widgetType, wF, hF]; } - bool isWSizable () { return false; } - bool isHSizable () { return false; } - /* Not resizable, so return current size. */ void getMinimalSize (out int mw, out int mh) { mw = wF; @@ -142,6 +144,8 @@ { this (IWindow wind, int[] data) { if (data.length != 3) throw new WidgetDataException; + wF = data[1]; + hF = data[2]; super (wind, data); } void draw () { @@ -169,6 +173,8 @@ this (IWindow wind, int[] data) { if (data.length != 3) throw new WidgetDataException; + wF = data[1]; + hF = data[2]; super (wind, data); } @@ -206,4 +212,24 @@ window.requestRedraw; } } + +/// Basic text widget +class TextWidget : FixedWidget +{ + this (IWindow wind, int[] data) { + if (data.length != 1) throw new WidgetDataException; + wF = 100; //FIXME: set properly + hF = 25; + super (wind,data); + } + + void draw () { + super.draw(); + if (font is null) font = Font.get("/usr/share/fonts/truetype/ttf-dejavu/DejaVuSans.ttf"); + font.drawStr (x,y, "Text Widget"); + } + +protected: + static Font font; +} //END Widgets diff -r 1530d9c04d4d -r 07bd1a09e161 mde/gui/widget/createWidget.d --- a/mde/gui/widget/createWidget.d Thu May 15 10:39:57 2008 +0100 +++ b/mde/gui/widget/createWidget.d Fri May 16 12:22:10 2008 +0100 @@ -60,6 +60,9 @@ FixedBlank = 0x1, SizableBlank = WSIZABLE | HSIZABLE | 0x1, + // text: 0x2 + Text = 0x2, + // buttons: 0x10 Button = INTERACTIBLE | 0x10, @@ -71,20 +74,21 @@ // Only used for binarySearch algorithm generation; must be ordered by numerical values. const char[][] WIDGETS = [ "FixedBlank", + "Text", "SizableBlank", "Button", "GridLayout" ]; // Purely to add indentation. Could just return "" without affecting functionality. -/+static char[] indent (uint i) { +static char[] indent (uint i) { char[] ret; for (; i > 0; --i) ret ~= " "; // This is not executable at compile time: //ret.length = i * 4; // number of characters for each indentation //ret[] = ' '; // character to indent with return ret; -}+/ -char[] indent (uint) { return ""; } +} +//char[] indent (uint) { return ""; } /* Generates a binary search algorithm. */ char[] binarySearch (char[] var, char[][] consts, int indents = 0) { diff -r 1530d9c04d4d -r 07bd1a09e161 mde/resource/exception.d --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/mde/resource/exception.d Fri May 16 12:22:10 2008 +0100 @@ -0,0 +1,40 @@ +/* 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 . */ + +/// Contains resource exceptions +module mde.resource.exception; +import mde.exception; + +/// Thrown when initialising freetype fails. +class fontException : mdeException { + char[] getSymbol () { + return super.getSymbol ~ ".resource.font"; + } + + this (char[] msg) { + super(msg); + } +} + +/// Thrown when loading a freetype font fails. +class fontLoadException : fontException { + char[] getSymbol () { + return super.getSymbol ~ ".resource.font"; + } + + this (char[] msg) { + super(msg); + } +} diff -r 1530d9c04d4d -r 07bd1a09e161 mde/resource/font.d --- /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 . */ + +/// 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; +} diff -r 1530d9c04d4d -r 07bd1a09e161 mde/resource/paths.d --- a/mde/resource/paths.d Thu May 15 10:39:57 2008 +0100 +++ b/mde/resource/paths.d Fri May 16 12:22:10 2008 +0100 @@ -150,7 +150,7 @@ /** Find at least one path for each required directory. * * Note: the logger cannot be used yet, so only output is exception messages. */ - +// FIXME: use tango/sys/Environment.d version (linux) { void resolvePaths () { // Home directory: diff -r 1530d9c04d4d -r 07bd1a09e161 mde/scheduler/init2.d --- a/mde/scheduler/init2.d Thu May 15 10:39:57 2008 +0100 +++ b/mde/scheduler/init2.d Fri May 16 12:22:10 2008 +0100 @@ -35,7 +35,7 @@ import imde = mde.imde; import mde.gui.Gui; import mde.input.Input; -import ft = mde.ft.init; +import font = mde.resource.font; // NOTE: error reporting needs a revision @@ -86,7 +86,7 @@ void initFreeType () { // init func try { - ft.initFreeType; + font.Font.initialize; } catch (Exception e) { logger.fatal ("initFreeType failed: " ~ e.msg); setInitFailure;