source: git/src/glbitmapfont.cc @ 76cf7f1

RELEASE/1.2debug-cidebug-ci-sanitiserswalls-datawalls-data-hanging-as-warning
Last change on this file since 76cf7f1 was 0273042, checked in by Olly Betts <olly@…>, 6 years ago

Eliminate use of gluErrorString

Fixes deprecation warning on macOS.

  • Property mode set to 100644
File size: 5.9 KB
RevLine 
[a1614eb]1//
2//  glbitmapfont.cc
3//
4//  Draw text using glBitmap.
5//
[0273042]6//  Copyright (C) 2011,2012,2013,2014,2015,2018 Olly Betts
[a1614eb]7//
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.
12//
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.
17//
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
21//
22
23#ifdef HAVE_CONFIG_H
24#include <config.h>
25#endif
26
27#include "glbitmapfont.h"
28
29#include "aventypes.h"
[0273042]30#include "gllogerror.h"
[a1614eb]31#include "useful.h"
32#include "wx.h"
33
[7ada45b]34#include <cerrno>
[d6ccc5f]35#ifdef HAVE_MMAP
[7ada45b]36#include <sys/mman.h>
[d6ccc5f]37#else
38#include <unistd.h>
39#endif
[7ada45b]40
41using namespace std;
42
[614d60b]43#include "../lib/preload_font.h"
44
[0273042]45BitmapFont::~BitmapFont() {
46    if (!gllist_base) return;
47    glDeleteLists(gllist_base, BITMAPFONT_MAX_CHAR);
48    CHECK_GL_ERROR("BitmapFont::~BitmapFont", "glDeleteLists");
49}
[a1614eb]50
51bool
[614d60b]52BitmapFont::load(const wxString & font_file_)
[a1614eb]53{
[614d60b]54    font_file = font_file_;
[a1614eb]55
56    if (!gllist_base) {
57        gllist_base = glGenLists(BITMAPFONT_MAX_CHAR);
[0273042]58        CHECK_GL_ERROR("BitmapFont::load", "glGenLists");
[a1614eb]59    }
60
[614d60b]61    const unsigned char * p = fontdata_preloaded;
62    const unsigned char * end = p + sizeof(fontdata_preloaded);
[a1614eb]63    for (int ch = 0; ch < BITMAPFONT_MAX_CHAR; ++ch) {
64        glNewList(gllist_base + ch, GL_COMPILE);
65        CHECK_GL_ERROR("BitmapFont::load", "glNewList");
[614d60b]66        if (p == end) {
[17c483d]67            return false;
68        }
[614d60b]69        unsigned int byte_width = *p++;
[a1614eb]70
[d4d6909]71        char_width[ch] = (byte_width & 0x0f) + 2;
72        byte_width >>= 6;
[a1614eb]73
74        int start = 0;
[1f95589]75        unsigned int n = 0;
[a1614eb]76        if (byte_width) {
[614d60b]77            if (p == end) {
[17c483d]78                return false;
79            }
[614d60b]80            unsigned int start_and_n = *p++;
[a1614eb]81            start = start_and_n >> 4;
82            n = (start_and_n & 15) + 1;
[614d60b]83
[87b0ab3f]84            if (unsigned(end - p) < n * byte_width) {
[17c483d]85                return false;
86            }
[a1614eb]87        }
88
89        // Even if there's nothing to display, we want to advance the
90        // raster position.
[614d60b]91        glBitmap(8 * byte_width, n, 0, -start, char_width[ch], 0, p);
[a1614eb]92        CHECK_GL_ERROR("BitmapFont::load", "glBitmap");
93        glEndList();
94        CHECK_GL_ERROR("BitmapFont::load", "glEndList");
[614d60b]95
96        p += n * byte_width;
[a1614eb]97    }
98
99    return true;
100}
101
102inline void call_lists(GLsizei n, const GLvoid * lists)
103{
[30b66b5]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);
110#else
111# error "sizeof(wxChar) not 1, 2 or 4"
112#endif
[a1614eb]113}
114
[36b4cd7]115void
[cba8bf34]116BitmapFont::init_extra_chars() const
[36b4cd7]117{
[834d2a7]118    int fd = wxOpen(font_file,
[614d60b]119#ifdef __WXMSW__
[194b978]120            _O_RDONLY|_O_SEQUENTIAL|_O_BINARY,
[614d60b]121#else
[834d2a7]122            O_RDONLY,
[614d60b]123#endif
[834d2a7]124            0);
[614d60b]125
[7ada45b]126    int data_len = 0;
127    unsigned char * data = NULL;
128    if (fd >= 0) {
129        struct stat sb;
130        if (fstat(fd, &sb) >= 0) {
131            data_len = sb.st_size;
132        }
133    }
134
135#if HAVE_MMAP
136    if (data_len) {
137        void * p = mmap(NULL, data_len, PROT_READ, MAP_SHARED, fd, 0);
138        if (p == MAP_FAILED) {
[614d60b]139            data_len = 0;
[7ada45b]140        } else {
141            extra_data = data = static_cast<unsigned char*>(p);
142        }
[614d60b]143    }
[7ada45b]144#else
[410c73f]145    data = new unsigned char[data_len];
[6e94014]146    extra_data = data;
[7ada45b]147    if (data_len) {
148        size_t c = data_len;
[d6ccc5f]149        unsigned char * p = data;
[7ada45b]150        while (c) {
[d6ccc5f]151            ssize_t n = read(fd, p, c);
[7ada45b]152            if (n <= 0) {
153                if (errno == EINTR) continue;
154                data_len = 0;
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");
158                break;
159            }
[d6ccc5f]160            p += n;
[7ada45b]161            c -= n;
162        }
[cba8bf34]163    }
[7ada45b]164#endif
165
166    if (fd >= 0)
167        close(fd);
[cba8bf34]168
[410c73f]169    extra_chars = new int[0x10000 - BITMAPFONT_MAX_CHAR];
[6e94014]170    int data_ch = 0;
[cba8bf34]171    for (int i = 0; i < 0x10000 - BITMAPFONT_MAX_CHAR; ++i) {
[6e94014]172        if (data_ch >= data_len) {
173            extra_chars[i] = -1;
[cba8bf34]174            continue;
[36b4cd7]175        }
[6e94014]176        extra_chars[i] = data_ch;
177        unsigned int byte_width = data[data_ch++];
[cba8bf34]178        byte_width >>= 6;
[36b4cd7]179
[cba8bf34]180        if (byte_width) {
[6e94014]181            unsigned int start_and_n = data[data_ch];
[cba8bf34]182            int n = (start_and_n & 15) + 1;
[6e94014]183            data_ch += n * byte_width + 1;
[36b4cd7]184        }
185    }
[cba8bf34]186}
187
188int
189BitmapFont::glyph_width(wxChar ch) const
190{
191#if SIZEOF_WXCHAR > 2
192    if (ch >= 0x10000) return 0;
193#endif
[7ada45b]194    if (!extra_chars)
[cba8bf34]195        init_extra_chars();
196
197    int width = 8;
198
[6e94014]199    int char_idx = extra_chars[ch - BITMAPFONT_MAX_CHAR];
200    if (char_idx >= 0) {
201        unsigned int byte_width = extra_data[char_idx];
[cba8bf34]202        width = (byte_width & 0x0f) + 2;
203    }
204
205    return width;
206}
207
208void
209BitmapFont::write_glyph(wxChar ch) const
210{
211#if SIZEOF_WXCHAR > 2
212    if (ch >= 0x10000) return;
213#endif
[7ada45b]214    if (!extra_chars)
[cba8bf34]215        init_extra_chars();
[36b4cd7]216
[d4d6909]217    unsigned int byte_width = 0;
[36b4cd7]218    int start = 0;
219    int n = 0;
220    int width = 8;
[d4d6909]221
[6e94014]222    int char_idx = extra_chars[ch - BITMAPFONT_MAX_CHAR];
223    const unsigned char * p = extra_data;
224    if (char_idx >= 0) {
225        p += char_idx;
[d4d6909]226        byte_width = *p++;
227        width = (byte_width & 0x0f) + 2;
228        byte_width >>= 6;
229
230        if (byte_width) {
231            unsigned int start_and_n = *p++;
232            start = start_and_n >> 4;
233            n = (start_and_n & 15) + 1;
234        }
[36b4cd7]235    }
236
237    // Even if there's nothing to display, we want to advance the
238    // raster position.
239    glBitmap(8 * byte_width, n, 0, -start, width, 0, p);
[614d60b]240    CHECK_GL_ERROR("BitmapFont::write_glyph", "glBitmap");
[36b4cd7]241}
242
[a1614eb]243void
244BitmapFont::write_string(const wxChar *s, size_t len) const
245{
[36b4cd7]246    if (!gllist_base) return;
[a1614eb]247    glListBase(gllist_base);
[30b66b5]248#if SIZEOF_WXCHAR == 1
249    call_lists(len, s);
250#elif SIZEOF_WXCHAR == 2 || SIZEOF_WXCHAR == 4
251    while (len) {
252        size_t n;
253        for (n = 0; n < len; ++n)
254            if (int(s[n]) >= BITMAPFONT_MAX_CHAR)
255                break;
256        call_lists(n, s);
257        s += n;
258        len -= n;
[c7627d4]259        while (len && int(*s) >= BITMAPFONT_MAX_CHAR) {
260            write_glyph(*s);
[30b66b5]261            ++s;
262            --len;
[a1614eb]263        }
264    }
[30b66b5]265#else
266# error "sizeof(wxChar) not 1, 2 or 4"
267#endif
[a1614eb]268}
Note: See TracBrowser for help on using the repository browser.