4 // Draw text using glBitmap.
6 // Copyright (C) 2011,2012,2013,2014,2015 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"
42 #include "../lib/preload_font.h"
44 #define CHECK_GL_ERROR(M, F) do { \
45 GLenum error_code_ = glGetError(); \
46 if (error_code_ != GL_NO_ERROR) { \
47 wxLogError(wxT(__FILE__ ":" STRING(__LINE__) ": OpenGL error: %s " \
48 "(call " F " in method " M ")"), \
49 wxString((const char *)gluErrorString(error_code_), \
50 wxConvUTF8).c_str()); \
55 BitmapFont::load(const wxString
& font_file_
)
57 font_file
= font_file_
;
60 gllist_base
= glGenLists(BITMAPFONT_MAX_CHAR
);
63 const unsigned char * p
= fontdata_preloaded
;
64 const unsigned char * end
= p
+ sizeof(fontdata_preloaded
);
65 for (int ch
= 0; ch
< BITMAPFONT_MAX_CHAR
; ++ch
) {
66 glNewList(gllist_base
+ ch
, GL_COMPILE
);
67 CHECK_GL_ERROR("BitmapFont::load", "glNewList");
71 unsigned int byte_width
= *p
++;
73 char_width
[ch
] = (byte_width
& 0x0f) + 2;
82 unsigned int start_and_n
= *p
++;
83 start
= start_and_n
>> 4;
84 n
= (start_and_n
& 15) + 1;
86 if (unsigned(end
- p
) < n
* byte_width
) {
91 // Even if there's nothing to display, we want to advance the
93 glBitmap(8 * byte_width
, n
, 0, -start
, char_width
[ch
], 0, p
);
94 CHECK_GL_ERROR("BitmapFont::load", "glBitmap");
96 CHECK_GL_ERROR("BitmapFont::load", "glEndList");
104 inline void call_lists(GLsizei n
, const GLvoid
* lists
)
106 #if SIZEOF_WXCHAR == 1
107 glCallLists(n
, GL_UNSIGNED_BYTE
, lists
);
108 #elif SIZEOF_WXCHAR == 2
109 glCallLists(n
, GL_UNSIGNED_SHORT
, lists
);
110 #elif SIZEOF_WXCHAR == 4
111 glCallLists(n
, GL_UNSIGNED_INT
, lists
);
113 # error "sizeof(wxChar) not 1, 2 or 4"
118 BitmapFont::init_extra_chars() const
120 int fd
= wxOpen(font_file
,
122 _O_RDONLY
|_O_SEQUENTIAL
|_O_BINARY
,
129 unsigned char * data
= NULL
;
132 if (fstat(fd
, &sb
) >= 0) {
133 data_len
= sb
.st_size
;
139 void * p
= mmap(NULL
, data_len
, PROT_READ
, MAP_SHARED
, fd
, 0);
140 if (p
== MAP_FAILED
) {
143 extra_data
= data
= static_cast<unsigned char*>(p
);
147 data
= new unsigned char[data_len
];
151 unsigned char * p
= data
;
153 ssize_t n
= read(fd
, p
, c
);
155 if (errno
== EINTR
) continue;
157 // FIXME: do something better. wxGetApp().ReportError(m);
158 // We have this message available: Error in format of font file ā%sā
159 // fprintf(stderr, "Couldn't load extended font.\n");
171 extra_chars
= new int[0x10000 - BITMAPFONT_MAX_CHAR
];
173 for (int i
= 0; i
< 0x10000 - BITMAPFONT_MAX_CHAR
; ++i
) {
174 if (data_ch
>= data_len
) {
178 extra_chars
[i
] = data_ch
;
179 unsigned int byte_width
= data
[data_ch
++];
183 unsigned int start_and_n
= data
[data_ch
];
184 int n
= (start_and_n
& 15) + 1;
185 data_ch
+= n
* byte_width
+ 1;
191 BitmapFont::glyph_width(wxChar ch
) const
193 #if SIZEOF_WXCHAR > 2
194 if (ch
>= 0x10000) return 0;
201 int char_idx
= extra_chars
[ch
- BITMAPFONT_MAX_CHAR
];
203 unsigned int byte_width
= extra_data
[char_idx
];
204 width
= (byte_width
& 0x0f) + 2;
211 BitmapFont::write_glyph(wxChar ch
) const
213 #if SIZEOF_WXCHAR > 2
214 if (ch
>= 0x10000) return;
219 unsigned int byte_width
= 0;
224 int char_idx
= extra_chars
[ch
- BITMAPFONT_MAX_CHAR
];
225 const unsigned char * p
= extra_data
;
229 width
= (byte_width
& 0x0f) + 2;
233 unsigned int start_and_n
= *p
++;
234 start
= start_and_n
>> 4;
235 n
= (start_and_n
& 15) + 1;
239 // Even if there's nothing to display, we want to advance the
241 glBitmap(8 * byte_width
, n
, 0, -start
, width
, 0, p
);
242 CHECK_GL_ERROR("BitmapFont::write_glyph", "glBitmap");
246 BitmapFont::write_string(const wxChar
*s
, size_t len
) const
248 if (!gllist_base
) return;
249 glListBase(gllist_base
);
250 #if SIZEOF_WXCHAR == 1
252 #elif SIZEOF_WXCHAR == 2 || SIZEOF_WXCHAR == 4
255 for (n
= 0; n
< len
; ++n
)
256 if (int(s
[n
]) >= BITMAPFONT_MAX_CHAR
)
261 while (len
&& int(*s
) >= BITMAPFONT_MAX_CHAR
) {
268 # error "sizeof(wxChar) not 1, 2 or 4"