source: git/src/fnt.cc @ e02a6a6

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

configure.in,src/: Define GETC() in config.h and use it everywhere.
Similarly define PUTC() to use putc_unlocked() where available and
use that everywhere too.

git-svn-id: file:///home/survex-svn/survex/trunk@3550 4b37db11-9a0c-4f06-9ece-9ab7cdaee568

  • Property mode set to 100644
File size: 6.0 KB
RevLine 
[6199d17]1//
2//  fnt.cc
3//
4//  Draw text using texture mapped fonts.
5//
[ecc16fc]6//  Copyright (C) 2003,2004,2006,2010 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
[ecbc6c18]24//  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
[6199d17]25//
[1eeb55a]26
[e02a6a6]27#ifdef HAVE_CONFIG_H
28# include <config.h>
29#endif
30
[1eeb55a]31#include "fnt.h"
32
33#include <stdio.h>
34
35static bool isSwapped = false;
36
[5b13e4c]37inline unsigned char fnt_readByte(FILE *fd) {
[e02a6a6]38    return (unsigned char)GETC(fd);
[1eeb55a]39}
40
[5b13e4c]41inline unsigned short fnt_readShort(FILE *fd) {
[1eeb55a]42    unsigned short x;
[deeebad]43    if (isSwapped) {
[e02a6a6]44        x = GETC(fd) | (GETC(fd) << 8);
[deeebad]45    } else {
[e02a6a6]46        x = (GETC(fd) << 8) | GETC(fd);
[deeebad]47    }
[1eeb55a]48    return x;
49}
50
[5b13e4c]51inline unsigned int fnt_readInt(FILE *fd) {
[1eeb55a]52    unsigned int x;
[deeebad]53    if (isSwapped) {
[e02a6a6]54        x = GETC(fd) | (GETC(fd) << 8) | (GETC(fd) << 16) | (GETC(fd) << 24);
[deeebad]55    } else {
[e02a6a6]56        x = (GETC(fd) << 24) | (GETC(fd) << 16) | (GETC(fd) << 8) | GETC(fd);
[deeebad]57    }
[1eeb55a]58    return x;
59}
60
61#define FNT_BYTE_FORMAT         0
62#define FNT_BITMAP_FORMAT       1
63
64bool
65fntTexFont::load(const char *fname)
66{
67    FILE *fd;
68
69    if ((fd = fopen(fname, "rb")) == NULL) {
[bd551c0]70        fprintf(stderr, "Failed to open '%s' for reading.\n", fname);
[1eeb55a]71        return false;
72    }
73
74    unsigned char magic[4];
75
[deeebad]76    if (fread(&magic, 4, 1, fd) != 1) {
[bd551c0]77        fprintf(stderr, "'%s' an empty file!\n", fname);
[1eeb55a]78        return false;
79    }
80
[deeebad]81    if (memcmp(magic, "\xfftxf", 4) != 0) {
[bd551c0]82        fprintf(stderr, "'%s' is not a 'txf' font file.\n", fname);
[1eeb55a]83        return false;
84    }
85
86    isSwapped = false;
[5b13e4c]87    int endianness = fnt_readInt(fd);
[1eeb55a]88
89    isSwapped = (endianness != 0x12345678);
90
[5b13e4c]91    int format      = fnt_readInt(fd);
92    int tex_width   = fnt_readInt(fd);
93    int tex_height  = fnt_readInt(fd);
[c57bd20]94    fnt_size = fnt_readInt(fd);
95    fnt_size += fnt_size >> 2;
[5b13e4c]96    /* int unknown = */ fnt_readInt(fd);
97    int num_glyphs  = fnt_readInt(fd);
[1eeb55a]98    list_base = glGenLists(256 - 32) - 32;
99
100    int i, j;
101
102    // Skip the glyph info first so we can set up the texture, then create
103    // display lists from it using the glyph info
104    int fpos = ftell(fd);
105    fseek(fd, num_glyphs * 12, SEEK_CUR);
106    // Load the image part of the file
107    int ntexels = tex_width * tex_height;
108
[885f73f]109    unsigned char *teximage = new unsigned char[ntexels];
[1eeb55a]110
111    switch (format) {
112        case FNT_BYTE_FORMAT: {
[885f73f]113            if ((int)fread(teximage, 1, ntexels, fd) != ntexels) {
114                delete [] teximage;
[bd551c0]115                fprintf(stderr, "Premature EOF in '%s'.\n", fname);
[1eeb55a]116                return false;
117            }
118            break;
119        }
120
121        case FNT_BITMAP_FORMAT: {
122            int stride = (tex_width + 7) >> 3;
123
124            unsigned char *texbitmap = new unsigned char[stride * tex_height];
125
126            if ((int)fread(texbitmap, 1, stride * tex_height, fd)
127                    != stride * tex_height) {
[885f73f]128                delete [] texbitmap;
129                delete [] teximage;
[bd551c0]130                fprintf(stderr, "Premature EOF in '%s'.\n", fname);
[1eeb55a]131                return false;
132            }
133
[885f73f]134            memset((void*)teximage, 0, ntexels);
[1eeb55a]135
[5b13e4c]136            for (i = 0; i < tex_height; ++i) {
137                for (j = 0; j < tex_width; ++j) {
[1eeb55a]138                    if (texbitmap[i * stride + (j >> 3)] & (1 << (j & 7))) {
[5f4a155]139                        teximage[i * tex_width + j] = 0xff;
[1eeb55a]140                    }
[5b13e4c]141                }
142            }
[1eeb55a]143
144            delete [] texbitmap;
145            break;
146        }
147
148        default:
[885f73f]149            delete [] teximage;
[bd551c0]150            fprintf(stderr, "Unrecognised format type in '%s'.\n", fname);
[1eeb55a]151            return false;
152    }
153    glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
154
155    glGenTextures(1, & texture);
156    glBindTexture(GL_TEXTURE_2D, texture);
157
158    glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
159
160    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
161    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
[5f4a155]162    glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, tex_width, tex_height, 0 /* Border */,
163                 GL_ALPHA, 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    for (i = 0; i < num_glyphs; ++i) {
[5b13e4c]179        unsigned short ch = fnt_readShort(fd);
180        unsigned char w = fnt_readByte(fd);
[1eeb55a]181        if (w > max_w) max_w = w;
[5b13e4c]182        unsigned char h = fnt_readByte(fd);
183        int vtx_left = (signed char)fnt_readByte(fd);
184        int vtx_bot = (signed char)fnt_readByte(fd);
[ecc16fc]185        signed char step = fnt_readByte(fd);
[5b13e4c]186        /* signed char unknown =*/ fnt_readByte(fd);
187        short x = fnt_readShort(fd);
188        short y = fnt_readShort(fd);
[1eeb55a]189
[aa048c3]190        if (ch < 32 || ch >= FNT_MAXCHAR) continue;
[5b13e4c]191
[1eeb55a]192        float tex_left = x * W;
193        float tex_right = (x + w) * W;
194        float tex_bot = y * H;
195        float tex_top = (y + h) * H;
196        int vtx_right = vtx_left + w;
197        int vtx_top = vtx_bot + h;
[5b13e4c]198        glNewList(list_base + ch, GL_COMPILE);
199        if (w != 0 && h != 0) {
200            glBegin(GL_QUADS);
201            glTexCoord2f(tex_left, tex_bot);
202            glVertex2i(vtx_left, vtx_bot);
203            glTexCoord2f(tex_right, tex_bot);
204            glVertex2i(vtx_right, vtx_bot);
205            glTexCoord2f(tex_right, tex_top);
206            glVertex2i(vtx_right, vtx_top);
207            glTexCoord2f(tex_left, tex_top);
208            glVertex2i(vtx_left, vtx_top);
209            glEnd();
210        }
[ecc16fc]211        widths[ch] = step;
[5b13e4c]212        glTranslated(widths[ch], 0, 0);
[1eeb55a]213        glEndList();
214    }
215
216    if (widths[(int)' '] == -1) {
217        glNewList(list_base + ' ', GL_COMPILE);
[0e21a58]218        widths[(int)' '] = widths[(int)'n'];
[5b13e4c]219        glTranslated(widths[(int)' '], 0, 0);
[1eeb55a]220        glEndList();
221    }
222
223    fclose(fd);
224    return true;
225}
Note: See TracBrowser for help on using the repository browser.