Blender  V2.59
bmfont.c
Go to the documentation of this file.
00001 /*
00002  * bmfont.c
00003  *
00004  * 04-10-2000 frank
00005  *
00006  * $Id: bmfont.c 35247 2011-02-27 20:40:57Z jesterking $
00007  *
00008  * ***** BEGIN GPL LICENSE BLOCK *****
00009  *
00010  * This program is free software; you can redistribute it and/or
00011  * modify it under the terms of the GNU General Public License
00012  * as published by the Free Software Foundation; either version 2
00013  * of the License, or (at your option) any later version.
00014  *
00015  * This program is distributed in the hope that it will be useful,
00016  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00017  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  * GNU General Public License for more details.
00019  *
00020  * You should have received a copy of the GNU General Public License
00021  * along with this program; if not, write to the Free Software Foundation,
00022  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
00023  *
00024  * The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
00025  * All rights reserved.
00026  *
00027  * The Original Code is: all of this file.
00028  *
00029  * Contributor(s): none yet.
00030  *
00031  * ***** END GPL LICENSE BLOCK *****
00032  *
00033  */
00034 
00056 #include <stdio.h>
00057 
00058 #include "MEM_guardedalloc.h"
00059 #include "BKE_global.h"
00060 #include "IMB_imbuf_types.h"
00061 
00062 #include "BKE_bmfont.h"
00063 #include "BKE_bmfont_types.h"
00064 
00065 void printfGlyph(bmGlyph * glyph)
00066 {
00067         printf("unicode: %d '%c'\n", glyph->unicode, glyph->unicode);
00068         printf(" locx: %4d locy: %4d\n", glyph->locx, glyph->locy);
00069         printf(" sizex: %3d sizey: %3d\n", glyph->sizex, glyph->sizey);
00070         printf(" ofsx:  %3d ofsy:  %3d\n", glyph->ofsx, glyph->ofsy);
00071         printf(" advan: %3d reser: %3d\n", glyph->advance, glyph->reserved);
00072 }
00073 
00074 #define MAX2(x,y)          ( (x)>(y) ? (x) : (y) )
00075 #define MAX3(x,y,z)                MAX2( MAX2((x),(y)) , (z) )  
00076 
00077 void calcAlpha(ImBuf * ibuf)
00078 {
00079         int i;
00080         char * rect;
00081         
00082         if (ibuf) {
00083                 rect = (char *) ibuf->rect;
00084                 for (i = ibuf->x * ibuf->y ; i > 0 ; i--) {
00085                         rect[3] = MAX3(rect[0], rect[1], rect[2]);
00086                         rect += 4;
00087                 }
00088         }
00089 }
00090 
00091 void readBitmapFontVersion0(ImBuf * ibuf, unsigned char * rect, int step)
00092 {
00093         int glyphcount, bytes, i, index, linelength, ysize;
00094         unsigned char * buffer;
00095         bmFont * bmfont;
00096         
00097         linelength = ibuf->x * step;
00098         
00099         glyphcount = (rect[6 * step] << 8) | rect[7 * step];
00100         bytes = ((glyphcount - 1) * sizeof(bmGlyph)) + sizeof(bmFont);
00101         
00102         ysize = (bytes + (ibuf->x - 1)) / ibuf->x;
00103         
00104         if (ysize < ibuf->y) {
00105                 // we're first going to copy all data into a liniar buffer.
00106                 // step can be 4 or 1 bytes, and the data is not sequential because
00107                 // the bitmap was flipped vertically.
00108                 
00109                 buffer = MEM_mallocN(bytes, "readBitmapFontVersion0:buffer");
00110                 
00111                 index = 0;      
00112                 for (i = 0; i < bytes; i++) {
00113                         buffer[i] = rect[index];
00114                         index += step;
00115                         if (index >= linelength) {
00116                                 // we've read one line, no skip to the line *before* that
00117                                 rect -= linelength;
00118                                 index -= linelength;
00119                         }
00120                 }
00121                 
00122                 // we're now going to endian convert the data
00123                 
00124                 bmfont = MEM_mallocN(bytes, "readBitmapFontVersion0:bmfont");
00125                 index = 0;
00126                 
00127                 // first read the header
00128                 bmfont->magic[0]    = buffer[index++];
00129                 bmfont->magic[1]    = buffer[index++];
00130                 bmfont->magic[2]    = buffer[index++];
00131                 bmfont->magic[3]    = buffer[index++];
00132                 bmfont->version     = (buffer[index] << 8) | buffer[index + 1]; index += 2;
00133                 bmfont->glyphcount  = (buffer[index] << 8) | buffer[index + 1]; index += 2;
00134                 bmfont->xsize       = (buffer[index] << 8) | buffer[index + 1]; index += 2;
00135                 bmfont->ysize       = (buffer[index] << 8) | buffer[index + 1]; index += 2;
00136                 
00137                 for (i = 0; i < bmfont->glyphcount; i++) {
00138                         bmfont->glyphs[i].unicode  = (buffer[index] << 8) | buffer[index + 1]; index += 2;
00139                         bmfont->glyphs[i].locx     = (buffer[index] << 8) | buffer[index + 1]; index += 2;
00140                         bmfont->glyphs[i].locy     = (buffer[index] << 8) | buffer[index + 1]; index += 2;
00141                         bmfont->glyphs[i].ofsx     = buffer[index++];
00142                         bmfont->glyphs[i].ofsy     = buffer[index++];
00143                         bmfont->glyphs[i].sizex    = buffer[index++];
00144                         bmfont->glyphs[i].sizey    = buffer[index++];
00145                         bmfont->glyphs[i].advance  = buffer[index++];
00146                         bmfont->glyphs[i].reserved = buffer[index++];
00147                         if (G.f & G_DEBUG) {
00148                                 printfGlyph(&bmfont->glyphs[i]);
00149                         }
00150                 }
00151                 
00152                 MEM_freeN(buffer);
00153                 
00154                 if (G.f & G_DEBUG) {
00155                         printf("Oldy = %d Newy = %d\n", ibuf->y, ibuf->y - ysize);
00156                         printf("glyphcount = %d\n", glyphcount);
00157                         printf("bytes = %d\n", bytes);
00158                 }
00159 
00160                 // we've read the data from the image. Now we're going
00161                 // to crop the image vertically so only the bitmap data
00162                 // remains visible
00163                 
00164                 ibuf->y -= ysize;
00165                 ibuf->userdata = bmfont;
00166                 ibuf->userflags |= IB_BITMAPFONT;
00167 
00168                 if (ibuf->depth < 32) {
00169                         // we're going to fake alpha here:
00170                         calcAlpha(ibuf);
00171                 }
00172         } else {
00173                 printf("readBitmapFontVersion0: corrupted bitmapfont\n");
00174         }
00175 }
00176 
00177 void detectBitmapFont(ImBuf *ibuf)
00178 {
00179         unsigned char * rect;
00180         unsigned short version;
00181         int i;
00182         
00183         if (ibuf != NULL && ibuf->rect != NULL) {
00184                         // bitmap must have an x size that is a power of two
00185                 if (is_power_of_two(ibuf->x)) {
00186                         rect = (unsigned char *) (ibuf->rect + (ibuf->x * (ibuf->y - 1)));
00187                         // printf ("starts with: %s %c %c %c %c\n", rect, rect[0], rect[1], rect[2], rect[3]);
00188                         if (rect[0] == 'B' && rect[1] == 'F' && rect[2] == 'N' && rect[3] == 'T') {
00189                                 // printf("found 8bit font !\n");
00190                                 // round y size down
00191                                 // do the 8 bit font stuff. (not yet)
00192                         } else {
00193                                 // we try all 4 possible combinations
00194                                 for (i = 0; i < 4; i++) {
00195                                         if (rect[0] == 'B' && rect[4] == 'F' && rect[8] == 'N' && rect[12] == 'T') {
00196                                                 // printf("found 24bit font !\n");
00197                                                 // We're going to parse the file:
00198                                                 
00199                                                 version = (rect[16] << 8) | rect[20];
00200                                                 
00201                                                 if (version == 0) {
00202                                                         readBitmapFontVersion0(ibuf, rect, 4);
00203                                                 } else {
00204                                                         printf("detectBitmapFont :Unsupported version %d\n", version);
00205                                                 }
00206                                                 
00207                                                 // on succes ibuf->userdata points to the bitmapfont
00208                                                 if (ibuf->userdata) {
00209                                                         break;
00210                                                 }
00211                                         }
00212                                         rect++;
00213                                 }
00214                         }
00215                 }
00216         }
00217 }
00218 
00219 int locateGlyph(bmFont *bmfont, unsigned short unicode)
00220 {
00221         int min, max, current = 0;
00222         
00223         if (bmfont) {
00224                 min = 0;
00225                 max = bmfont->glyphcount;
00226                 while (1) {
00227                         // look halfway for glyph
00228                         current = (min + max) >> 1;
00229 
00230                         if (bmfont->glyphs[current].unicode == unicode) {
00231                                 break;
00232                         } else if (bmfont->glyphs[current].unicode < unicode) {
00233                                 // have to move up
00234                                 min = current;
00235                         } else {
00236                                 // have to move down
00237                                 max = current;
00238                         }
00239                         
00240                         if (max - min <= 1) {
00241                                 // unable to locate glyph
00242                                 current = 0;
00243                                 break;
00244                         }
00245                 }
00246         }
00247         
00248         return(current);
00249 }
00250 
00251 void matrixGlyph(ImBuf * ibuf, unsigned short unicode,
00252                 float *centerx, float *centery,
00253                 float *sizex,   float *sizey,
00254                 float *transx,  float *transy,
00255                 float *movex,   float *movey,
00256                 float *advance)
00257 {
00258         int index;
00259         bmFont *bmfont;
00260         
00261         *centerx = *centery = 0.0;
00262         *sizex = *sizey = 1.0;
00263         *transx = *transy = 0.0;
00264         *movex = *movey = 0.0;
00265         *advance = 1.0;
00266                 
00267         if (ibuf) {
00268                 bmfont = ibuf->userdata;
00269                 if (bmfont && (ibuf->userflags & IB_BITMAPFONT)) {
00270                         index = locateGlyph(bmfont, unicode);
00271                         if (index) {
00272                                                                 
00273                                 *sizex = (bmfont->glyphs[index].sizex) / (float) (bmfont->glyphs[0].sizex);
00274                                 *sizey = (bmfont->glyphs[index].sizey) / (float) (bmfont->glyphs[0].sizey);
00275 
00276                                 *transx = bmfont->glyphs[index].locx / (float) ibuf->x;
00277                                 *transy = (ibuf->y - bmfont->glyphs[index].locy) / (float) ibuf->y;
00278 
00279                                 *centerx = bmfont->glyphs[0].locx / (float) ibuf->x;
00280                                 *centery = (ibuf->y - bmfont->glyphs[0].locy) / (float) ibuf->y;
00281 
00282                                 // 2.0 units is the default size of an object
00283                                 
00284                                 *movey = 1.0f - *sizey + 2.0f * (bmfont->glyphs[index].ofsy - bmfont->glyphs[0].ofsy) / (float) bmfont->glyphs[0].sizey;
00285                                 *movex = *sizex - 1.0f + 2.0f * (bmfont->glyphs[index].ofsx - bmfont->glyphs[0].ofsx) / (float) bmfont->glyphs[0].sizex;
00286                                 
00287                                 *advance = 2.0f * bmfont->glyphs[index].advance / (float) bmfont->glyphs[0].advance;
00288 
00289                                 // printfGlyph(&bmfont->glyphs[index]);
00290                                 // printf("%c %d %0.5f %0.5f %0.5f %0.5f %0.5f \n", unicode, index, *sizex, *sizey, *transx, *transy, *advance);
00291                         }
00292                 }
00293         }
00294 }