-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathFONT.cpp
330 lines (282 loc) · 7.85 KB
/
FONT.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
/*
Copyright (C) 1998 BJ Eirich (aka vecna)
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, write to the Free Software
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
// ÚÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ¿
// ³ The VERGE Engine ³
// ³ Copyright (C)1998 BJ Eirich (aka vecna) ³
// ³ Font Loading / Text Output module ³
// ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
/*
mod log:
<tSB>
8 December 2000 Removed BIOS font crap. Win2k doesn't like it.
10 Nov 2000 Tweaks here and there for Windows port.
<aen>
30 December 1999 Major revamp.
*/
#include "verge.h"
class font_t
{
private:
string_k F_filename;
int F_cellwidth, F_cellheight; // font cell dimensions; currently all fonts are monospace
int F_subsetcount; // total sets within this font
int F_selected; // currently selected subset
memorystream_t F_data; // holds font image data
// helpers
int loadheader(VFILE* vfp);
public:
int vacant() const { return (F_data.getsize() < 1); }
void loadbiosfont();
void clear() // vacates this font; frees image data, empties filename string
{
F_filename="";
F_data.clear();
}
// accessors
const string_k& getfilename() const { return F_filename; }
int getheight() const { return F_cellheight; }
int getwidth() const { return F_cellwidth; }
int getsubsetcount() const { return F_subsetcount; }
// constructors
font_t() { }
/* font_t(const char* filename)
{
loadfromfile(filename);
}*/
// primary interface
int loadfromfile(const char* filename);
int selected() const { return F_selected; }
void select(int subset)
{
if (subset < 0 || subset >= F_subsetcount)
return;
F_selected = subset;
}
void paintchar(const char ch);
void paintstring(const char* zstr, int imbed = 0);
};
#define MAX_FONTS 10
class fontcontroller_t
{
private:
// actual fonts
font_t F_fonts[MAX_FONTS];
public:
// default constructor
fontcontroller_t()
{
}
void load(int slot, const char* filename)
{
// invalid slot
if (slot < 0 || slot >= MAX_FONTS)
return;
// invalid name
if (!filename)
return;
F_fonts[slot].loadfromfile(filename);
}
// accessors
font_t& getfont(int slot)
{
// invalid requests get the dummy
if (slot < 0 || slot >= MAX_FONTS)
return F_fonts[0];
// valid requests are fulfilled
return F_fonts[slot];
}
};
// DATA ////////////////////////////////////////////////////////////////////////////////////////////
fontcontroller_t fontcontroller;
// global font coordinates & misc
static int font_x, font_y, font_alignx;
// CODE ////////////////////////////////////////////////////////////////////////////////////////////
void font_t::paintchar(const char ch)
{
// validate character range
if (ch < 32 && ch >= 127)
return;
// convert to font bay character offset
int offset = (F_selected*96*F_cellwidth*F_cellheight) + ((ch-32)*F_cellwidth*F_cellheight);
// move there
F_data.setposition(offset*gfx.bpp);
// paint the character
/* LFB_Blit(font_x, font_y, F_cellwidth, F_cellheight,
(unsigned char*)F_data.getposdata(), 1, 0);*/
gfx.TCopySprite(font_x,font_y,
F_cellwidth,F_cellheight,
(byte*)F_data.getposdata());
}
void font_t::paintstring(const char* zstr, int imbed)
{
while (*zstr)
{
const unsigned char ch = *zstr++;
// i don't likes it. implement font selection some other way.
switch (ch)
{
case 126: select(0); continue;
case 128: select(1); continue;
case 129: select(2); continue;
case 130: select(3); continue;
}
// allow tab and newlines codes to have meaning?
if (imbed)
{
if ('\t' == ch)
{
int chx = (font_x - font_alignx)/F_cellwidth;
font_x += (4 - (chx % 4))*F_cellwidth;
continue;
}
else if ('\n' == ch)
{
font_y += F_cellheight;
font_x = font_alignx;
continue;
}
}
paintchar(ch);
font_x += F_cellwidth;
}
}
int font_t::loadheader(VFILE* vfp)
{
if (!vfp)
// failure
return 0;
long ver = vgetc(vfp);
if (ver != 1)
{
vclose(vfp);
Sys_Error("font_t::loadheader: %s: incorrect version number (reported %d).\n",
getfilename(), ver);
}
// set font dims
F_cellwidth = vgetw(vfp);
if (F_cellwidth < 1 || F_cellwidth > 128)
{
vclose(vfp);
Sys_Error("font_t::loadheader: %s: bogus cell-width (reported %d).\n",
getfilename(), F_cellwidth);
}
F_cellheight = vgetw(vfp);
if (F_cellheight < 1 || F_cellheight > 128)
{
vclose(vfp);
Sys_Error("font_t::loadheader: %s: bogus cell-length (reported %d).\n",
getfilename(), F_cellheight);
}
// set subsets
F_subsetcount = vgetw(vfp);
F_selected = 0;
if (F_subsetcount < 1 || F_subsetcount > 4)
{
vclose(vfp);
Sys_Error("font_t::loadheader: %s: bogus subset count (reported %d).\n",
getfilename(), F_subsetcount);
}
// success
return 1;
}
int font_t::loadfromfile(const char* filename)
{
// set filename; stuff relies on this for error messages
F_filename = filename;
VFILE* f = vopen(F_filename.c_str());
if (!f)
{
Log(va("font_t::loadfromfile: %s: unable to open", getfilename()));
// failture
return 0;
}
else
{
// get header info and setup some defaults
// -- ignore return value for now; f is gauranteed to exist anyway
loadheader(f);
// get cumulative size of all subsets in this font & resize data to match
F_data.setsize(F_subsetcount*96*(F_cellwidth*F_cellheight));
// bend the rules and read in the font
vread((char*)F_data.getdata(), F_data.getsize(), f);
vclose(f);
}
if (gfx.bpp>1)
{
// make a temp copy of 8-bit image
memorystream_t save;
save.write(F_data, F_data.getsize());
// clear & resize destination for hicolor image
F_data.clear();
F_data.setsize(sizeof(unsigned short)*save.getsize());
// bend the rules so we can do this a little bit faster
unsigned char* saveptr = (unsigned char*)save.getdata();
unsigned short* newptr = (unsigned short*)F_data.getdata();
for (unsigned int n = 0; n < save.getsize(); n += 1)
{
newptr[n]
= (unsigned short)( (saveptr[n])
? (gfx.Conv8(saveptr[n]))
: gfx.trans_mask);
}
}
// success
return 1;
}
// wrapper routines for font-related classes
void Font_Print(int slot, const char* zstr)
{
fontcontroller.getfont(slot).paintstring(zstr);
}
void Font_PrintImbed(int slot, const char* zstr)
{
fontcontroller.getfont(slot).paintstring(zstr, 1);
}
int Font_GetWidth(int slot)
{
return fontcontroller.getfont(slot).getwidth();
}
int Font_GetLength(int slot)
{
return fontcontroller.getfont(slot).getheight();
}
int Font_Load(const char* filename)
{
int n;
for (n=0; n < MAX_FONTS; n++)
{
if (fontcontroller.getfont(n).vacant())
// if we fail, return a bogus slot; will equate to usage of 'dummy'
if (!fontcontroller.getfont(n).loadfromfile(filename))
return -1;
// we succeeded, break out
else
break;
}
// return slot of font we loaded; if no free slots found,
// we'll be returning a bogus slot anyway (total slots + 1),
// which equates to usage of 'dummy'
return n;
}
// global positioning routines
// *** in the future, make this relative
// *** to a main viewport canvas or something
void Font_GotoXY(int x, int y)
{
font_x = font_alignx = x;
font_y = y;
}
int Font_GetX() { return font_x; }
int Font_GetY() { return font_y; }