Blender  V2.59
bmfont.cpp
Go to the documentation of this file.
00001 /*
00002  * bmfont.c
00003  *
00004  * 04-10-2000 frank
00005  *
00006  * $Id: bmfont.cpp 35170 2011-02-25 13:35:11Z 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 "BLI_blenlib.h"
00060 #include "BKE_global.h"
00061 #include "IMB_imbuf_types.h"
00062 
00063 #include "BKE_bmfont.h"
00064 #include "BKE_bmfont_types.h"
00065 
00066 /*MAART:
00067 void printfGlyph(bmGlyph * glyph)
00068 {
00069         printf("unicode: %d '%c'\n", glyph->unicode, glyph->unicode);
00070         printf(" locx: %4d locy: %4d\n", glyph->locx, glyph->locy);
00071         printf(" sizex: %3d sizey: %3d\n", glyph->sizex, glyph->sizey);
00072         printf(" ofsx:  %3d ofsy:  %3d\n", glyph->ofsx, glyph->ofsy);
00073         printf(" advan: %3d reser: %3d\n", glyph->advance, glyph->reserved);
00074 }
00075 */
00076 
00077 #define MAX2(x,y)          ( (x)>(y) ? (x) : (y) )
00078 #define MAX3(x,y,z)                MAX2( MAX2((x),(y)) , (z) )  
00079 
00080 void calcAlpha(ImBuf * ibuf)
00081 {
00082         int i;
00083         char * rect;
00084         
00085         if (ibuf) {
00086                 rect = (char *) ibuf->rect;
00087                 for (i = ibuf->x * ibuf->y ; i > 0 ; i--) {
00088                         rect[3] = MAX3(rect[0], rect[1], rect[2]);
00089                         rect += 4;
00090                 }
00091         }
00092 }
00093 
00094 void readBitmapFontVersion0(ImBuf * ibuf, unsigned char * rect, int step)
00095 {
00096         int glyphcount, bytes, i, index, linelength, ysize;
00097         unsigned char * buffer;
00098         bmFont * bmfont;
00099         
00100         linelength = ibuf->x * step;
00101         
00102         glyphcount = (rect[6 * step] << 8) | rect[7 * step];
00103         bytes = ((glyphcount - 1) * sizeof(bmGlyph)) + sizeof(bmFont);
00104         
00105         ysize = (bytes + (ibuf->x - 1)) / ibuf->x;
00106         
00107         if (ysize < ibuf->y) {
00108                 // we're first going to copy all data into a liniar buffer.
00109                 // step can be 4 or 1 bytes, and the data is not sequential because
00110                 // the bitmap was flipped vertically.
00111                 
00112                 buffer = (unsigned char*)MEM_mallocN(bytes, "readBitmapFontVersion0:buffer");
00113                 
00114                 index = 0;      
00115                 for (i = 0; i < bytes; i++) {
00116                         buffer[i] = rect[index];
00117                         index += step;
00118                         if (index >= linelength) {
00119                                 // we've read one line, no skip to the line *before* that
00120                                 rect -= linelength;
00121                                 index -= linelength;
00122                         }
00123                 }
00124                 
00125                 // we're now going to endian convert the data
00126                 
00127                 bmfont = (bmFont*)MEM_mallocN(bytes, "readBitmapFontVersion0:bmfont");
00128                 index = 0;
00129                 
00130                 // first read the header
00131                 bmfont->magic[0]    = buffer[index++];
00132                 bmfont->magic[1]    = buffer[index++];
00133                 bmfont->magic[2]    = buffer[index++];
00134                 bmfont->magic[3]    = buffer[index++];
00135                 bmfont->version     = (buffer[index] << 8) | buffer[index + 1]; index += 2;
00136                 bmfont->glyphcount  = (buffer[index] << 8) | buffer[index + 1]; index += 2;
00137                 bmfont->xsize       = (buffer[index] << 8) | buffer[index + 1]; index += 2;
00138                 bmfont->ysize       = (buffer[index] << 8) | buffer[index + 1]; index += 2;
00139                 
00140                 for (i = 0; i < bmfont->glyphcount; i++) {
00141                         bmfont->glyphs[i].unicode  = (buffer[index] << 8) | buffer[index + 1]; index += 2;
00142                         bmfont->glyphs[i].locx     = (buffer[index] << 8) | buffer[index + 1]; index += 2;
00143                         bmfont->glyphs[i].locy     = (buffer[index] << 8) | buffer[index + 1]; index += 2;
00144                         bmfont->glyphs[i].ofsx     = buffer[index++];
00145                         bmfont->glyphs[i].ofsy     = buffer[index++];
00146                         bmfont->glyphs[i].sizex    = buffer[index++];
00147                         bmfont->glyphs[i].sizey    = buffer[index++];
00148                         bmfont->glyphs[i].advance  = buffer[index++];
00149                         bmfont->glyphs[i].reserved = buffer[index++];
00150                         /* MAART:
00151                         if (G.f & G_DEBUG) {
00152                                 printfGlyph(&bmfont->glyphs[i]);
00153                         }
00154                         */
00155                 }
00156                 
00157                 MEM_freeN(buffer);
00158                 
00159                 /* MAART:
00160                 if (G.f & G_DEBUG) {
00161                         printf("Oldy = %d Newy = %d\n", ibuf->y, ibuf->y - ysize);
00162                         printf("glyphcount = %d\n", glyphcount);
00163                         printf("bytes = %d\n", bytes);
00164                 }
00165                 */
00166 
00167                 // we've read the data from the image. Now we're going
00168                 // to crop the image vertically so only the bitmap data
00169                 // remains visible
00170                 
00171                 ibuf->y -= ysize;
00172                 ibuf->userdata = bmfont;
00173                 ibuf->userflags |= IB_BITMAPFONT;
00174 
00175                 if (ibuf->depth < 32) {
00176                         // we're going to fake alpha here:
00177                         calcAlpha(ibuf);
00178                 }
00179         } else {
00180                 /* MAART:
00181                 printf("readBitmapFontVersion0: corrupted bitmapfont\n");
00182                 */
00183         }
00184 }
00185 
00186 void detectBitmapFont(ImBuf *ibuf)
00187 {
00188         unsigned char * rect;
00189         unsigned short version;
00190         long i;
00191         
00192         if (ibuf != NULL) {
00193                 // bitmap must have an x size that is a power of two
00194                 if (is_power_of_two(ibuf->x)) {
00195                         rect = (unsigned char *) (ibuf->rect + (ibuf->x * (ibuf->y - 1)));
00196                         // printf ("starts with: %s %c %c %c %c\n", rect, rect[0], rect[1], rect[2], rect[3]);
00197                         if (rect[0] == 'B' && rect[1] == 'F' && rect[2] == 'N' && rect[3] == 'T') {
00198                                 // printf("found 8bit font !\n");
00199                                 // round y size down
00200                                 // do the 8 bit font stuff. (not yet)
00201                         } else {
00202                                 // we try all 4 possible combinations
00203                                 for (i = 0; i < 4; i++) {
00204                                         if (rect[0] == 'B' && rect[4] == 'F' && rect[8] == 'N' && rect[12] == 'T') {
00205                                                 // printf("found 24bit font !\n");
00206                                                 // We're going to parse the file:
00207                                                 
00208                                                 version = (rect[16] << 8) | rect[20];
00209                                                 
00210                                                 if (version == 0) {
00211                                                         readBitmapFontVersion0(ibuf, rect, 4);
00212                                                 } else {
00213                                                         //printf("detectBitmapFont :Unsupported version %d\n", version);
00214                                                 }
00215                                                 
00216                                                 // on succes ibuf->userdata points to the bitmapfont
00217                                                 if (ibuf->userdata) {
00218                                                         break;
00219                                                 }
00220                                         }
00221                                         rect++;
00222                                 }
00223                         }
00224                 }
00225         }
00226 }
00227 
00228 int locateGlyph(bmFont *bmfont, unsigned short unicode)
00229 {
00230         int min, max, current = 0;
00231         
00232         if (bmfont) {
00233                 min = 0;
00234                 max = bmfont->glyphcount;
00235                 while (1) {
00236                         // look halfway for glyph
00237                         current = (min + max) >> 1;
00238 
00239                         if (bmfont->glyphs[current].unicode == unicode) {
00240                                 break;
00241                         } else if (bmfont->glyphs[current].unicode < unicode) {
00242                                 // have to move up
00243                                 min = current;
00244                         } else {
00245                                 // have to move down
00246                                 max = current;
00247                         }
00248                         
00249                         if (max - min <= 1) {
00250                                 // unable to locate glyph
00251                                 current = 0;
00252                                 break;
00253                         }
00254                 }
00255         }
00256         
00257         return(current);
00258 }
00259 
00260 void matrixGlyph(ImBuf * ibuf, unsigned short unicode,
00261                 float *centerx, float *centery,
00262                 float *sizex,   float *sizey,
00263                 float *transx,  float *transy,
00264                 float *movex,   float *movey,
00265                 float *advance)
00266 {
00267         int index;
00268         bmFont *bmfont;
00269         
00270         *centerx = *centery = 0.0;
00271         *sizex = *sizey = 1.0;
00272         *transx = *transy = 0.0;
00273         *movex = *movey = 0.0;
00274         *advance = 1.0;
00275                 
00276         if (ibuf) {
00277                 bmfont = (bmFont*)ibuf->userdata;
00278                 if (bmfont && (ibuf->userflags & IB_BITMAPFONT)) {
00279                         index = locateGlyph(bmfont, unicode);
00280                         if (index) {
00281                                                                 
00282                                 *sizex = (bmfont->glyphs[index].sizex) / (float) (bmfont->glyphs[0].sizex);
00283                                 *sizey = (bmfont->glyphs[index].sizey) / (float) (bmfont->glyphs[0].sizey);
00284 
00285                                 *transx = bmfont->glyphs[index].locx / (float) ibuf->x;
00286                                 *transy = (ibuf->y - bmfont->glyphs[index].locy) / (float) ibuf->y;
00287 
00288                                 *centerx = bmfont->glyphs[0].locx / (float) ibuf->x;
00289                                 *centery = (ibuf->y - bmfont->glyphs[0].locy) / (float) ibuf->y;
00290 
00291                                 // 2.0 units is the default size of an object
00292                                 
00293                                 *movey = (float)(1.0 - *sizey + 2.0 * (bmfont->glyphs[index].ofsy - bmfont->glyphs[0].ofsy) / (float) bmfont->glyphs[0].sizey);
00294                                 *movex = (float)(*sizex - 1.0 + 2.0 * (bmfont->glyphs[index].ofsx - bmfont->glyphs[0].ofsx) / (float) bmfont->glyphs[0].sizex);
00295                                 
00296                                 *advance = (float)(2.0 * bmfont->glyphs[index].advance / (float) bmfont->glyphs[0].advance);
00297 
00298                                 // printfGlyph(&bmfont->glyphs[index]);
00299                                 // printf("%c %d %0.5f %0.5f %0.5f %0.5f %0.5f \n", unicode, index, *sizex, *sizey, *transx, *transy, *advance);
00300                         }
00301                 }
00302         }
00303 }