From 12315f4d0e0ae993805f141f64cb8c73c5297311 Mon Sep 17 00:00:00 2001 From: Hans Lambermont Date: Sat, 12 Oct 2002 11:37:38 +0000 Subject: Initial revision --- source/blender/blenkernel/intern/bmfont.c | 293 ++++++++++++++++++++++++++++++ 1 file changed, 293 insertions(+) create mode 100644 source/blender/blenkernel/intern/bmfont.c (limited to 'source/blender/blenkernel/intern/bmfont.c') diff --git a/source/blender/blenkernel/intern/bmfont.c b/source/blender/blenkernel/intern/bmfont.c new file mode 100644 index 00000000000..c5c4221a076 --- /dev/null +++ b/source/blender/blenkernel/intern/bmfont.c @@ -0,0 +1,293 @@ +/** + * bmfont.c + * + * 04-10-2000 frank + * + * $Id$ + * + * ***** BEGIN GPL/BL DUAL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. The Blender + * Foundation also sells licenses for use in proprietary software under + * the Blender License. See http://www.blender.org/BL/ for information + * about this. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV. + * All rights reserved. + * + * The Original Code is: all of this file. + * + * Contributor(s): none yet. + * + * ***** END GPL/BL DUAL LICENSE BLOCK ***** + * + */ + +/** + * Two external functions: + * + * void detectBitmapFont(ImBuf *ibuf) + * detects if an image buffer contains a bitmap font. It makes the + * specific bitmap data which is stored in the bitmap invisible to blender. + * + * void matrixGlyph(ImBuf * ibuf, unsigned short unicode, *float x 7) + * returns all the information about the character (unicode) in the floats + * + * Room for improvement: + * add kerning data in the bitmap + * all calculations in matrixGlyph() are static and could be done during + * initialization + */ + +#include + +#include "MEM_guardedalloc.h" +#include "BLI_blenlib.h" +#include "BKE_global.h" +#include "IMB_imbuf_types.h" + +#include "BKE_bmfont.h" +#include "BKE_bmfont_types.h" + +void printfGlyph(bmGlyph * glyph) +{ + printf("unicode: %d '%c'\n", glyph->unicode, glyph->unicode); + printf(" locx: %4d locy: %4d\n", glyph->locx, glyph->locy); + printf(" sizex: %3d sizey: %3d\n", glyph->sizex, glyph->sizey); + printf(" ofsx: %3d ofsy: %3d\n", glyph->ofsx, glyph->ofsy); + printf(" advan: %3d reser: %3d\n", glyph->advance, glyph->reserved); +} + +#define MAX2(x,y) ( (x)>(y) ? (x) : (y) ) +#define MAX3(x,y,z) MAX2( MAX2((x),(y)) , (z) ) + +void calcAlpha(ImBuf * ibuf) +{ + int i; + char * rect; + + if (ibuf) { + rect = (char *) ibuf->rect; + for (i = ibuf->x * ibuf->y ; i > 0 ; i--) { + rect[3] = MAX3(rect[0], rect[1], rect[2]); + rect += 4; + } + } +} + +void readBitmapFontVersion0(ImBuf * ibuf, unsigned char * rect, int step) +{ + int glyphcount, bytes, i, index, linelength, ysize; + unsigned char * buffer; + bmFont * bmfont; + + linelength = ibuf->x * step; + + glyphcount = (rect[6 * step] << 8) | rect[7 * step]; + bytes = ((glyphcount - 1) * sizeof(bmGlyph)) + sizeof(bmFont); + + ysize = (bytes + (ibuf->x - 1)) / ibuf->x; + + if (ysize < ibuf->y) { + // we're first going to copy all data into a liniar buffer. + // step can be 4 or 1 bytes, and the data is not sequential because + // the bitmap was flipped vertically. + + buffer = MEM_mallocN(bytes, "readBitmapFontVersion0:buffer"); + + index = 0; + for (i = 0; i < bytes; i++) { + buffer[i] = rect[index]; + index += step; + if (index >= linelength) { + // we've read one line, no skip to the line *before* that + rect -= linelength; + index -= linelength; + } + } + + // we're now going to endian convert the data + + bmfont = MEM_mallocN(bytes, "readBitmapFontVersion0:bmfont"); + index = 0; + + // first read the header + bmfont->magic[0] = buffer[index++]; + bmfont->magic[1] = buffer[index++]; + bmfont->magic[2] = buffer[index++]; + bmfont->magic[3] = buffer[index++]; + bmfont->version = (buffer[index] << 8) | buffer[index + 1]; index += 2; + bmfont->glyphcount = (buffer[index] << 8) | buffer[index + 1]; index += 2; + bmfont->xsize = (buffer[index] << 8) | buffer[index + 1]; index += 2; + bmfont->ysize = (buffer[index] << 8) | buffer[index + 1]; index += 2; + + for (i = 0; i < bmfont->glyphcount; i++) { + bmfont->glyphs[i].unicode = (buffer[index] << 8) | buffer[index + 1]; index += 2; + bmfont->glyphs[i].locx = (buffer[index] << 8) | buffer[index + 1]; index += 2; + bmfont->glyphs[i].locy = (buffer[index] << 8) | buffer[index + 1]; index += 2; + bmfont->glyphs[i].ofsx = buffer[index++]; + bmfont->glyphs[i].ofsy = buffer[index++]; + bmfont->glyphs[i].sizex = buffer[index++]; + bmfont->glyphs[i].sizey = buffer[index++]; + bmfont->glyphs[i].advance = buffer[index++]; + bmfont->glyphs[i].reserved = buffer[index++]; + if (G.f & G_DEBUG) { + printfGlyph(&bmfont->glyphs[i]); + } + } + + MEM_freeN(buffer); + + if (G.f & G_DEBUG) { + printf("Oldy = %d Newy = %d\n", ibuf->y, ibuf->y - ysize); + printf("glyphcount = %d\n", glyphcount); + printf("bytes = %d\n", bytes); + } + + // we've read the data from the image. Now we're going + // to crop the image vertically so only the bitmap data + // remains visible + + ibuf->y -= ysize; + ibuf->userdata = bmfont; + ibuf->userflags |= IB_BITMAPFONT; + + if (ibuf->depth < 32) { + // we're going to fake alpha here: + calcAlpha(ibuf); + } + } else { + printf("readBitmapFontVersion0: corrupted bitmapfont\n"); + } +} + +void detectBitmapFont(ImBuf *ibuf) +{ + unsigned char * rect; + unsigned short version; + long i; + + if (ibuf != NULL) { + // bitmap must have an x size that is a power of two + if (is_power_of_two(ibuf->x)) { + rect = (unsigned char *) (ibuf->rect + (ibuf->x * (ibuf->y - 1))); + // printf ("starts with: %s %c %c %c %c\n", rect, rect[0], rect[1], rect[2], rect[3]); + if (rect[0] == 'B' && rect[1] == 'F' && rect[2] == 'N' && rect[3] == 'T') { + // printf("found 8bit font !\n"); + // round y size down + // do the 8 bit font stuff. (not yet) + } else { + // we try all 4 possible combinations + for (i = 0; i < 4; i++) { + if (rect[0] == 'B' && rect[4] == 'F' && rect[8] == 'N' && rect[12] == 'T') { + // printf("found 24bit font !\n"); + // We're going to parse the file: + + version = (rect[16] << 8) | rect[20]; + + if (version == 0) { + readBitmapFontVersion0(ibuf, rect, 4); + } else { + printf("detectBitmapFont :Unsupported version %d\n", version); + } + + // on succes ibuf->userdata points to the bitmapfont + if (ibuf->userdata) { + break; + } + } + rect++; + } + } + } + } +} + +int locateGlyph(bmFont *bmfont, unsigned short unicode) +{ + int min, max, current = 0; + + if (bmfont) { + min = 0; + max = bmfont->glyphcount; + while (1) { + // look halfway for glyph + current = (min + max) >> 1; + + if (bmfont->glyphs[current].unicode == unicode) { + break; + } else if (bmfont->glyphs[current].unicode < unicode) { + // have to move up + min = current; + } else { + // have to move down + max = current; + } + + if (max - min <= 1) { + // unable to locate glyph + current = 0; + break; + } + } + } + + return(current); +} + +void matrixGlyph(ImBuf * ibuf, unsigned short unicode, + float *centerx, float *centery, + float *sizex, float *sizey, + float *transx, float *transy, + float *movex, float *movey, + float *advance) +{ + int index; + bmFont *bmfont; + + *centerx = *centery = 0.0; + *sizex = *sizey = 1.0; + *transx = *transy = 0.0; + *movex = *movey = 0.0; + *advance = 1.0; + + if (ibuf) { + bmfont = ibuf->userdata; + if (bmfont && (ibuf->userflags & IB_BITMAPFONT)) { + index = locateGlyph(bmfont, unicode); + if (index) { + + *sizex = (bmfont->glyphs[index].sizex) / (float) (bmfont->glyphs[0].sizex); + *sizey = (bmfont->glyphs[index].sizey) / (float) (bmfont->glyphs[0].sizey); + + *transx = bmfont->glyphs[index].locx / (float) ibuf->x; + *transy = (ibuf->y - bmfont->glyphs[index].locy) / (float) ibuf->y; + + *centerx = bmfont->glyphs[0].locx / (float) ibuf->x; + *centery = (ibuf->y - bmfont->glyphs[0].locy) / (float) ibuf->y; + + // 2.0 units is the default size of an object + + *movey = 1.0f - *sizey + 2.0f * (bmfont->glyphs[index].ofsy - bmfont->glyphs[0].ofsy) / (float) bmfont->glyphs[0].sizey; + *movex = *sizex - 1.0f + 2.0f * (bmfont->glyphs[index].ofsx - bmfont->glyphs[0].ofsx) / (float) bmfont->glyphs[0].sizex; + + *advance = 2.0f * bmfont->glyphs[index].advance / (float) bmfont->glyphs[0].advance; + + // printfGlyph(&bmfont->glyphs[index]); + // printf("%c %d %0.5f %0.5f %0.5f %0.5f %0.5f \n", unicode, index, *sizex, *sizey, *transx, *transy, *advance); + } + } + } +} -- cgit v1.2.3