source: git/src/fnt.cc @ c57bd20

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

src/fnt.cc: Use font size from txf file rather than trying to
calculate it from the texture fragment sizes.

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

  • Property mode set to 100644
File size: 5.9 KB
Line 
1//
2//  fnt.cc
3//
4//  Draw text using texture mapped fonts.
5//
6//  Copyright (C) 2003,2004,2006,2010 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    fnt_size = fnt_readInt(fd);
91    fnt_size += fnt_size >> 2;
92    /* int unknown = */ fnt_readInt(fd);
93    int num_glyphs  = fnt_readInt(fd);
94    list_base = glGenLists(256 - 32) - 32;
95
96    int i, j;
97
98    // Skip the glyph info first so we can set up the texture, then create
99    // display lists from it using the glyph info
100    int fpos = ftell(fd);
101    fseek(fd, num_glyphs * 12, SEEK_CUR);
102    // Load the image part of the file
103    int ntexels = tex_width * tex_height;
104
105    unsigned char *teximage = new unsigned char[ntexels];
106
107    switch (format) {
108        case FNT_BYTE_FORMAT: {
109            if ((int)fread(teximage, 1, ntexels, fd) != ntexels) {
110                delete [] teximage;
111                fprintf(stderr, "Premature EOF in '%s'.\n", fname);
112                return false;
113            }
114            break;
115        }
116
117        case FNT_BITMAP_FORMAT: {
118            int stride = (tex_width + 7) >> 3;
119
120            unsigned char *texbitmap = new unsigned char[stride * tex_height];
121
122            if ((int)fread(texbitmap, 1, stride * tex_height, fd)
123                    != stride * tex_height) {
124                delete [] texbitmap;
125                delete [] teximage;
126                fprintf(stderr, "Premature EOF in '%s'.\n", fname);
127                return false;
128            }
129
130            memset((void*)teximage, 0, ntexels);
131
132            for (i = 0; i < tex_height; ++i) {
133                for (j = 0; j < tex_width; ++j) {
134                    if (texbitmap[i * stride + (j >> 3)] & (1 << (j & 7))) {
135                        teximage[i * tex_width + j] = 0xff;
136                    }
137                }
138            }
139
140            delete [] texbitmap;
141            break;
142        }
143
144        default:
145            delete [] teximage;
146            fprintf(stderr, "Unrecognised format type in '%s'.\n", fname);
147            return false;
148    }
149    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
150
151    glGenTextures(1, & texture);
152    glBindTexture(GL_TEXTURE_2D, texture);
153
154    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
155
156    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
157    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
158    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0 /* Border */,
159                 GL_ALPHA, GL_UNSIGNED_BYTE, (GLvoid *)teximage);
160    delete [] teximage;
161
162    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
163    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
164
165    fseek(fd, fpos, SEEK_SET);
166
167    for (i = 0; i < FNT_MAXCHAR; ++i) widths[i] = -1;
168
169    // Load the glyph array
170
171    float W = 1.0f / (float)tex_width;
172    float H = 1.0f / (float)tex_height;
173    unsigned char max_w = 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        int vtx_bot = (signed char)fnt_readByte(fd);
181        signed char step = fnt_readByte(fd);
182        /* signed char unknown =*/ fnt_readByte(fd);
183        short x = fnt_readShort(fd);
184        short y = fnt_readShort(fd);
185
186        if (ch < 32 || ch >= FNT_MAXCHAR) continue;
187
188        float tex_left = x * W;
189        float tex_right = (x + w) * W;
190        float tex_bot = y * H;
191        float tex_top = (y + h) * H;
192        int vtx_right = vtx_left + w;
193        int vtx_top = vtx_bot + h;
194        glNewList(list_base + ch, GL_COMPILE);
195        if (w != 0 && h != 0) {
196            glBegin(GL_QUADS);
197            glTexCoord2f(tex_left, tex_bot);
198            glVertex2i(vtx_left, vtx_bot);
199            glTexCoord2f(tex_right, tex_bot);
200            glVertex2i(vtx_right, vtx_bot);
201            glTexCoord2f(tex_right, tex_top);
202            glVertex2i(vtx_right, vtx_top);
203            glTexCoord2f(tex_left, tex_top);
204            glVertex2i(vtx_left, vtx_top);
205            glEnd();
206        }
207        widths[ch] = step;
208        glTranslated(widths[ch], 0, 0);
209        glEndList();
210    }
211
212    if (widths[(int)' '] == -1) {
213        glNewList(list_base + ' ', GL_COMPILE);
214        widths[(int)' '] = widths[(int)'n'];
215        glTranslated(widths[(int)' '], 0, 0);
216        glEndList();
217    }
218
219    fclose(fd);
220    return true;
221}
Note: See TracBrowser for help on using the repository browser.