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

RELEASE/1.1RELEASE/1.2debug-cidebug-ci-sanitisersstereowalls-data
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
Line 
1//
2//  fnt.cc
3//
4//  Draw text using texture mapped fonts.
5//
6//  Copyright (C) 2003,2004,2006 Olly Betts
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//
26
27#include "fnt.h"
28
29#include <stdio.h>
30
31static bool isSwapped = false;
32
33inline unsigned char fnt_readByte(FILE *fd) {
34    return (unsigned char)getc(fd);
35}
36
37inline unsigned short fnt_readShort(FILE *fd) {
38    unsigned short x;
39    if (isSwapped) {
40        x = getc(fd) | (getc(fd) << 8);
41    } else {
42        x = (getc(fd) << 8) | getc(fd);
43    }
44    return x;
45}
46
47inline unsigned int fnt_readInt(FILE *fd) {
48    unsigned int x;
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    }
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) {
66        fprintf(stderr, "Failed to open '%s' for reading.\n", fname);
67        return false;
68    }
69
70    unsigned char magic[4];
71
72    if (fread(&magic, 4, 1, fd) != 1) {
73        fprintf(stderr, "'%s' an empty file!\n", fname);
74        return false;
75    }
76
77    if (memcmp(magic, "\xfftxf", 4) != 0) {
78        fprintf(stderr, "'%s' is not a 'txf' font file.\n", fname);
79        return false;
80    }
81
82    isSwapped = false;
83    int endianness = fnt_readInt(fd);
84
85    isSwapped = (endianness != 0x12345678);
86
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);
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
104    unsigned char *teximage = new unsigned char[ntexels];
105
106    switch (format) {
107        case FNT_BYTE_FORMAT: {
108            if ((int)fread(teximage, 1, ntexels, fd) != ntexels) {
109                delete [] teximage;
110                fprintf(stderr, "Premature EOF in '%s'.\n", fname);
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) {
123                delete [] texbitmap;
124                delete [] teximage;
125                fprintf(stderr, "Premature EOF in '%s'.\n", fname);
126                return false;
127            }
128
129            memset((void*)teximage, 0, ntexels);
130
131            for (i = 0; i < tex_height; ++i) {
132                for (j = 0; j < tex_width; ++j) {
133                    if (texbitmap[i * stride + (j >> 3)] & (1 << (j & 7))) {
134                        teximage[i * tex_width + j] = 0xff;
135                    }
136                }
137            }
138
139            delete [] texbitmap;
140            break;
141        }
142
143        default:
144            delete [] teximage;
145            fprintf(stderr, "Unrecognised format type in '%s'.\n", fname);
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);
157    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0 /* Border */,
158                 GL_ALPHA, GL_UNSIGNED_BYTE, (GLvoid *)teximage);
159    delete [] teximage;
160
161    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
162    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
163
164    fseek(fd, fpos, SEEK_SET);
165
166    for (i = 0; i < FNT_MAXCHAR; ++i) widths[i] = -1;
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) {
175        unsigned short ch = fnt_readShort(fd);
176        unsigned char w = fnt_readByte(fd);
177        if (w > max_w) max_w = w;
178        unsigned char h = fnt_readByte(fd);
179        int vtx_left = (signed char)fnt_readByte(fd);
180        // We can't handle lbearing and rbearing correctly so ignore them.
181        vtx_left = 0;
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);
187
188        if (ch < 32 || ch >= FNT_MAXCHAR) continue;
189
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;
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();
208            widths[ch] = w + 1;
209        } else {
210            widths[ch] = fnt_size / 2;
211        }
212        glTranslated(widths[ch], 0, 0);
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);
221        widths[(int)' '] = widths[(int)'n'];
222        glTranslated(widths[(int)' '], 0, 0);
223        glEndList();
224    }
225
226    fclose(fd);
227    return true;
228}
Note: See TracBrowser for help on using the repository browser.