Blender V2.61 - r43446

bmfont.c

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