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
;
35 // ////////////////////////////////////////////////////////////////////////// //
39 TexAtlas
.Rect
[256] rects
;
43 // called when context is destroyed; so we don't need to free resources
45 // create display lists
46 listBase
= glGenLists(256);
47 fontAtlas
.updateTexture();
49 scope(exit
) glPopMatrix();
50 foreach (ubyte cc
; 0..256) {
52 TexAtlas
.Rect arc
= rects
[cc
];
55 ubyte cn
= cast(ubyte)koi8upper(cast(char)cc
);
60 cn
= cast(ubyte)koi8lower(cast(char)cc
);
70 glNewList(listBase
+cc
, GL_COMPILE
);
75 int y1
= y0
+vi
.height
;
76 auto frect
= fontAtlas
.texCoords(arc
);
78 glTexCoord2f(frect
.x0
, frect
.y0
); glVertex2i(x0
, y0
); // top-left
79 glTexCoord2f(frect
.x1
, frect
.y0
); glVertex2i(x1
, y0
); // top-right
80 glTexCoord2f(frect
.x1
, frect
.y1
); glVertex2i(x1
, y1
); // bottom-right
81 glTexCoord2f(frect
.x0
, frect
.y1
); glVertex2i(x0
, y1
); // bottom-left
84 glTranslatef(vi
.width
, 0, 0);
90 // build texture atlas
91 private void buildAtlas (bool asBW
=false, int spwdt
=-1, int sphgt
=-1) {
92 // create empty thing for space (if necessary)
93 if (vga
[32] is null) {
94 int height
= 0, wdt
, count
;
95 foreach (D2DImage v
; vga
) if (v
!is null) { if (height
< v
.height
) height
= v
.height
; wdt
+= v
.width
; ++count
; }
97 if (spwdt
<= 0) spwdt
= wdt
;
98 if (sphgt
<= 0) sphgt
= height
;
99 vga
[32] = new D2DImage(spwdt
, sphgt
);
104 fontAtlas
= new TexAtlas(asz
, asz
);
105 foreach (ubyte cc
; 0..256) {
106 if (vga
[cc
] is null) continue;
107 auto img
= (asBW ? vga
[cc
].blackAndWhiteChan
!"red".img
: vga
[cc
].img
);
108 auto rc
= fontAtlas
.insert(img
);
109 if (!rc
.valid
) { success
= false; break; }
113 asz
*= 2; // increase atlas size
114 if (asz
> 2048) assert(0, "invalid bitmap font (too huge)");
120 __gshared D2DFont smfont
;
121 __gshared D2DFont bffont
;
122 __gshared D2DFont smbwfont
;
125 //TODO: reinit font function
126 public void loadSmFont () { loadSmFontAt(smfont
, false); loadSmFontAt(smbwfont
, true); }
127 public void loadBfFont () { loadBfFontAt(bffont
); }
130 void loadSmFontAt (ref D2DFont font
, bool asBW
) {
131 if (!font
.imagesLoaded
) {
132 foreach (ubyte cc
; 0..256) {
133 //if (cc == 'y') continue; // smfont has invalid glyph there (why?!)
135 import std
.string
: format
;
136 font
.vga
[cc
] = new D2DImage("fonts/stcf/stcfnx%02x.vga".format(cc
));
137 } catch (Exception
) {
141 font
.buildAtlas(asBW
);
146 writePng("_zfont.png", font.fontAtlas.img);
152 void loadBfFontAt (ref D2DFont font
) {
153 if (!font
.imagesLoaded
) {
154 foreach (ubyte cc
; 0..256) {
156 import std
.string
: format
;
157 font
.vga
[cc
] = new D2DImage("fonts/stbf/stbf_x%02x.vga".format(cc
));
158 } catch (Exception
) {
167 writePng("_zfont.png", font.fontAtlas.img);
173 void fontDrawText (ref D2DFont font
, int x
, int y
, const(char)[] str) {
174 if (str.length
== 0) return;
176 glPushAttrib(GL_LIST_BIT
/*|GL_TEXTURE_BIT*/);
181 bindTexture(font
.fontAtlas
.tex
.id
);
182 //glRasterPos2i(x, y);
183 glTranslatef(x
, y
, 0);
184 glListBase(font
.listBase
);
185 glCallLists(cast(uint)str.length
, GL_UNSIGNED_BYTE
, str.ptr
);
189 int fontTextWidth (ref D2DFont font
, const(char)[] str) {
191 foreach (char ch
; str) {
192 auto v
= font
.vga
.ptr
[ch
];
193 if (v
!is null) res
+= v
.width
;
199 int fontTextHeight (ref D2DFont font
, const(char)[] str) {
201 foreach (char ch
; str) {
202 auto v
= font
.vga
.ptr
[ch
];
203 if (v
!is null && res
< v
.height
) res
= v
.height
;
209 public void smDrawText (int x
, int y
, const(char)[] str) { fontDrawText(smfont
, x
, y
, str); }
210 public void bfDrawText (int x
, int y
, const(char)[] str) { fontDrawText(bffont
, x
, y
, str); }
211 public void smbwDrawText (int x
, int y
, const(char)[] str) { fontDrawText(smbwfont
, x
, y
, str); }
213 public int smTextWidth (const(char)[] str) { return fontTextWidth(smfont
, str); }
214 public int bfTextWidth (const(char)[] str) { return fontTextWidth(bffont
, str); }
216 public int smTextHeight (const(char)[] str) { return fontTextHeight(smfont
, str); }
217 public int bfTextHeight (const(char)[] str) { return fontTextHeight(bffont
, str); }
220 // ////////////////////////////////////////////////////////////////////////// //
221 __gshared Texture conFontTex
;
222 __gshared GLuint conListBase
;
223 enum ConCharWdt
= 10;
225 public void loadConFont () {
226 conFontTex
= new Texture("console/confont.png", Texture
.Option
.Nearest
);
227 conListBase
= glGenLists(256);
229 scope(exit
) glPopMatrix();
230 foreach (ubyte cc
; 0..256) {
232 if (cc
> ' ') { x
= ((cc
-32)%16)*16; y
= ((cc
-32)/16)*16; }
233 glNewList(conListBase
+cc
, GL_COMPILE
);
239 float tx0
= x
/256.0f, ty0
= y
/256.0f;
240 float tx1
= (x
+ConCharWdt
)/256.0f, ty1
= (y
+16)/256.0f;
242 glTexCoord2f(tx0
, ty0
); glVertex2i(x0
, y0
); // top-left
243 glTexCoord2f(tx1
, ty0
); glVertex2i(x1
, y0
); // top-right
244 glTexCoord2f(tx1
, ty1
); glVertex2i(x1
, y1
); // bottom-right
245 glTexCoord2f(tx0
, ty1
); glVertex2i(x0
, y1
); // bottom-left
248 glTranslatef(ConCharWdt
, 0, 0);
254 public int conCharHeight () { pragma(inline
, true); return 16; }
255 public int conCharWidth (char ch
) { pragma(inline
, true); return ConCharWdt
; }
257 public void conDrawChar (char ch
) {
258 bindTexture(conFontTex
.id
);
259 glCallList(cast(uint)ch
+conListBase
);