hud: keys are on top now
[dd2d.git] / d2dfont.d
blob98e76d0863b44e604040f913506cc38662e18bb9
1 /* DooM2D: Midnight on the Firing Line
2 * coded by Ketmar // Invisible Vector <ketmar@ketmar.no-ip.org>
3 * Understanding is not required. Only obedience.
5 * This program is free software: you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation, either version 3 of the License, or
8 * (at your option) any later version.
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 module d2dfont is aliced;
19 private:
21 import arsd.color;
22 import iv.stream;
24 import iv.glbinds;
25 import glutils;
26 import console;
27 import wadarc;
29 import d2dgfx;
30 import tatlas;
32 import iv.vfs.koi8;
35 // ////////////////////////////////////////////////////////////////////////// //
36 struct D2DFont {
37 bool imagesLoaded;
38 D2DImage[256] vga;
39 TexAtlas.Rect[256] rects;
40 GLuint listBase;
41 TexAtlas fontAtlas;
44 public __gshared D2DFont smfont;
47 //TODO: reinit font function
48 public void loadSmFont () { loadSmFontAt(smfont); }
51 void loadSmFontAt (ref D2DFont smfont) {
52 if (!smfont.imagesLoaded) {
53 foreach (ubyte cc; 0..256) {
54 if (cc == 'y') continue; // smfont has invalid glyph there (why?!)
55 try {
56 import std.string : format;
57 smfont.vga[cc] = new D2DImage("fonts/stcf/stcfnx%02x.vga".format(cc));
58 } catch (Exception) {
62 // create empty thing for space (if necessary)
63 if (smfont.vga[32] is null) {
64 assert(smfont.vga['W']);
65 smfont.vga[32] = new D2DImage(6, smfont.vga['W'].height);
67 // build texture atlas
68 int asz = 128;
69 for (;;) {
70 bool success = true;
71 smfont.fontAtlas = new TexAtlas(asz, asz);
72 foreach (ubyte cc; 0..256) {
73 if (smfont.vga[cc] is null) continue;
74 auto rc = smfont.fontAtlas.insert(smfont.vga[cc]);
75 if (!rc.valid) { success = false; break; }
76 smfont.rects[cc] = rc;
78 if (success) break;
79 asz *= 2; // increase atlas size
80 if (asz > 2048) assert(0, "invalid bitmap font (too huge)");
82 // create display lists
83 smfont.listBase = glGenLists(256);
84 smfont.fontAtlas.updateTexture();
85 glPushMatrix();
86 scope(exit) glPopMatrix();
87 foreach (ubyte cc; 0..256) {
88 auto vga = smfont.vga[cc];
89 TexAtlas.Rect arc = smfont.rects[cc];
90 if (vga is null) {
91 // try uppercase
92 ubyte cn = cast(ubyte)koi8upper(cast(char)cc);
93 vga = smfont.vga[cn];
94 arc = smfont.rects[cn];
95 if (vga is null) {
96 // else use space
97 vga = smfont.vga[32];
98 arc = smfont.rects[32];
101 glNewList(smfont.listBase+cc, GL_COMPILE);
102 // draw char sprite
103 int x0 = -vga.sx;
104 int y0 = -vga.sy;
105 int x1 = x0+vga.width;
106 int y1 = y0+vga.height;
107 auto frect = smfont.fontAtlas.texCoords(arc);
108 glBegin(GL_QUADS);
109 glTexCoord2f(frect.x0, frect.y0); glVertex2i(x0, y0); // top-left
110 glTexCoord2f(frect.x1, frect.y0); glVertex2i(x1, y0); // top-right
111 glTexCoord2f(frect.x1, frect.y1); glVertex2i(x1, y1); // bottom-right
112 glTexCoord2f(frect.x0, frect.y1); glVertex2i(x0, y1); // bottom-left
113 glEnd();
114 // move coords
115 glTranslatef(vga.width, 0, 0);
116 // done
117 glEndList();
121 import arsd.png;
122 writePng("_zfont.png", smfont.fontAtlas.img);
128 public void smDrawText (int x, int y, const(char)[] str) {
129 if (str.length == 0) return;
130 glPushMatrix();
131 glPushAttrib(GL_LIST_BIT|GL_TEXTURE_BIT);
132 scope(exit) {
133 glPopAttrib();
134 glPopMatrix();
136 bindTexture(smfont.fontAtlas.tex.id);
137 //glRasterPos2i(x, y);
138 glTranslatef(x, y, 0);
139 glListBase(smfont.listBase);
140 glCallLists(cast(uint)str.length, GL_UNSIGNED_BYTE, str.ptr);