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_vec_types.h" 00045 00046 00047 #include "BLI_blenlib.h" 00048 #include "BLI_linklist.h" /* linknode */ 00049 #include "BLI_math.h" 00050 00051 #include "BIF_gl.h" 00052 #include "BLF_api.h" 00053 00054 #include "blf_internal_types.h" 00055 #include "blf_internal.h" 00056 00057 00058 /* freetype2 handle ONLY for this file!. */ 00059 static FT_Library ft_lib; 00060 00061 int blf_font_init(void) 00062 { 00063 return FT_Init_FreeType(&ft_lib); 00064 } 00065 00066 void blf_font_exit(void) 00067 { 00068 FT_Done_FreeType(ft_lib); 00069 } 00070 00071 void blf_font_size(FontBLF *font, int size, int dpi) 00072 { 00073 GlyphCacheBLF *gc; 00074 FT_Error err; 00075 00076 err= FT_Set_Char_Size(font->face, 0, (size * 64), dpi, dpi); 00077 if (err) { 00078 /* FIXME: here we can go through the fixed size and choice a close one */ 00079 printf("The current font don't support the size, %d and dpi, %d\n", size, dpi); 00080 return; 00081 } 00082 00083 font->size= size; 00084 font->dpi= dpi; 00085 00086 gc= blf_glyph_cache_find(font, size, dpi); 00087 if (gc) 00088 font->glyph_cache= gc; 00089 else { 00090 gc= blf_glyph_cache_new(font); 00091 if (gc) 00092 font->glyph_cache= gc; 00093 else 00094 font->glyph_cache= NULL; 00095 } 00096 } 00097 00098 static void blf_font_ensure_ascii_table(FontBLF *font) 00099 { 00100 GlyphBLF **glyph_ascii_table= font->glyph_cache->glyph_ascii_table; 00101 00102 /* build ascii on demand */ 00103 if(glyph_ascii_table['0']==NULL) { 00104 GlyphBLF *g; 00105 unsigned int i; 00106 for(i=0; i<256; i++) { 00107 g= blf_glyph_search(font->glyph_cache, i); 00108 if (!g) { 00109 FT_UInt glyph_index= FT_Get_Char_Index(font->face, i); 00110 g= blf_glyph_add(font, glyph_index, i); 00111 } 00112 glyph_ascii_table[i]= g; 00113 } 00114 } 00115 } 00116 00117 /* Fast path for runs of ASCII characters. Given that common UTF-8 00118 * input will consist of an overwhelming majority of ASCII 00119 * characters. 00120 */ 00121 00122 /* Note, 00123 * blf_font_ensure_ascii_table(font); must be called before this macro */ 00124 00125 #define BLF_UTF8_NEXT_FAST(_font, _g, _str, _i, _c, _glyph_ascii_table) \ 00126 if(((_c)= (_str)[_i]) < 0x80) { \ 00127 _g= (_glyph_ascii_table)[_c]; \ 00128 _i++; \ 00129 } \ 00130 else if ((_c= BLI_str_utf8_as_unicode_step(_str, &(_i)))!=BLI_UTF8_ERR) { \ 00131 if ((_g= blf_glyph_search((_font)->glyph_cache, _c)) == NULL) { \ 00132 _g= blf_glyph_add(_font, \ 00133 FT_Get_Char_Index((_font)->face, _c), _c); \ 00134 } \ 00135 } \ 00136 00137 00138 #define BLF_KERNING_VARS(_font, _has_kerning, _kern_mode) \ 00139 const short _has_kerning= FT_HAS_KERNING((_font)->face); \ 00140 const FT_UInt _kern_mode= (_has_kerning == 0) ? 0 : \ 00141 (((_font)->flags & BLF_KERNING_DEFAULT) ? \ 00142 ft_kerning_default : FT_KERNING_UNFITTED) \ 00143 00144 00145 #define BLF_KERNING_STEP(_font, _kern_mode, _g_prev, _g, _delta, _pen_x) \ 00146 { \ 00147 if (_g_prev) { \ 00148 _delta.x= _delta.y= 0; \ 00149 if (FT_Get_Kerning((_font)->face, \ 00150 (_g_prev)->idx, \ 00151 (_g)->idx, \ 00152 _kern_mode, \ 00153 &(_delta)) == 0) \ 00154 { \ 00155 _pen_x += delta.x >> 6; \ 00156 } \ 00157 } \ 00158 } \ 00159 00160 void blf_font_draw(FontBLF *font, const char *str, unsigned int len) 00161 { 00162 unsigned int c; 00163 GlyphBLF *g, *g_prev= NULL; 00164 FT_Vector delta; 00165 int pen_x= 0, pen_y= 0; 00166 size_t i= 0; 00167 GlyphBLF **glyph_ascii_table= font->glyph_cache->glyph_ascii_table; 00168 00169 BLF_KERNING_VARS(font, has_kerning, kern_mode); 00170 00171 blf_font_ensure_ascii_table(font); 00172 00173 while (str[i] && i < len) { 00174 00175 BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table); 00176 00177 if (c == BLI_UTF8_ERR) break; 00178 if (g == NULL) continue; 00179 if (has_kerning) BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x); 00180 00181 /* do not return this loop if clipped, we want every character tested */ 00182 blf_glyph_render(font, g, (float)pen_x, (float)pen_y); 00183 00184 pen_x += g->advance; 00185 g_prev= g; 00186 } 00187 } 00188 00189 /* faster version of blf_font_draw, ascii only for view dimensions */ 00190 void blf_font_draw_ascii(FontBLF *font, const char *str, unsigned int len) 00191 { 00192 unsigned char c; 00193 GlyphBLF *g, *g_prev= NULL; 00194 FT_Vector delta; 00195 int pen_x= 0, pen_y= 0; 00196 GlyphBLF **glyph_ascii_table= font->glyph_cache->glyph_ascii_table; 00197 00198 BLF_KERNING_VARS(font, has_kerning, kern_mode); 00199 00200 blf_font_ensure_ascii_table(font); 00201 00202 while ((c= *(str++)) && len--) { 00203 if ((g= glyph_ascii_table[c]) == NULL) continue; 00204 if (has_kerning) BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x); 00205 00206 /* do not return this loop if clipped, we want every character tested */ 00207 blf_glyph_render(font, g, (float)pen_x, (float)pen_y); 00208 00209 pen_x += g->advance; 00210 g_prev= g; 00211 } 00212 } 00213 00214 /* Sanity checks are done by BLF_draw_buffer() */ 00215 void blf_font_buffer(FontBLF *font, const char *str) 00216 { 00217 unsigned int c; 00218 GlyphBLF *g, *g_prev= NULL; 00219 FT_Vector delta; 00220 int pen_x= (int)font->pos[0], pen_y= 0; 00221 size_t i= 0; 00222 GlyphBLF **glyph_ascii_table= font->glyph_cache->glyph_ascii_table; 00223 00224 /* buffer specific vars*/ 00225 const unsigned char b_col_char[4]= {font->b_col[0] * 255, 00226 font->b_col[1] * 255, 00227 font->b_col[2] * 255, 00228 font->b_col[3] * 255}; 00229 unsigned char *cbuf; 00230 int chx, chy; 00231 int y, x; 00232 float a, *fbuf; 00233 00234 BLF_KERNING_VARS(font, has_kerning, kern_mode); 00235 00236 blf_font_ensure_ascii_table(font); 00237 00238 while (str[i]) { 00239 00240 BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table); 00241 00242 if (c == BLI_UTF8_ERR) break; 00243 if (g == NULL) continue; 00244 if (has_kerning) BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x); 00245 00246 chx= pen_x + ((int)g->pos_x); 00247 chy= (int)font->pos[1] + g->height; 00248 00249 if (g->pitch < 0) { 00250 pen_y = (int)font->pos[1] + (g->height - (int)g->pos_y); 00251 } 00252 else { 00253 pen_y = (int)font->pos[1] - (g->height - (int)g->pos_y); 00254 } 00255 00256 if ((chx + g->width) >= 0 && chx < font->bw && (pen_y + g->height) >= 0 && pen_y < font->bh) { 00257 /* dont draw beyond the buffer bounds */ 00258 int width_clip= g->width; 00259 int height_clip= g->height; 00260 int yb_start= g->pitch < 0 ? 0 : g->height-1; 00261 00262 if (width_clip + chx > font->bw) width_clip -= chx + width_clip - font->bw; 00263 if (height_clip + pen_y > font->bh) height_clip -= pen_y + height_clip - font->bh; 00264 00265 /* drawing below the image? */ 00266 if(pen_y < 0) { 00267 yb_start += (g->pitch < 0) ? -pen_y : pen_y; 00268 height_clip += pen_y; 00269 pen_y= 0; 00270 } 00271 00272 if (font->b_fbuf) { 00273 int yb= yb_start; 00274 for (y=(chy >= 0 ? 0:-chy); y < height_clip; y++) { 00275 for (x=(chx >= 0 ? 0:-chx); x < width_clip; x++) { 00276 00277 a= *(g->bitmap + x + (yb * g->pitch)) / 255.0f; 00278 00279 if(a > 0.0f) { 00280 float alphatest; 00281 fbuf= font->b_fbuf + font->bch * ((chx + x) + ((pen_y + y)*font->bw)); 00282 if (a >= 1.0f) { 00283 fbuf[0]= font->b_col[0]; 00284 fbuf[1]= font->b_col[1]; 00285 fbuf[2]= font->b_col[2]; 00286 fbuf[3]= (alphatest= (fbuf[3] + (font->b_col[3]))) < 1.0f ? alphatest : 1.0f; 00287 } 00288 else { 00289 fbuf[0]= (font->b_col[0]*a) + (fbuf[0] * (1-a)); 00290 fbuf[1]= (font->b_col[1]*a) + (fbuf[1] * (1-a)); 00291 fbuf[2]= (font->b_col[2]*a) + (fbuf[2] * (1-a)); 00292 fbuf[3]= (alphatest= (fbuf[3] + (font->b_col[3]*a))) < 1.0f ? alphatest : 1.0f; 00293 } 00294 } 00295 } 00296 00297 if (g->pitch < 0) 00298 yb++; 00299 else 00300 yb--; 00301 } 00302 } 00303 00304 if (font->b_cbuf) { 00305 int yb= yb_start; 00306 for (y= 0; y < height_clip; y++) { 00307 for (x= 0; x < width_clip; x++) { 00308 a= *(g->bitmap + x + (yb * g->pitch)) / 255.0f; 00309 00310 if(a > 0.0f) { 00311 int alphatest; 00312 cbuf= font->b_cbuf + font->bch * ((chx + x) + ((pen_y + y)*font->bw)); 00313 if (a >= 1.0f) { 00314 cbuf[0]= b_col_char[0]; 00315 cbuf[1]= b_col_char[1]; 00316 cbuf[2]= b_col_char[2]; 00317 cbuf[3]= (alphatest= ((int)cbuf[3] + (int)b_col_char[3])) < 255 ? alphatest : 255; 00318 } 00319 else { 00320 cbuf[0]= (b_col_char[0]*a) + (cbuf[0] * (1-a)); 00321 cbuf[1]= (b_col_char[1]*a) + (cbuf[1] * (1-a)); 00322 cbuf[2]= (b_col_char[2]*a) + (cbuf[2] * (1-a)); 00323 cbuf[3]= (alphatest= ((int)cbuf[3] + (int)((font->b_col[3]*a)*255.0f))) < 255 ? alphatest : 255; 00324 } 00325 } 00326 } 00327 00328 if (g->pitch < 0) 00329 yb++; 00330 else 00331 yb--; 00332 } 00333 } 00334 } 00335 00336 pen_x += g->advance; 00337 g_prev= g; 00338 } 00339 } 00340 00341 void blf_font_boundbox(FontBLF *font, const char *str, rctf *box) 00342 { 00343 unsigned int c; 00344 GlyphBLF *g, *g_prev= NULL; 00345 FT_Vector delta; 00346 int pen_x= 0, pen_y= 0; 00347 size_t i= 0; 00348 GlyphBLF **glyph_ascii_table= font->glyph_cache->glyph_ascii_table; 00349 00350 rctf gbox; 00351 00352 BLF_KERNING_VARS(font, has_kerning, kern_mode); 00353 00354 box->xmin= 32000.0f; 00355 box->xmax= -32000.0f; 00356 box->ymin= 32000.0f; 00357 box->ymax= -32000.0f; 00358 00359 blf_font_ensure_ascii_table(font); 00360 00361 while (str[i]) { 00362 00363 BLF_UTF8_NEXT_FAST(font, g, str, i, c, glyph_ascii_table); 00364 00365 if (c == BLI_UTF8_ERR) break; 00366 if (g == NULL) continue; 00367 if (has_kerning) BLF_KERNING_STEP(font, kern_mode, g_prev, g, delta, pen_x); 00368 00369 gbox.xmin= pen_x; 00370 gbox.xmax= pen_x + g->advance; 00371 gbox.ymin= g->box.ymin + pen_y; 00372 gbox.ymax= g->box.ymax + pen_y; 00373 00374 if (gbox.xmin < box->xmin) box->xmin= gbox.xmin; 00375 if (gbox.ymin < box->ymin) box->ymin= gbox.ymin; 00376 00377 if (gbox.xmax > box->xmax) box->xmax= gbox.xmax; 00378 if (gbox.ymax > box->ymax) box->ymax= gbox.ymax; 00379 00380 pen_x += g->advance; 00381 g_prev= g; 00382 } 00383 00384 if (box->xmin > box->xmax) { 00385 box->xmin= 0.0f; 00386 box->ymin= 0.0f; 00387 box->xmax= 0.0f; 00388 box->ymax= 0.0f; 00389 } 00390 } 00391 00392 void blf_font_width_and_height(FontBLF *font, const char *str, float *width, float *height) 00393 { 00394 float xa, ya; 00395 rctf box; 00396 00397 if (font->flags & BLF_ASPECT) { 00398 xa= font->aspect[0]; 00399 ya= font->aspect[1]; 00400 } 00401 else { 00402 xa= 1.0f; 00403 ya= 1.0f; 00404 } 00405 00406 blf_font_boundbox(font, str, &box); 00407 *width= ((box.xmax - box.xmin) * xa); 00408 *height= ((box.ymax - box.ymin) * ya); 00409 } 00410 00411 float blf_font_width(FontBLF *font, const char *str) 00412 { 00413 float xa; 00414 rctf box; 00415 00416 if (font->flags & BLF_ASPECT) 00417 xa= font->aspect[0]; 00418 else 00419 xa= 1.0f; 00420 00421 blf_font_boundbox(font, str, &box); 00422 return (box.xmax - box.xmin) * xa; 00423 } 00424 00425 float blf_font_height(FontBLF *font, const char *str) 00426 { 00427 float ya; 00428 rctf box; 00429 00430 if (font->flags & BLF_ASPECT) 00431 ya= font->aspect[1]; 00432 else 00433 ya= 1.0f; 00434 00435 blf_font_boundbox(font, str, &box); 00436 return (box.ymax - box.ymin) * ya; 00437 } 00438 00439 float blf_font_fixed_width(FontBLF *font) 00440 { 00441 const unsigned int c = ' '; 00442 GlyphBLF *g= blf_glyph_search(font->glyph_cache, c); 00443 if (!g) { 00444 g= blf_glyph_add(font, FT_Get_Char_Index(font->face, c), c); 00445 00446 /* if we don't find the glyph. */ 00447 if (!g) { 00448 return 0.0f; 00449 } 00450 } 00451 00452 return g->advance; 00453 } 00454 00455 void blf_font_free(FontBLF *font) 00456 { 00457 GlyphCacheBLF *gc; 00458 00459 font->glyph_cache= NULL; 00460 while (font->cache.first) { 00461 gc= font->cache.first; 00462 BLI_remlink(&font->cache, gc); 00463 blf_glyph_cache_free(gc); 00464 } 00465 00466 FT_Done_Face(font->face); 00467 if (font->filename) 00468 MEM_freeN(font->filename); 00469 if (font->name) 00470 MEM_freeN(font->name); 00471 MEM_freeN(font); 00472 } 00473 00474 static void blf_font_fill(FontBLF *font) 00475 { 00476 unsigned int i; 00477 00478 font->aspect[0]= 1.0f; 00479 font->aspect[1]= 1.0f; 00480 font->aspect[2]= 1.0f; 00481 font->pos[0]= 0.0f; 00482 font->pos[1]= 0.0f; 00483 font->angle= 0.0f; 00484 00485 for (i= 0; i < 16; i++) 00486 font->m[i]= 0; 00487 00488 font->clip_rec.xmin= 0.0f; 00489 font->clip_rec.xmax= 0.0f; 00490 font->clip_rec.ymin= 0.0f; 00491 font->clip_rec.ymax= 0.0f; 00492 font->flags= 0; 00493 font->dpi= 0; 00494 font->size= 0; 00495 font->cache.first= NULL; 00496 font->cache.last= NULL; 00497 font->glyph_cache= NULL; 00498 font->blur= 0; 00499 font->max_tex_size= -1; 00500 font->b_fbuf= NULL; 00501 font->b_cbuf= NULL; 00502 font->bw= 0; 00503 font->bh= 0; 00504 font->bch= 0; 00505 font->b_col[0]= 0; 00506 font->b_col[1]= 0; 00507 font->b_col[2]= 0; 00508 font->b_col[3]= 0; 00509 font->ft_lib= ft_lib; 00510 } 00511 00512 FontBLF *blf_font_new(const char *name, const char *filename) 00513 { 00514 FontBLF *font; 00515 FT_Error err; 00516 char *mfile; 00517 00518 font= (FontBLF *)MEM_callocN(sizeof(FontBLF), "blf_font_new"); 00519 err= FT_New_Face(ft_lib, filename, 0, &font->face); 00520 if (err) { 00521 MEM_freeN(font); 00522 return NULL; 00523 } 00524 00525 err= FT_Select_Charmap(font->face, ft_encoding_unicode); 00526 if (err) { 00527 printf("Can't set the unicode character map!\n"); 00528 FT_Done_Face(font->face); 00529 MEM_freeN(font); 00530 return NULL; 00531 } 00532 00533 mfile= blf_dir_metrics_search(filename); 00534 if (mfile) { 00535 err= FT_Attach_File(font->face, mfile); 00536 if(err) { 00537 fprintf(stderr, "FT_Attach_File failed to load '%s' with error %d\n", filename, (int)err); 00538 } 00539 MEM_freeN(mfile); 00540 } 00541 00542 font->name= BLI_strdup(name); 00543 font->filename= BLI_strdup(filename); 00544 blf_font_fill(font); 00545 return font; 00546 } 00547 00548 void blf_font_attach_from_mem(FontBLF *font, const unsigned char *mem, int mem_size) 00549 { 00550 FT_Open_Args open; 00551 00552 open.flags= FT_OPEN_MEMORY; 00553 open.memory_base= (FT_Byte *)mem; 00554 open.memory_size= mem_size; 00555 FT_Attach_Stream(font->face, &open); 00556 } 00557 00558 FontBLF *blf_font_new_from_mem(const char *name, unsigned char *mem, int mem_size) 00559 { 00560 FontBLF *font; 00561 FT_Error err; 00562 00563 font= (FontBLF *)MEM_callocN(sizeof(FontBLF), "blf_font_new_from_mem"); 00564 err= FT_New_Memory_Face(ft_lib, mem, mem_size, 0, &font->face); 00565 if (err) { 00566 MEM_freeN(font); 00567 return NULL; 00568 } 00569 00570 err= FT_Select_Charmap(font->face, ft_encoding_unicode); 00571 if (err) { 00572 printf("Can't set the unicode character map!\n"); 00573 FT_Done_Face(font->face); 00574 MEM_freeN(font); 00575 return NULL; 00576 } 00577 00578 font->name= BLI_strdup(name); 00579 font->filename= NULL; 00580 blf_font_fill(font); 00581 return font; 00582 }