sprites now using display lists too
[dd2d.git] / d2dfont.d
blobcd19692330d685bb3848204612f1ff01a223fd63
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 //glBindTexture(GL_TEXTURE_2D, smfont.fontAtlas.tex.id);
86 glPushMatrix();
87 scope(exit) glPopMatrix();
88 foreach (ubyte cc; 0..256) {
89 auto vga = smfont.vga[cc];
90 TexAtlas.Rect arc = smfont.rects[cc];
91 if (vga is null) {
92 // try uppercase
93 ubyte cn = cast(ubyte)koi8upper(cast(char)cc);
94 vga = smfont.vga[cn];
95 arc = smfont.rects[cn];
96 if (vga is null) {
97 // else use space
98 vga = smfont.vga[32];
99 arc = smfont.rects[32];
102 glNewList(smfont.listBase+cc, GL_COMPILE);
103 // draw char sprite
104 int x0 = -vga.sx;
105 int y0 = -vga.sy;
106 int x1 = x0+vga.width;
107 int y1 = y0+vga.height;
108 auto frect = smfont.fontAtlas.texCoords(arc);
109 glBegin(GL_QUADS);
110 glTexCoord2f(frect.x0, frect.y0); glVertex2i(x0, y0); // top-left
111 glTexCoord2f(frect.x1, frect.y0); glVertex2i(x1, y0); // top-right
112 glTexCoord2f(frect.x1, frect.y1); glVertex2i(x1, y1); // bottom-right
113 glTexCoord2f(frect.x0, frect.y1); glVertex2i(x0, y1); // bottom-left
114 glEnd();
115 // move coords
116 glTranslatef(vga.width, 0, 0);
117 // done
118 glEndList();
122 import arsd.png;
123 writePng("_zfont.png", smfont.fontAtlas.img);
129 public void smDrawText (int x, int y, const(char)[] str) {
130 if (str.length == 0) return;
131 glPushMatrix();
132 glPushAttrib(GL_LIST_BIT|GL_TEXTURE_BIT);
133 scope(exit) {
134 glPopAttrib();
135 glPopMatrix();
137 glBindTexture(GL_TEXTURE_2D, smfont.fontAtlas.tex.id);
138 //glRasterPos2i(x, y);
139 glTranslatef(x, y, 0);
140 glListBase(smfont.listBase);
141 glCallLists(cast(uint)str.length, GL_UNSIGNED_BYTE, str.ptr);