source: git/src/fnt.cc @ ae68e7b

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

Remove now superfluous ().

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

  • Property mode set to 100644
File size: 6.4 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))) {
[ae68e7b]134                        teximage[i * tex_width + j] = 1;
[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);
[eaaa55b]157    static const GLuint map[2] = { 0, 0xffffffff };
[885f73f]158    glPixelMapuiv(GL_PIXEL_MAP_I_TO_A, 2, map);
159    glPixelMapuiv(GL_PIXEL_MAP_I_TO_R, 2, map);
160    glPixelMapuiv(GL_PIXEL_MAP_I_TO_G, 2, map);
161    glPixelMapuiv(GL_PIXEL_MAP_I_TO_B, 2, map);
162    glTexImage2D(GL_TEXTURE_2D, 0, 4, tex_width, tex_height, 0 /* Border */,
163                 GL_COLOR_INDEX, GL_UNSIGNED_BYTE, (GLvoid *)teximage);
[1eeb55a]164    delete [] teximage;
165
[096e56c]166    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
[1dda087]167    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
168
[1eeb55a]169    fseek(fd, fpos, SEEK_SET);
170
[aa048c3]171    for (i = 0; i < FNT_MAXCHAR; ++i) widths[i] = -1;
[1eeb55a]172
173    // Load the glyph array
174
175    float W = 1.0f / (float)tex_width;
176    float H = 1.0f / (float)tex_height;
177    unsigned char max_w = 0;
178    int u = 0, d = 0;
179    for (i = 0; i < num_glyphs; ++i) {
[5b13e4c]180        unsigned short ch = fnt_readShort(fd);
181        unsigned char w = fnt_readByte(fd);
[1eeb55a]182        if (w > max_w) max_w = w;
[5b13e4c]183        unsigned char h = fnt_readByte(fd);
184        int vtx_left = (signed char)fnt_readByte(fd);
[0e21a58]185        // We can't handle lbearing and rbearing correctly so ignore them.
186        vtx_left = 0;
[5b13e4c]187        int vtx_bot = (signed char)fnt_readByte(fd);
188        /* signed char step =*/ fnt_readByte(fd);
189        /* signed char unknown =*/ fnt_readByte(fd);
190        short x = fnt_readShort(fd);
191        short y = fnt_readShort(fd);
[1eeb55a]192
[aa048c3]193        if (ch < 32 || ch >= FNT_MAXCHAR) continue;
[5b13e4c]194
[1eeb55a]195        float tex_left = x * W;
196        float tex_right = (x + w) * W;
197        float tex_bot = y * H;
198        float tex_top = (y + h) * H;
199        int vtx_right = vtx_left + w;
200        int vtx_top = vtx_bot + h;
[5b13e4c]201        glNewList(list_base + ch, GL_COMPILE);
202        if (w != 0 && h != 0) {
203            glBegin(GL_QUADS);
204            glTexCoord2f(tex_left, tex_bot);
205            glVertex2i(vtx_left, vtx_bot);
206            glTexCoord2f(tex_right, tex_bot);
207            glVertex2i(vtx_right, vtx_bot);
208            glTexCoord2f(tex_right, tex_top);
209            glVertex2i(vtx_right, vtx_top);
210            glTexCoord2f(tex_left, tex_top);
211            glVertex2i(vtx_left, vtx_top);
212            glEnd();
[0e21a58]213            widths[ch] = w + 1;
[5b13e4c]214        } else {
215            widths[ch] = fnt_size / 2;
216        }
217        glTranslated(widths[ch], 0, 0);
[1eeb55a]218        glEndList();
219        if (vtx_bot < d) d = vtx_bot;
220        if (vtx_top > u) u = vtx_top;
221    }
222    fnt_size = u - d;
223
224    if (widths[(int)' '] == -1) {
225        glNewList(list_base + ' ', GL_COMPILE);
[0e21a58]226        widths[(int)' '] = widths[(int)'n'];
[5b13e4c]227        glTranslated(widths[(int)' '], 0, 0);
[1eeb55a]228        glEndList();
229    }
230
231    fclose(fd);
232    return true;
233}
Note: See TracBrowser for help on using the repository browser.