Blender V2.61 - r43446
|
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, ¶m); 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, ¶m); 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 }