Blender V2.61 - r43446

blf.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) 2009 Blender Foundation.
00019  * All rights reserved.
00020  *
00021  *
00022  * Contributor(s): Blender Foundation
00023  *
00024  * ***** END GPL LICENSE BLOCK *****
00025  */
00026 
00032 #include <stdio.h>
00033 #include <stdlib.h>
00034 #include <string.h>
00035 #include <math.h>
00036 
00037 #include <ft2build.h>
00038 
00039 #include FT_FREETYPE_H
00040 #include FT_GLYPH_H
00041 
00042 #include "MEM_guardedalloc.h"
00043 
00044 #include "DNA_listBase.h"
00045 #include "DNA_vec_types.h"
00046 
00047 #include "BIF_gl.h"
00048 #include "BLF_api.h"
00049 
00050 #include "blf_internal_types.h"
00051 #include "blf_internal.h"
00052 
00053 
00054 /* Max number of font in memory.
00055  * Take care that now every font have a glyph cache per size/dpi,
00056  * so we don't need load the same font with different size, just
00057  * load one and call BLF_size.
00058  */
00059 #define BLF_MAX_FONT 16
00060 
00061 /* Font array. */
00062 static FontBLF *global_font[BLF_MAX_FONT] = {0};
00063 
00064 /* Default size and dpi, for BLF_draw_default. */
00065 static int global_font_default= -1;
00066 static int global_font_points= 11;
00067 static int global_font_dpi= 72;
00068 
00069 // XXX, should these be made into global_font_'s too?
00070 int blf_mono_font= -1;
00071 int blf_mono_font_render= -1;
00072 
00073 static FontBLF *BLF_get(int fontid)
00074 {
00075     if (fontid >= 0 && fontid < BLF_MAX_FONT)
00076         return global_font[fontid];
00077     return NULL;
00078 }
00079 
00080 int BLF_init(int points, int dpi)
00081 {
00082     int i;
00083 
00084     for (i= 0; i < BLF_MAX_FONT; i++)
00085         global_font[i]= NULL;
00086 
00087     global_font_points= points;
00088     global_font_dpi= dpi;
00089     return blf_font_init();
00090 }
00091 
00092 void BLF_exit(void)
00093 {
00094     FontBLF *font;
00095     int i;
00096 
00097     for (i= 0; i < BLF_MAX_FONT; i++) {
00098         font= global_font[i];
00099         if (font) {
00100             blf_font_free(font);
00101             global_font[i]= NULL;
00102         }
00103     }
00104 
00105     blf_font_exit();
00106 }
00107 
00108 void BLF_cache_clear(void)
00109 {
00110     FontBLF *font;
00111     int i;
00112 
00113     for (i= 0; i < BLF_MAX_FONT; i++) {
00114         font= global_font[i];
00115         if (font)
00116             blf_glyph_cache_clear(font);
00117     }
00118 }
00119 
00120 static int blf_search(const char *name)
00121 {
00122     FontBLF *font;
00123     int i;
00124 
00125     for (i= 0; i < BLF_MAX_FONT; i++) {
00126         font= global_font[i];
00127         if (font && (!strcmp(font->name, name)))
00128             return i;
00129     }
00130 
00131     return -1;
00132 }
00133 
00134 static int blf_search_available(void)
00135 {
00136     int i;
00137 
00138     for (i= 0; i < BLF_MAX_FONT; i++)
00139         if(!global_font[i])
00140             return i;
00141     
00142     return -1;
00143 }
00144 
00145 int BLF_load(const char *name)
00146 {
00147     FontBLF *font;
00148     char *filename;
00149     int i;
00150 
00151     if (!name)
00152         return -1;
00153 
00154     /* check if we already load this font. */
00155     i= blf_search(name);
00156     if (i >= 0) {
00157         /*font= global_font[i];*/ /*UNUSED*/
00158         return i;
00159     }
00160 
00161     i = blf_search_available();
00162     if (i == -1) {
00163         printf("Too many fonts!!!\n");
00164         return -1;
00165     }
00166 
00167     filename= blf_dir_search(name);
00168     if (!filename) {
00169         printf("Can't find font: %s\n", name);
00170         return -1;
00171     }
00172 
00173     font= blf_font_new(name, filename);
00174     MEM_freeN(filename);
00175 
00176     if (!font) {
00177         printf("Can't load font: %s\n", name);
00178         return -1;
00179     }
00180 
00181     global_font[i]= font;
00182     return i;
00183 }
00184 
00185 int BLF_load_unique(const char *name)
00186 {
00187     FontBLF *font;
00188     char *filename;
00189     int i;
00190 
00191     if (!name)
00192         return -1;
00193 
00194     /* Don't search in the cache!! make a new
00195      * object font, this is for keep fonts threads safe.
00196      */
00197     i = blf_search_available();
00198     if (i == -1) {
00199         printf("Too many fonts!!!\n");
00200         return -1;
00201     }
00202 
00203     filename= blf_dir_search(name);
00204     if (!filename) {
00205         printf("Can't find font: %s\n", name);
00206         return -1;
00207     }
00208 
00209     font= blf_font_new(name, filename);
00210     MEM_freeN(filename);
00211 
00212     if (!font) {
00213         printf("Can't load font: %s\n", name);
00214         return -1;
00215     }
00216 
00217     global_font[i]= font;
00218     return i;
00219 }
00220 
00221 void BLF_metrics_attach(int fontid, unsigned char *mem, int mem_size)
00222 {
00223     FontBLF *font= BLF_get(fontid);
00224 
00225     if (font) {
00226         blf_font_attach_from_mem(font, mem, mem_size);
00227     }
00228 }
00229 
00230 int BLF_load_mem(const char *name, unsigned char *mem, int mem_size)
00231 {
00232     FontBLF *font;
00233     int i;
00234 
00235     if (!name)
00236         return -1;
00237 
00238     i= blf_search(name);
00239     if (i >= 0) {
00240         /*font= global_font[i];*/ /*UNUSED*/
00241         return i;
00242     }
00243 
00244     i = blf_search_available();
00245     if (i == -1) {
00246         printf("Too many fonts!!!\n");
00247         return -1;
00248     }
00249 
00250     if (!mem || !mem_size) {
00251         printf("Can't load font: %s from memory!!\n", name);
00252         return -1;
00253     }
00254 
00255     font= blf_font_new_from_mem(name, mem, mem_size);
00256     if (!font) {
00257         printf("Can't load font: %s from memory!!\n", name);
00258         return -1;
00259     }
00260 
00261     global_font[i]= font;
00262     return i;
00263 }
00264 
00265 int BLF_load_mem_unique(const char *name, unsigned char *mem, int mem_size)
00266 {
00267     FontBLF *font;
00268     int i;
00269 
00270     if (!name)
00271         return -1;
00272 
00273     /*
00274      * Don't search in the cache, make a new object font!
00275      * this is to keep the font thread safe.
00276      */
00277     i = blf_search_available();
00278     if (i == -1) {
00279         printf("Too many fonts!!!\n");
00280         return -1;
00281     }
00282 
00283     if (!mem || !mem_size) {
00284         printf("Can't load font: %s from memory!!\n", name);
00285         return -1;
00286     }
00287 
00288     font= blf_font_new_from_mem(name, mem, mem_size);
00289     if (!font) {
00290         printf("Can't load font: %s from memory!!\n", name);
00291         return -1;
00292     }
00293 
00294     global_font[i]= font;
00295     return i;
00296 }
00297 
00298 void BLF_unload(const char *name)
00299 {
00300     FontBLF *font;
00301     int i;
00302 
00303     for (i= 0; i < BLF_MAX_FONT; i++) {
00304         font= global_font[i];
00305 
00306         if (font && (!strcmp(font->name, name))) {
00307             blf_font_free(font);
00308             global_font[i]= NULL;
00309         }
00310     }
00311 }
00312 
00313 void BLF_enable(int fontid, int option)
00314 {
00315     FontBLF *font= BLF_get(fontid);
00316 
00317     if (font) {
00318         font->flags |= option;
00319     }
00320 }
00321 
00322 void BLF_disable(int fontid, int option)
00323 {
00324     FontBLF *font= BLF_get(fontid);
00325 
00326     if (font) {
00327         font->flags &= ~option;
00328     }
00329 }
00330 
00331 void BLF_enable_default(int option)
00332 {
00333     FontBLF *font= BLF_get(global_font_default);
00334 
00335     if (font) {
00336         font->flags |= option;
00337     }
00338 }
00339 
00340 void BLF_disable_default(int option)
00341 {
00342     FontBLF *font= BLF_get(global_font_default);
00343 
00344     if (font) {
00345         font->flags &= ~option;
00346     }
00347 }
00348 
00349 void BLF_aspect(int fontid, float x, float y, float z)
00350 {
00351     FontBLF *font= BLF_get(fontid);
00352 
00353     if (font) {
00354         font->aspect[0]= x;
00355         font->aspect[1]= y;
00356         font->aspect[2]= z;
00357     }
00358 }
00359 
00360 void BLF_matrix(int fontid, const double m[16])
00361 {
00362     FontBLF *font= BLF_get(fontid);
00363 
00364     if (font) {
00365         memcpy(font->m, m, sizeof(font->m));
00366     }
00367 }
00368 
00369 void BLF_position(int fontid, float x, float y, float z)
00370 {
00371     FontBLF *font= BLF_get(fontid);
00372 
00373     if (font) {
00374         float xa, ya, za;
00375         float remainder;
00376 
00377         if (font->flags & BLF_ASPECT) {
00378             xa= font->aspect[0];
00379             ya= font->aspect[1];
00380             za= font->aspect[2];
00381         }
00382         else {
00383             xa= 1.0f;
00384             ya= 1.0f;
00385             za= 1.0f;
00386         }
00387 
00388         remainder= x - floorf(x);
00389         if (remainder > 0.4f && remainder < 0.6f) {
00390             if (remainder < 0.5f)
00391                 x -= 0.1f * xa;
00392             else
00393                 x += 0.1f * xa;
00394         }
00395 
00396         remainder= y - floorf(y);
00397         if (remainder > 0.4f && remainder < 0.6f) {
00398             if (remainder < 0.5f)
00399                 y -= 0.1f * ya;
00400             else
00401                 y += 0.1f * ya;
00402         }
00403 
00404         remainder= z - floorf(z);
00405         if (remainder > 0.4f && remainder < 0.6f) {
00406             if (remainder < 0.5f)
00407                 z -= 0.1f * za;
00408             else
00409                 z += 0.1f * za;
00410         }
00411 
00412         font->pos[0]= x;
00413         font->pos[1]= y;
00414         font->pos[2]= z;
00415     }
00416 }
00417 
00418 void BLF_size(int fontid, int size, int dpi)
00419 {
00420     FontBLF *font= BLF_get(fontid);
00421 
00422     if (font) {
00423         blf_font_size(font, size, dpi);
00424     }
00425 }
00426 
00427 void BLF_blur(int fontid, int size)
00428 {
00429     FontBLF *font= BLF_get(fontid);
00430 
00431     if (font) {
00432         font->blur= size;
00433     }
00434 }
00435 
00436 void BLF_draw_default(float x, float y, float z, const char *str, size_t len)
00437 {
00438     if (!str)
00439         return;
00440 
00441     if (global_font_default == -1)
00442         global_font_default= blf_search("default");
00443 
00444     if (global_font_default == -1) {
00445         printf("Warning: Can't found default font!!\n");
00446         return;
00447     }
00448 
00449     BLF_size(global_font_default, global_font_points, global_font_dpi);
00450     BLF_position(global_font_default, x, y, z);
00451     BLF_draw(global_font_default, str, len);
00452 }
00453 
00454 /* same as above but call 'BLF_draw_ascii' */
00455 void BLF_draw_default_ascii(float x, float y, float z, const char *str, size_t len)
00456 {
00457     if (!str)
00458         return;
00459 
00460     if (global_font_default == -1)
00461         global_font_default= blf_search("default");
00462 
00463     if (global_font_default == -1) {
00464         printf("Warning: Can't found default font!!\n");
00465         return;
00466     }
00467 
00468     BLF_size(global_font_default, global_font_points, global_font_dpi);
00469     BLF_position(global_font_default, x, y, z);
00470     BLF_draw_ascii(global_font_default, str, len); /* XXX, use real length */
00471 }
00472 
00473 void BLF_rotation_default(float angle)
00474 {
00475     FontBLF *font= BLF_get(global_font_default);
00476 
00477     if (font) {
00478         font->angle= angle;
00479     }
00480 }
00481 
00482 static void blf_draw__start(FontBLF *font, GLint *mode, GLint *param)
00483 {
00484     /*
00485      * The pixmap alignment hack is handle
00486      * in BLF_position (old ui_rasterpos_safe).
00487      */
00488 
00489     glEnable(GL_BLEND);
00490     glEnable(GL_TEXTURE_2D);
00491     glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
00492 
00493     /* Save the current matrix mode. */
00494     glGetIntegerv(GL_MATRIX_MODE, mode);
00495 
00496     glMatrixMode(GL_TEXTURE);
00497     glPushMatrix();
00498     glLoadIdentity();
00499 
00500     glMatrixMode(GL_MODELVIEW);
00501     glPushMatrix();
00502 
00503     if (font->flags & BLF_MATRIX)
00504         glMultMatrixd((GLdouble *)&font->m);
00505 
00506     glTranslatef(font->pos[0], font->pos[1], font->pos[2]);
00507 
00508     if (font->flags & BLF_ASPECT)
00509         glScalef(font->aspect[0], font->aspect[1], font->aspect[2]);
00510 
00511     if (font->flags & BLF_ROTATION)
00512         glRotatef(font->angle, 0.0f, 0.0f, 1.0f);
00513 
00514     if(font->shadow || font->blur)
00515         glGetFloatv(GL_CURRENT_COLOR, font->orig_col);
00516 
00517     /* always bind the texture for the first glyph */
00518     font->tex_bind_state= -1;
00519 
00520     /* Save the current parameter to restore it later. */
00521     glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param);
00522     if (*param != GL_MODULATE)
00523         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
00524 }
00525 
00526 static void blf_draw__end(GLint mode, GLint param)
00527 {
00528     /* and restore the original value. */
00529     if (param != GL_MODULATE)
00530         glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, param);
00531 
00532     glMatrixMode(GL_TEXTURE);
00533     glPopMatrix();
00534 
00535     glMatrixMode(GL_MODELVIEW);
00536     glPopMatrix();
00537 
00538     if (mode != GL_MODELVIEW)
00539         glMatrixMode(mode);
00540 
00541     glDisable(GL_BLEND);
00542     glDisable(GL_TEXTURE_2D);
00543 }
00544 
00545 void BLF_draw(int fontid, const char *str, size_t len)
00546 {
00547     FontBLF *font= BLF_get(fontid);
00548     GLint mode, param;
00549 
00550     if (font && font->glyph_cache) {
00551         blf_draw__start(font, &mode, &param);
00552         blf_font_draw(font, str, len);
00553         blf_draw__end(mode, param);
00554     }
00555 }
00556 
00557 void BLF_draw_ascii(int fontid, const char *str, size_t len)
00558 {
00559     FontBLF *font= BLF_get(fontid);
00560     GLint mode, param;
00561 
00562     if (font && font->glyph_cache) {
00563         blf_draw__start(font, &mode, &param);
00564         blf_font_draw_ascii(font, str, len);
00565         blf_draw__end(mode, param);
00566     }
00567 }
00568 
00569 void BLF_boundbox(int fontid, const char *str, rctf *box)
00570 {
00571     FontBLF *font= BLF_get(fontid);
00572 
00573     if (font) {
00574         blf_font_boundbox(font, str, box);
00575     }
00576 }
00577 
00578 void BLF_width_and_height(int fontid, const char *str, float *width, float *height)
00579 {
00580     FontBLF *font= BLF_get(fontid);
00581 
00582     if (font && font->glyph_cache) {
00583         blf_font_width_and_height(font, str, width, height);
00584     }
00585 }
00586 
00587 float BLF_width(int fontid, const char *str)
00588 {
00589     FontBLF *font= BLF_get(fontid);
00590 
00591     if (font && font->glyph_cache) {
00592         return blf_font_width(font, str);
00593     }
00594 
00595     return 0.0f;
00596 }
00597 
00598 float BLF_fixed_width(int fontid)
00599 {
00600     FontBLF *font= BLF_get(fontid);
00601 
00602     if (font && font->glyph_cache) {
00603         return blf_font_fixed_width(font);
00604     }
00605 
00606     return 0.0f;
00607 }
00608 
00609 float BLF_width_default(const char *str)
00610 {
00611     if (global_font_default == -1)
00612         global_font_default= blf_search("default");
00613 
00614     if (global_font_default == -1) {
00615         printf("Error: Can't found default font!!\n");
00616         return 0.0f;
00617     }
00618 
00619     BLF_size(global_font_default, global_font_points, global_font_dpi);
00620     return BLF_width(global_font_default, str);
00621 }
00622 
00623 float BLF_height(int fontid, const char *str)
00624 {
00625     FontBLF *font= BLF_get(fontid);
00626 
00627     if (font && font->glyph_cache) {
00628         return blf_font_height(font, str);
00629     }
00630 
00631     return 0.0f;
00632 }
00633 
00634 float BLF_height_max(int fontid)
00635 {
00636     FontBLF *font= BLF_get(fontid);
00637 
00638     if (font && font->glyph_cache) {
00639         return font->glyph_cache->max_glyph_height;
00640     }
00641 
00642     return 0.0f;
00643 }
00644 
00645 float BLF_width_max(int fontid)
00646 {
00647     FontBLF *font= BLF_get(fontid);
00648 
00649     if (font && font->glyph_cache) {
00650         return font->glyph_cache->max_glyph_width;
00651     }
00652 
00653     return 0.0f;
00654 }
00655 
00656 float BLF_descender(int fontid)
00657 {
00658     FontBLF *font= BLF_get(fontid);
00659 
00660     if (font && font->glyph_cache) {
00661         return font->glyph_cache->descender;
00662     }
00663 
00664     return 0.0f;
00665 }
00666 
00667 float BLF_ascender(int fontid)
00668 {
00669     FontBLF *font= BLF_get(fontid);
00670 
00671     if (font && font->glyph_cache) {
00672         return font->glyph_cache->ascender;
00673     }
00674 
00675     return 0.0f;
00676 }
00677 
00678 float BLF_height_default(const char *str)
00679 {
00680     if (global_font_default == -1)
00681         global_font_default= blf_search("default");
00682 
00683     if (global_font_default == -1) {
00684         printf("Error: Can't found default font!!\n");
00685         return 0.0f;
00686     }
00687 
00688     BLF_size(global_font_default, global_font_points, global_font_dpi);
00689 
00690     return BLF_height(global_font_default, str);
00691 }
00692 
00693 void BLF_rotation(int fontid, float angle)
00694 {
00695     FontBLF *font= BLF_get(fontid);
00696 
00697     if (font) {
00698         font->angle= angle;
00699     }
00700 }
00701 
00702 void BLF_clipping(int fontid, float xmin, float ymin, float xmax, float ymax)
00703 {
00704     FontBLF *font= BLF_get(fontid);
00705 
00706     if (font) {
00707         font->clip_rec.xmin= xmin;
00708         font->clip_rec.ymin= ymin;
00709         font->clip_rec.xmax= xmax;
00710         font->clip_rec.ymax= ymax;
00711     }
00712 }
00713 
00714 void BLF_clipping_default(float xmin, float ymin, float xmax, float ymax)
00715 {
00716     FontBLF *font= BLF_get(global_font_default);
00717 
00718     if (font) {
00719         font->clip_rec.xmin= xmin;
00720         font->clip_rec.ymin= ymin;
00721         font->clip_rec.xmax= xmax;
00722         font->clip_rec.ymax= ymax;
00723     }
00724 }
00725 
00726 void BLF_shadow(int fontid, int level, float r, float g, float b, float a)
00727 {
00728     FontBLF *font= BLF_get(fontid);
00729 
00730     if (font) {
00731         font->shadow= level;
00732         font->shadow_col[0]= r;
00733         font->shadow_col[1]= g;
00734         font->shadow_col[2]= b;
00735         font->shadow_col[3]= a;
00736     }
00737 }
00738 
00739 void BLF_shadow_offset(int fontid, int x, int y)
00740 {
00741     FontBLF *font= BLF_get(fontid);
00742 
00743     if (font) {
00744         font->shadow_x= x;
00745         font->shadow_y= y;
00746     }
00747 }
00748 
00749 void BLF_buffer(int fontid, float *fbuf, unsigned char *cbuf, int w, int h, int nch)
00750 {
00751     FontBLF *font= BLF_get(fontid);
00752 
00753     if (font) {
00754         font->b_fbuf= fbuf;
00755         font->b_cbuf= cbuf;
00756         font->bw= w;
00757         font->bh= h;
00758         font->bch= nch;
00759     }
00760 }
00761 
00762 void BLF_buffer_col(int fontid, float r, float g, float b, float a)
00763 {
00764     FontBLF *font= BLF_get(fontid);
00765 
00766     if (font) {
00767         font->b_col[0]= r;
00768         font->b_col[1]= g;
00769         font->b_col[2]= b;
00770         font->b_col[3]= a;
00771     }
00772 }
00773 
00774 void BLF_draw_buffer(int fontid, const char *str)
00775 {
00776     FontBLF *font= BLF_get(fontid);
00777 
00778     if (font && font->glyph_cache && (font->b_fbuf || font->b_cbuf)) {
00779         blf_font_buffer(font, str);
00780     }
00781 }