8 * ***** BEGIN GPL LICENSE BLOCK *****
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License
12 * as published by the Free Software Foundation; either version 2
13 * of the License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
24 * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
25 * All rights reserved.
27 * The Original Code is: all of this file.
29 * Contributor(s): none yet.
31 * ***** END GPL LICENSE BLOCK *****
36 * Two external functions:
38 * void detectBitmapFont(ImBuf *ibuf)
39 * detects if an image buffer contains a bitmap font. It makes the
40 * specific bitmap data which is stored in the bitmap invisible to blender.
42 * void matrixGlyph(ImBuf * ibuf, unsigned short unicode, *float x 7)
43 * returns all the information about the character (unicode) in the floats
45 * Room for improvement:
46 * add kerning data in the bitmap
47 * all calculations in matrixGlyph() are static and could be done during
53 #include "MEM_guardedalloc.h"
54 #include "BLI_blenlib.h"
55 #include "BKE_global.h"
56 #include "IMB_imbuf_types.h"
58 #include "BKE_bmfont.h"
59 #include "BKE_bmfont_types.h"
65 void printfGlyph(bmGlyph * glyph)
67 printf("unicode: %d '%c'\n", glyph->unicode, glyph->unicode);
68 printf(" locx: %4d locy: %4d\n", glyph->locx, glyph->locy);
69 printf(" sizex: %3d sizey: %3d\n", glyph->sizex, glyph->sizey);
70 printf(" ofsx: %3d ofsy: %3d\n", glyph->ofsx, glyph->ofsy);
71 printf(" advan: %3d reser: %3d\n", glyph->advance, glyph->reserved);
74 #define MAX2(x,y) ( (x)>(y) ? (x) : (y) )
75 #define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) )
77 void calcAlpha(ImBuf * ibuf)
83 rect = (char *) ibuf->rect;
84 for (i = ibuf->x * ibuf->y ; i > 0 ; i--) {
85 rect[3] = MAX3(rect[0], rect[1], rect[2]);
91 void readBitmapFontVersion0(ImBuf * ibuf, unsigned char * rect, int step)
93 int glyphcount, bytes, i, index, linelength, ysize;
94 unsigned char * buffer;
97 linelength = ibuf->x * step;
99 glyphcount = (rect[6 * step] << 8) | rect[7 * step];
100 bytes = ((glyphcount - 1) * sizeof(bmGlyph)) + sizeof(bmFont);
102 ysize = (bytes + (ibuf->x - 1)) / ibuf->x;
104 if (ysize < ibuf->y) {
105 // we're first going to copy all data into a liniar buffer.
106 // step can be 4 or 1 bytes, and the data is not sequential because
107 // the bitmap was flipped vertically.
109 buffer = MEM_mallocN(bytes, "readBitmapFontVersion0:buffer");
112 for (i = 0; i < bytes; i++) {
113 buffer[i] = rect[index];
115 if (index >= linelength) {
116 // we've read one line, no skip to the line *before* that
122 // we're now going to endian convert the data
124 bmfont = MEM_mallocN(bytes, "readBitmapFontVersion0:bmfont");
127 // first read the header
128 bmfont->magic[0] = buffer[index++];
129 bmfont->magic[1] = buffer[index++];
130 bmfont->magic[2] = buffer[index++];
131 bmfont->magic[3] = buffer[index++];
132 bmfont->version = (buffer[index] << 8) | buffer[index + 1]; index += 2;
133 bmfont->glyphcount = (buffer[index] << 8) | buffer[index + 1]; index += 2;
134 bmfont->xsize = (buffer[index] << 8) | buffer[index + 1]; index += 2;
135 bmfont->ysize = (buffer[index] << 8) | buffer[index + 1]; index += 2;
137 for (i = 0; i < bmfont->glyphcount; i++) {
138 bmfont->glyphs[i].unicode = (buffer[index] << 8) | buffer[index + 1]; index += 2;
139 bmfont->glyphs[i].locx = (buffer[index] << 8) | buffer[index + 1]; index += 2;
140 bmfont->glyphs[i].locy = (buffer[index] << 8) | buffer[index + 1]; index += 2;
141 bmfont->glyphs[i].ofsx = buffer[index++];
142 bmfont->glyphs[i].ofsy = buffer[index++];
143 bmfont->glyphs[i].sizex = buffer[index++];
144 bmfont->glyphs[i].sizey = buffer[index++];
145 bmfont->glyphs[i].advance = buffer[index++];
146 bmfont->glyphs[i].reserved = buffer[index++];
148 printfGlyph(&bmfont->glyphs[i]);
155 printf("Oldy = %d Newy = %d\n", ibuf->y, ibuf->y - ysize);
156 printf("glyphcount = %d\n", glyphcount);
157 printf("bytes = %d\n", bytes);
160 // we've read the data from the image. Now we're going
161 // to crop the image vertically so only the bitmap data
165 ibuf->userdata = bmfont;
166 ibuf->userflags |= IB_BITMAPFONT;
168 if (ibuf->depth < 32) {
169 // we're going to fake alpha here:
173 printf("readBitmapFontVersion0: corrupted bitmapfont\n");
177 void detectBitmapFont(ImBuf *ibuf)
179 unsigned char * rect;
180 unsigned short version;
184 // bitmap must have an x size that is a power of two
185 if (is_power_of_two(ibuf->x)) {
186 rect = (unsigned char *) (ibuf->rect + (ibuf->x * (ibuf->y - 1)));
187 // printf ("starts with: %s %c %c %c %c\n", rect, rect[0], rect[1], rect[2], rect[3]);
188 if (rect[0] == 'B' && rect[1] == 'F' && rect[2] == 'N' && rect[3] == 'T') {
189 // printf("found 8bit font !\n");
191 // do the 8 bit font stuff. (not yet)
193 // we try all 4 possible combinations
194 for (i = 0; i < 4; i++) {
195 if (rect[0] == 'B' && rect[4] == 'F' && rect[8] == 'N' && rect[12] == 'T') {
196 // printf("found 24bit font !\n");
197 // We're going to parse the file:
199 version = (rect[16] << 8) | rect[20];
202 readBitmapFontVersion0(ibuf, rect, 4);
204 printf("detectBitmapFont :Unsupported version %d\n", version);
207 // on succes ibuf->userdata points to the bitmapfont
208 if (ibuf->userdata) {
219 int locateGlyph(bmFont *bmfont, unsigned short unicode)
221 int min, max, current = 0;
225 max = bmfont->glyphcount;
227 // look halfway for glyph
228 current = (min + max) >> 1;
230 if (bmfont->glyphs[current].unicode == unicode) {
232 } else if (bmfont->glyphs[current].unicode < unicode) {
240 if (max - min <= 1) {
241 // unable to locate glyph
251 void matrixGlyph(ImBuf * ibuf, unsigned short unicode,
252 float *centerx, float *centery,
253 float *sizex, float *sizey,
254 float *transx, float *transy,
255 float *movex, float *movey,
261 *centerx = *centery = 0.0;
262 *sizex = *sizey = 1.0;
263 *transx = *transy = 0.0;
264 *movex = *movey = 0.0;
268 bmfont = ibuf->userdata;
269 if (bmfont && (ibuf->userflags & IB_BITMAPFONT)) {
270 index = locateGlyph(bmfont, unicode);
273 *sizex = (bmfont->glyphs[index].sizex) / (float) (bmfont->glyphs[0].sizex);
274 *sizey = (bmfont->glyphs[index].sizey) / (float) (bmfont->glyphs[0].sizey);
276 *transx = bmfont->glyphs[index].locx / (float) ibuf->x;
277 *transy = (ibuf->y - bmfont->glyphs[index].locy) / (float) ibuf->y;
279 *centerx = bmfont->glyphs[0].locx / (float) ibuf->x;
280 *centery = (ibuf->y - bmfont->glyphs[0].locy) / (float) ibuf->y;
282 // 2.0 units is the default size of an object
284 *movey = 1.0f - *sizey + 2.0f * (bmfont->glyphs[index].ofsy - bmfont->glyphs[0].ofsy) / (float) bmfont->glyphs[0].sizey;
285 *movex = *sizex - 1.0f + 2.0f * (bmfont->glyphs[index].ofsx - bmfont->glyphs[0].ofsx) / (float) bmfont->glyphs[0].sizex;
287 *advance = 2.0f * bmfont->glyphs[index].advance / (float) bmfont->glyphs[0].advance;
289 // printfGlyph(&bmfont->glyphs[index]);
290 // printf("%c %d %0.5f %0.5f %0.5f %0.5f %0.5f \n", unicode, index, *sizex, *sizey, *transx, *transy, *advance);