4 // Draw text using glBitmap.
6 // Copyright (C) 2011,2012,2013,2014,2015,2018 Olly Betts
8 // This program is free software; you can redistribute it and/or modify
9 // it under the terms of the GNU General Public License as published by
10 // the Free Software Foundation; either version 2 of the License, or
11 // (at your option) any later version.
13 // This program is distributed in the hope that it will be useful,
14 // but WITHOUT ANY WARRANTY; without even the implied warranty of
15 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 // GNU General Public License for more details.
18 // You should have received a copy of the GNU General Public License
19 // along with this program; if not, write to the Free Software
20 // Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
27 #include "glbitmapfont.h"
29 #include "aventypes.h"
30 #include "gllogerror.h"
43 #include "../lib/preload_font.h"
45 BitmapFont::~BitmapFont() {
46 if (!gllist_base
) return;
47 glDeleteLists(gllist_base
, BITMAPFONT_MAX_CHAR
);
48 CHECK_GL_ERROR("BitmapFont::~BitmapFont", "glDeleteLists");
52 BitmapFont::load(const wxString
& font_file_
)
54 font_file
= font_file_
;
57 gllist_base
= glGenLists(BITMAPFONT_MAX_CHAR
);
58 CHECK_GL_ERROR("BitmapFont::load", "glGenLists");
61 const unsigned char * p
= fontdata_preloaded
;
62 const unsigned char * end
= p
+ sizeof(fontdata_preloaded
);
63 for (int ch
= 0; ch
< BITMAPFONT_MAX_CHAR
; ++ch
) {
64 glNewList(gllist_base
+ ch
, GL_COMPILE
);
65 CHECK_GL_ERROR("BitmapFont::load", "glNewList");
69 unsigned int byte_width
= *p
++;
71 char_width
[ch
] = (byte_width
& 0x0f) + 2;
80 unsigned int start_and_n
= *p
++;
81 start
= start_and_n
>> 4;
82 n
= (start_and_n
& 15) + 1;
84 if (unsigned(end
- p
) < n
* byte_width
) {
89 // Even if there's nothing to display, we want to advance the
91 glBitmap(8 * byte_width
, n
, 0, -start
, char_width
[ch
], 0, p
);
92 CHECK_GL_ERROR("BitmapFont::load", "glBitmap");
94 CHECK_GL_ERROR("BitmapFont::load", "glEndList");
102 inline void call_lists(GLsizei n
, const GLvoid
* lists
)
104 #if SIZEOF_WXCHAR == 1
105 glCallLists(n
, GL_UNSIGNED_BYTE
, lists
);
106 #elif SIZEOF_WXCHAR == 2
107 glCallLists(n
, GL_UNSIGNED_SHORT
, lists
);
108 #elif SIZEOF_WXCHAR == 4
109 glCallLists(n
, GL_UNSIGNED_INT
, lists
);
111 # error "sizeof(wxChar) not 1, 2 or 4"
116 BitmapFont::init_extra_chars() const
118 int fd
= wxOpen(font_file
,
120 _O_RDONLY
|_O_SEQUENTIAL
|_O_BINARY
,
127 unsigned char * data
= NULL
;
130 if (fstat(fd
, &sb
) >= 0) {
131 data_len
= sb
.st_size
;
137 void * p
= mmap(NULL
, data_len
, PROT_READ
, MAP_SHARED
, fd
, 0);
138 if (p
== MAP_FAILED
) {
141 extra_data
= data
= static_cast<unsigned char*>(p
);
145 data
= new unsigned char[data_len
];
149 unsigned char * p
= data
;
151 ssize_t n
= read(fd
, p
, c
);
153 if (errno
== EINTR
) continue;
155 // FIXME: do something better. wxGetApp().ReportError(m);
156 // We have this message available: Error in format of font file ā%sā
157 // fprintf(stderr, "Couldn't load extended font.\n");
169 extra_chars
= new int[0x10000 - BITMAPFONT_MAX_CHAR
];
171 for (int i
= 0; i
< 0x10000 - BITMAPFONT_MAX_CHAR
; ++i
) {
172 if (data_ch
>= data_len
) {
176 extra_chars
[i
] = data_ch
;
177 unsigned int byte_width
= data
[data_ch
++];
181 unsigned int start_and_n
= data
[data_ch
];
182 int n
= (start_and_n
& 15) + 1;
183 data_ch
+= n
* byte_width
+ 1;
189 BitmapFont::glyph_width(wxChar ch
) const
191 #if SIZEOF_WXCHAR > 2
192 if (ch
>= 0x10000) return 0;
199 int char_idx
= extra_chars
[ch
- BITMAPFONT_MAX_CHAR
];
201 unsigned int byte_width
= extra_data
[char_idx
];
202 width
= (byte_width
& 0x0f) + 2;
209 BitmapFont::write_glyph(wxChar ch
) const
211 #if SIZEOF_WXCHAR > 2
212 if (ch
>= 0x10000) return;
217 unsigned int byte_width
= 0;
222 int char_idx
= extra_chars
[ch
- BITMAPFONT_MAX_CHAR
];
223 const unsigned char * p
= extra_data
;
227 width
= (byte_width
& 0x0f) + 2;
231 unsigned int start_and_n
= *p
++;
232 start
= start_and_n
>> 4;
233 n
= (start_and_n
& 15) + 1;
237 // Even if there's nothing to display, we want to advance the
239 glBitmap(8 * byte_width
, n
, 0, -start
, width
, 0, p
);
240 CHECK_GL_ERROR("BitmapFont::write_glyph", "glBitmap");
244 BitmapFont::write_string(const wxChar
*s
, size_t len
) const
246 if (!gllist_base
) return;
247 glListBase(gllist_base
);
248 #if SIZEOF_WXCHAR == 1
250 #elif SIZEOF_WXCHAR == 2 || SIZEOF_WXCHAR == 4
253 for (n
= 0; n
< len
; ++n
)
254 if (int(s
[n
]) >= BITMAPFONT_MAX_CHAR
)
259 while (len
&& int(*s
) >= BITMAPFONT_MAX_CHAR
) {
266 # error "sizeof(wxChar) not 1, 2 or 4"