source: git/src/fnt.cc @ 5f4a155

RELEASE/1.1RELEASE/1.2debug-cidebug-ci-sanitisersstereowalls-datawalls-data-hanging-as-warning
Last change on this file since 5f4a155 was 5f4a155, checked in by Olly Betts <olly@…>, 14 years ago

src/fnt.cc: Change back to not using GL_COLOR_INDEX, but with still
being able to set the font texture from a byte array.

git-svn-id: file:///home/survex-svn/survex/branches/survex-1_1@3402 4b37db11-9a0c-4f06-9ece-9ab7cdaee568

  • Property mode set to 100644
File size: 6.1 KB
RevLine 
[6199d17]1//
2//  fnt.cc
3//
4//  Draw text using texture mapped fonts.
5//
[0e21a58]6//  Copyright (C) 2003,2004,2006 Olly Betts
[6199d17]7//
8//     Based on code from PLIB - http://plib.sourceforge.net
9//     Copyright (C) 1998,2002  Steve Baker
10//     Relicensed under the GNU GPL as permitted by the GNU LGPL
11//
12//  This program is free software; you can redistribute it and/or modify
13//  it under the terms of the GNU General Public License as published by
14//  the Free Software Foundation; either version 2 of the License, or
15//  (at your option) any later version.
16//
17//  This program is distributed in the hope that it will be useful,
18//  but WITHOUT ANY WARRANTY; without even the implied warranty of
19//  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20//  GNU General Public License for more details.
21//
22//  You should have received a copy of the GNU General Public License
23//  along with this program; if not, write to the Free Software
24//  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
25//
[1eeb55a]26
27#include "fnt.h"
28
29#include <stdio.h>
30
31static bool isSwapped = false;
32
[5b13e4c]33inline unsigned char fnt_readByte(FILE *fd) {
[1eeb55a]34    return (unsigned char)getc(fd);
35}
36
[5b13e4c]37inline unsigned short fnt_readShort(FILE *fd) {
[1eeb55a]38    unsigned short x;
[deeebad]39    if (isSwapped) {
40        x = getc(fd) | (getc(fd) << 8);
41    } else {
42        x = (getc(fd) << 8) | getc(fd);
43    }
[1eeb55a]44    return x;
45}
46
[5b13e4c]47inline unsigned int fnt_readInt(FILE *fd) {
[1eeb55a]48    unsigned int x;
[deeebad]49    if (isSwapped) {
50        x = getc(fd) | (getc(fd) << 8) | (getc(fd) << 16) | (getc(fd) << 24);
51    } else {
52        x = (getc(fd) << 24) | (getc(fd) << 16) | (getc(fd) << 8) | getc(fd);
53    }
[1eeb55a]54    return x;
55}
56
57#define FNT_BYTE_FORMAT         0
58#define FNT_BITMAP_FORMAT       1
59
60bool
61fntTexFont::load(const char *fname)
62{
63    FILE *fd;
64
65    if ((fd = fopen(fname, "rb")) == NULL) {
[bd551c0]66        fprintf(stderr, "Failed to open '%s' for reading.\n", fname);
[1eeb55a]67        return false;
68    }
69
70    unsigned char magic[4];
71
[deeebad]72    if (fread(&magic, 4, 1, fd) != 1) {
[bd551c0]73        fprintf(stderr, "'%s' an empty file!\n", fname);
[1eeb55a]74        return false;
75    }
76
[deeebad]77    if (memcmp(magic, "\xfftxf", 4) != 0) {
[bd551c0]78        fprintf(stderr, "'%s' is not a 'txf' font file.\n", fname);
[1eeb55a]79        return false;
80    }
81
82    isSwapped = false;
[5b13e4c]83    int endianness = fnt_readInt(fd);
[1eeb55a]84
85    isSwapped = (endianness != 0x12345678);
86
[5b13e4c]87    int format      = fnt_readInt(fd);
88    int tex_width   = fnt_readInt(fd);
89    int tex_height  = fnt_readInt(fd);
90    /* int max_height = */ fnt_readInt(fd);
91    /* int unknown = */ fnt_readInt(fd);
92    int num_glyphs  = fnt_readInt(fd);
[1eeb55a]93    list_base = glGenLists(256 - 32) - 32;
94
95    int i, j;
96
97    // Skip the glyph info first so we can set up the texture, then create
98    // display lists from it using the glyph info
99    int fpos = ftell(fd);
100    fseek(fd, num_glyphs * 12, SEEK_CUR);
101    // Load the image part of the file
102    int ntexels = tex_width * tex_height;
103
[885f73f]104    unsigned char *teximage = new unsigned char[ntexels];
[1eeb55a]105
106    switch (format) {
107        case FNT_BYTE_FORMAT: {
[885f73f]108            if ((int)fread(teximage, 1, ntexels, fd) != ntexels) {
109                delete [] teximage;
[bd551c0]110                fprintf(stderr, "Premature EOF in '%s'.\n", fname);
[1eeb55a]111                return false;
112            }
113            break;
114        }
115
116        case FNT_BITMAP_FORMAT: {
117            int stride = (tex_width + 7) >> 3;
118
119            unsigned char *texbitmap = new unsigned char[stride * tex_height];
120
121            if ((int)fread(texbitmap, 1, stride * tex_height, fd)
122                    != stride * tex_height) {
[885f73f]123                delete [] texbitmap;
124                delete [] teximage;
[bd551c0]125                fprintf(stderr, "Premature EOF in '%s'.\n", fname);
[1eeb55a]126                return false;
127            }
128
[885f73f]129            memset((void*)teximage, 0, ntexels);
[1eeb55a]130
[5b13e4c]131            for (i = 0; i < tex_height; ++i) {
132                for (j = 0; j < tex_width; ++j) {
[1eeb55a]133                    if (texbitmap[i * stride + (j >> 3)] & (1 << (j & 7))) {
[5f4a155]134                        teximage[i * tex_width + j] = 0xff;
[1eeb55a]135                    }
[5b13e4c]136                }
137            }
[1eeb55a]138
139            delete [] texbitmap;
140            break;
141        }
142
143        default:
[885f73f]144            delete [] teximage;
[bd551c0]145            fprintf(stderr, "Unrecognised format type in '%s'.\n", fname);
[1eeb55a]146            return false;
147    }
148    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
149
150    glGenTextures(1, & texture);
151    glBindTexture(GL_TEXTURE_2D, texture);
152
153    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
154
155    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
156    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
[5f4a155]157    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0 /* Border */,
158                 GL_ALPHA, GL_UNSIGNED_BYTE, (GLvoid *)teximage);
[1eeb55a]159    delete [] teximage;
160
[096e56c]161    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
[1dda087]162    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
163
[1eeb55a]164    fseek(fd, fpos, SEEK_SET);
165
[aa048c3]166    for (i = 0; i < FNT_MAXCHAR; ++i) widths[i] = -1;
[1eeb55a]167
168    // Load the glyph array
169
170    float W = 1.0f / (float)tex_width;
171    float H = 1.0f / (float)tex_height;
172    unsigned char max_w = 0;
173    int u = 0, d = 0;
174    for (i = 0; i < num_glyphs; ++i) {
[5b13e4c]175        unsigned short ch = fnt_readShort(fd);
176        unsigned char w = fnt_readByte(fd);
[1eeb55a]177        if (w > max_w) max_w = w;
[5b13e4c]178        unsigned char h = fnt_readByte(fd);
179        int vtx_left = (signed char)fnt_readByte(fd);
[0e21a58]180        // We can't handle lbearing and rbearing correctly so ignore them.
181        vtx_left = 0;
[5b13e4c]182        int vtx_bot = (signed char)fnt_readByte(fd);
183        /* signed char step =*/ fnt_readByte(fd);
184        /* signed char unknown =*/ fnt_readByte(fd);
185        short x = fnt_readShort(fd);
186        short y = fnt_readShort(fd);
[1eeb55a]187
[aa048c3]188        if (ch < 32 || ch >= FNT_MAXCHAR) continue;
[5b13e4c]189
[1eeb55a]190        float tex_left = x * W;
191        float tex_right = (x + w) * W;
192        float tex_bot = y * H;
193        float tex_top = (y + h) * H;
194        int vtx_right = vtx_left + w;
195        int vtx_top = vtx_bot + h;
[5b13e4c]196        glNewList(list_base + ch, GL_COMPILE);
197        if (w != 0 && h != 0) {
198            glBegin(GL_QUADS);
199            glTexCoord2f(tex_left, tex_bot);
200            glVertex2i(vtx_left, vtx_bot);
201            glTexCoord2f(tex_right, tex_bot);
202            glVertex2i(vtx_right, vtx_bot);
203            glTexCoord2f(tex_right, tex_top);
204            glVertex2i(vtx_right, vtx_top);
205            glTexCoord2f(tex_left, tex_top);
206            glVertex2i(vtx_left, vtx_top);
207            glEnd();
[0e21a58]208            widths[ch] = w + 1;
[5b13e4c]209        } else {
210            widths[ch] = fnt_size / 2;
211        }
212        glTranslated(widths[ch], 0, 0);
[1eeb55a]213        glEndList();
214        if (vtx_bot < d) d = vtx_bot;
215        if (vtx_top > u) u = vtx_top;
216    }
217    fnt_size = u - d;
218
219    if (widths[(int)' '] == -1) {
220        glNewList(list_base + ' ', GL_COMPILE);
[0e21a58]221        widths[(int)' '] = widths[(int)'n'];
[5b13e4c]222        glTranslated(widths[(int)' '], 0, 0);
[1eeb55a]223        glEndList();
224    }
225
226    fclose(fd);
227    return true;
228}
Note: See TracBrowser for help on using the repository browser.