From b9063b27a9376ca276cb80f692ef8fa923a966a7 Mon Sep 17 00:00:00 2001 From: Diego Borghetti Date: Mon, 9 Feb 2009 07:15:22 +0000 Subject: Just commit so I can continue tomorrow from work. All the code have #if 0 / #endif so nothing to worry about. --- source/blender/blenfont/BLF_api.h | 16 ++ source/blender/blenfont/intern/blf_dir.c | 171 +++++++++++++ source/blender/blenfont/intern/blf_font.c | 134 +++++++++++ source/blender/blenfont/intern/blf_glyph.c | 268 +++++++++++++++++++++ source/blender/blenfont/intern/blf_internal.h | 38 +++ .../blender/blenfont/intern/blf_internal_types.h | 147 +++++++++++ 6 files changed, 774 insertions(+) create mode 100644 source/blender/blenfont/intern/blf_dir.c create mode 100644 source/blender/blenfont/intern/blf_font.c create mode 100644 source/blender/blenfont/intern/blf_glyph.c create mode 100644 source/blender/blenfont/intern/blf_internal.h diff --git a/source/blender/blenfont/BLF_api.h b/source/blender/blenfont/BLF_api.h index 0a4ed0d7020..d91fbbf0fa9 100644 --- a/source/blender/blenfont/BLF_api.h +++ b/source/blender/blenfont/BLF_api.h @@ -49,4 +49,20 @@ int BLF_lang_error(void); /* Return the code string for the specified language code. */ char *BLF_lang_find_code(short langid); +#if 0 + +/* Add a path to the font dir paths. */ +void BLF_dir_add(const char *path); + +/* Remove a path from the font dir paths. */ +void BLF_dir_rem(const char *path); + +/* Return an array with all the font dir (this can be used for filesel) */ +char **BLF_dir_get(int *ndir); + +/* Free the data return by BLF_dir_get. */ +void BLF_dir_free(char **dirs, int count); + +#endif /* zero!! */ + #endif /* BLF_API_H */ diff --git a/source/blender/blenfont/intern/blf_dir.c b/source/blender/blenfont/intern/blf_dir.c new file mode 100644 index 00000000000..2472d36a1d8 --- /dev/null +++ b/source/blender/blenfont/intern/blf_dir.c @@ -0,0 +1,171 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#if 0 + +#include +#include +#include + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" + +#include "BKE_utildefines.h" + +#include "BLI_blenlib.h" +#include "BLI_linklist.h" /* linknode */ +#include "BLI_string.h" + +#include "blf_internal_types.h" + +static ListBase global_font_dir= { NULL, NULL }; + +DirBLF *blf_dir_find(const char *path) +{ + DirBLF *p; + + p= global_font_dir.first; + while (p) { + if (!strcmp(p->path, path)) + return(p); + p= p->next; + } + return(NULL); +} + +void BLF_dir_add(const char *path) +{ + DirBLF *dir; + + dir= blf_dir_find(path); + if (dir) /* already in the list ? just return. */ + return; + + dir= (DirBLF *)MEM_mallocN(sizeof(DirBLF), "BLF_dir_add"); + dir->path= BLI_strdup(path); + BLI_addhead(&global_font_dir, dir); +} + +void BLF_dir_rem(const char *path) +{ + DirBLF *dir; + + dir= blf_dir_find(path); + if (dir) { + BLI_remlink(&global_font_dir, dir); + MEM_freeN(dir->path); + MEM_freeN(dir); + } +} + +char **BLF_dir_get(int *ndir) +{ + DirBLF *p; + char **dirs; + char *path; + int i, count; + + count= BLI_countlist(&global_font_dir); + if (!count) + return(NULL); + + dirs= (char **)MEM_mallocN(sizeof(char *) * count, "BLF_dir_get"); + p= global_font_dir.first; + i= 0; + while (p) { + path= BLI_strdup(p->path); + dirs[i]= path; + p= p->next; + } + *ndir= i; + return(dirs); +} + +void BLF_dir_free(char **dirs, int count) +{ + char *path; + int i; + + for (i= 0; i < count; i++) { + path= dirs[i]; + MEM_freeN(path); + } + MEM_freeN(dirs); +} + +char *blf_dir_search(char *file) +{ + DirBLF *dir; + char full_path[FILE_MAXDIR+FILE_MAXFILE]; + char *s; + + dir= global_font_dir.first; + s= NULL; + while (dir) { + BLI_join_dirfile(full_path, dir->path, file); + if (BLI_exist(full_path)) { + s= (char *)MEM_mallocN(strlen(full_path)+1,"blf_dir_search"); + strcpy(s, full_path); + break; + } + dir= dir->next; + } + + if (!s) { + /* check the current directory, why not ? */ + if (BLI_exist(file)) + s= BLI_strdup(file); + } + + return(s); +} + +int blf_dir_split(const char *str, char *file, int *size) +{ + char *s, i, len; + + /* Window, Linux or Mac, this is always / */ + s= strrchr(str, '/'); + if (s) { + len= s - str; + for (i= 0; i < len; i++) + file[i]= str[i]; + + file[i]= '.'; + file[i+1]= 't'; + file[i+2]= 't'; + file[i+3]= 'f'; + file[i+4]= '\0'; + s++; + *size= atoi(s); + return(1); + } + return(0); +} + +#endif /* zero!! */ diff --git a/source/blender/blenfont/intern/blf_font.c b/source/blender/blenfont/intern/blf_font.c new file mode 100644 index 00000000000..8c7ec7a480f --- /dev/null +++ b/source/blender/blenfont/intern/blf_font.c @@ -0,0 +1,134 @@ +/** + * $Id: + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#if 0 + +#include +#include +#include + +#include + +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" + +#include "BKE_utildefines.h" + +#include "BLI_blenlib.h" +#include "BLI_linklist.h" /* linknode */ +#include "BLI_string.h" + +#include "blf_internal_types.h" + + +/* freetype2 handle. */ +FT_Library global_ft_lib; + +int blf_font_init(void) +{ + return(FT_Init_FreeType(&global_ft_lib)); +} + +void blf_font_exit(void) +{ + FT_Done_Freetype(global_ft_lib); +} + +FontBLF *blf_font_new(char *name) +{ + FontBLF *font; + FT_Error err; + + font= (FontBLF *)MEM_mallocN(sizeof(FontBLF), "blf_font_new"); + err= FT_New_Face(global_ft_lib, name, 0, &font->face); + if (err) { + MEM_freeN(font); + return(NULL); + } + + err= FT_Select_Charmap(font->face, ft_encoding_unicode); + if (err) { + printf("Warning: FT_Select_Charmap fail!!\n"); + FT_Done_Face(font->face); + MEM_freeN(font); + return(NULL); + } + + font->name= MEM_strdup(name); + font->ref= 1; + font->aspect= 1.0f; + font->pos[0]= 0.0f; + font->pos[1]= 0.0f; + font->angle[0]= 0.0f; + font->angle[1]= 0.0f; + font->angle[2]= 0.0f; + Mat4One(font->mat); + font->clip_rec.xmin= 0.0f; + font->clip_rec.xmax= 0.0f; + font->clip_rec.ymin= 0.0f; + font->clip_rec.ymax= 0.0f; + font->clip_mode= BLF_CLIP_DISABLE; + font->dpi= 0; + font->size= 0; + font->cache.first= NULL; + font->cache.last= NULL; + font->glyph_cache= NULL; + glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&font->max_tex_size); + return(font); +} + +void blf_font_size(FontBLF *font, int size, int dpi) +{ + GlyphCacheBLF *gc; + FT_Error err; + + err= FT_Set_Char_Size(font->face, 0, (size * 64), dpi, dpi); + if (err) { + /* FIXME: here we can go through the fixed size and choice a close one */ + printf("Warning: The current face don't support the size (%d) and dpi (%d)\n", size, dpi); + return; + } + + font->size= size; + font->dpi= dpi; + + gc= blf_glyph_cache_find(font, size, dpi); + if (gc) + font->glyph_cache= gc; + else { + gc= blf_glyph_cache_new(font); + if (gc) + font->glyph_cache= gc; + } +} + +#endif /* zero!! */ diff --git a/source/blender/blenfont/intern/blf_glyph.c b/source/blender/blenfont/intern/blf_glyph.c new file mode 100644 index 00000000000..bea49ccb387 --- /dev/null +++ b/source/blender/blenfont/intern/blf_glyph.c @@ -0,0 +1,268 @@ +/** + * $Id: + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * + * Contributor(s): Blender Foundation + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#if 0 + +#include +#include +#include + +#include + +#include FT_FREETYPE_H +#include FT_GLYPH_H + +#include "MEM_guardedalloc.h" + +#include "DNA_listBase.h" + +#include "BKE_utildefines.h" + +#include "BLI_blenlib.h" +#include "BLI_linklist.h" /* linknode */ +#include "BLI_string.h" + +#include "blf_internal_types.h" + + +unsigned int blf_glyph_hash(unsigned int val) +{ + unsigned int key; + + key= val; + key += ~(key << 16); + key ^= (key >> 5); + key += (key << 3); + key ^= (key >> 13); + key += ~(key << 9); + key ^= (key >> 17); + return(key % 257); +} + +GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, int size, int dpi) +{ + GlyphCacheBLF *p; + + p= (GlyphCacheBLF *)font->cache.first; + while (p) { + if (p->size == size && p->dpi == dpi) + return(p); + p= p->next; + } + return(NULL); +} + +/* Create a new glyph cache for the current size and dpi. */ +GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font) +{ + GlyphCacheBLF *gc; + int i; + + gc= (GlyphCacheBLF *)MEM_mallocN(sizeof(GlyphCacheBLF)); + gc->next= NULL; + gc->prev= NULL; + gc->size= font->size; + gc->dpi= font->dpi; + + for (i= 0; i < 257; i++) { + gc->bucket[i].first= NULL; + gc->bucket[i].last= NULL; + } + + gc->textures= (GLuint *)malloc(sizeof(GLunit)*256); + gc->ntex= 256; + gc->cur_tex= -1; + gc->x_offs= 0; + gc->y_offs= 0; + gc->pad= 3; + + gc->num_glyphs= font->face.num_glyphs; + gc->rem_glyphs= font->face.num_glyphs; + gc->ascender= ((float)font->size.metrics.ascender) / 64.0f; + gc->descender= ((float)font->size.metrics.descender) / 64.0f; + + if (FT_IS_SCALABLE(font->face)) { + gc->max_glyph_width= (float)((font->face->bbox.xMax - font->face->bbox.xMin) * + (((float)font->face->size.metrics.x_ppem) / + ((float)font->face->units_per_EM))); + + gc->max_glyph_height= (float)((font->face->bbox.yMax - font->face->bbox.yMin) * + (((float)font->face->size.metrics.y_ppem) / + ((float)font->face->units_per_EM))); + } + else { + gc->max_glyph_width= ((float)font->face->metrics.max_advance) / 64.0f; + gc->max_glyph_height= ((float)font->face->size.metrics.height) / 64.0f; + } + + gc->p2_width= 0; + gc->p2_height= 0; + + BLI_addhead(&font->cache, gc); + return(gc); +} + +void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc) +{ + int tot_mem; + unsigned char *buf; + + /* move the index. */ + gc->cur_tex++; + + if (gc->cur_tex > gc->ntex) { + gc->ntex *= 2; + gc->textures= (GLuint *)realloc((void *)gc->textures, sizeof(GLunit)*gc->ntex); + } + + gc->p2_width= blf_next_p2((gc->rem_glyphs * gc->max_glyph_width) + (gc->pad * 2)); + if (gc->p2_width > font->max_tex_size) + gc->p2_width= font->max_tex_size; + + i= (int)((gc->p2_width - (gc->pad * 2)) / gc->p2_width); + gc->p2_height= blf_next_p2(((gc->num_glyphs / i) + 1) * gc->max_glyph_height); + + if (gc->p2_height > font->max_tex_size) + gc->p2_height= font->max_tex_size; + + tot_mem= gc->p2_width * gc->p2_height; + buf= (unsigned char *)malloc(tot_mem); + memset((void *)buf, 0, tot_mem); + + glGenTextures(1, (GLuint*)gc->texures[gc->cur_tex]); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, gc->p2_width, gc->p2_height, 0, GL_ALPHA, GL_UNSIGNED_BYTE, buf); + free((void *)buf); +} + +GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, FT_UInt idx) +{ + GlyphBLF *p; + unsigned int key; + + key= blf_glyph_hash(idx); + p= gc->bucket[key].first; + while (p) { + if (p->index == idx) + return(p); + p= p->next; + } + return(NULL); +} + +GlyphBLF *blf_glyph_add(FontBLF *font, FT_UInt index, unsigned int c) +{ + FT_GlyphSlot slot; + GlyphCache *gc; + GlyphBLF *g; + FT_Error err; + FT_Bitmap bitmap; + FTBBox bbox; + unsigned int key; + + g= blf_glyph_search(font->glyph_cache, index); + if (g) + return(g); + + err= FT_Load_Glyph(font->face, index, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP); + if (err) + return(NULL); + + /* get the glyph. */ + slot= font->face->glyph; + + err= FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL); + if (err) + return(NULL); + + g= (GlyphBLF *)MEM_mallocN(sizeof(GlyphBLF), "blf_glyph_add"); + g->next= NULL; + g->prev= NULL; + g->c= c; + g->index= index; + + gc= font->glyph_cache; + if (gc->cur_tex == -1) { + blf_glyph_cache_texture(font, gc); + gc->x_offs= gc->pad; + gc->y_offs= gc->pad; + } + + if (gc->x_offs > (gc->p2_width - gc->max_glyph_width)) { + gc->x_offs= gc->pad; + gc->y_offs += gc->max_glyph_height; + + if (gc->y_offs > (gc->p2_height - gc->max_glyph_height)) { + gc->y_offs= gc->pad; + blf_glyph_cache_texture(font, gc); + } + } + + bitmap= slot->bitmap; + g->tex= gc->textures[gc->cur_tex]; + g->xoff= gc->x_offs; + g->yoff= gc->y_offs; + g->width= bitmap.width; + g->height= bitmap.rows; + + if (g->width && g->height) { + glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT); + glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + glBindTexture(GL_TEXTURE_2D, g->tex); + glTexSubImage2D(GL_TEXTURE_2D, 0, g->xoff, g->yoff, g->width, g->height, GL_ALPHA, GL_UNSIGNED_BYTE, bitmap.buffer); + glPopClientAttrib(); + } + + g->advance= ((float)slot->advance.x) / 64.0f; + g->pos_x= bitmap.left; + g->pos_y= bitmap.top; + + FT_Outline_Get_CBox(&(slot->outline), &bbox); + g->box.xmin= ((float)bbox.xMin) / 64.0f; + g->box.xmax= ((float)bbox.xMax) / 64.0f; + g->box.ymin= ((float)bbox.yMin) / 64.0f; + g->box.ymax= ((float)bbox.yMax) / 64.0f; + + g->uv[0][0]= ((float)g->xoff) / ((float)g->p2_width); + g->uv[0][1]= ((float)g->yoff) / ((float)g->p2_height); + g->uv[1][0]= ((float)(g->xoff + g->width)) / ((float)g->p2_width); + g->uv[1][1]= ((float)(g->yoff + g->height)) / ((float)g->p2_height); + + key= blf_glyph_hash(g->index); + BLI_addhead(&gc->bucket[key], g); + return(g); +} + +#endif /* zero!! */ diff --git a/source/blender/blenfont/intern/blf_internal.h b/source/blender/blenfont/intern/blf_internal.h new file mode 100644 index 00000000000..b88c83e4b13 --- /dev/null +++ b/source/blender/blenfont/intern/blf_internal.h @@ -0,0 +1,38 @@ +/** + * $Id$ + * + * ***** BEGIN GPL LICENSE BLOCK ***** + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + * + * The Original Code is Copyright (C) 2009 Blender Foundation. + * All rights reserved. + * + * Contributor(s): Blender Foundation. + * + * ***** END GPL LICENSE BLOCK ***** + */ + +#ifndef BLF_INTERNAL_H +#define BLF_INTERNAL_H + +#if 0 + +char *blf_dir_search(const char *file); +int blf_dir_split(const char *str, char *file, int *size); + +#endif /* zero! */ + +#endif /* BLF_INTERNAL_H */ diff --git a/source/blender/blenfont/intern/blf_internal_types.h b/source/blender/blenfont/intern/blf_internal_types.h index 3a8c1bca3f5..b9ae9dfdac7 100644 --- a/source/blender/blenfont/intern/blf_internal_types.h +++ b/source/blender/blenfont/intern/blf_internal_types.h @@ -28,6 +28,149 @@ #ifndef BLF_INTERNAL_TYPES_H #define BLF_INTERNAL_TYPES_H +#if 0 + +typedef struct DirBLF { + struct DirBLF *next; + struct DirBLF *prev; + + /* full path where search fonts. */ + char *path; +} DirBLF; + +typedef struct _GlyphCacheBLF { + struct _GlyphCacheBLF *next; + struct _GlyphCacheBLF *prev; + + /* font size. */ + int size; + + /* and dpi. */ + int dpi; + + /* and the glyphs. */ + ListBase bucket[257]; + + /* texture array, to draw the glyphs. */ + GLuint *textures; + + /* size of the array. */ + int ntex; + + /* and the last texture, aka. the current texture. */ + int cur_tex; + + /* like bftgl, we draw every glyph in a big texture, so this is the + * current position inside the texture. + */ + int x_offs; + int y_offs; + + /* and the space from one to other. */ + unsigned int pad; + + /* and the bigger glyph in the font. */ + int max_glyph_width; + int max_glyph_height; + + /* next two integer power of two, to build the texture. */ + int p2_width; + int p2_height; + + /* number of glyphs in the font. */ + int num_glyphs; + + /* number of glyphs that we load here. */ + int rem_glyphs; + + /* ascender and descender value. */ + float ascender; + float descender; +} GlyphCacheBLF; + +typedef struct _GlyphBLF { + struct _GlyphBLF *next; + struct _GlyphBLF *prev; + + /* and the character, as UTF8 */ + unsigned int c; + + /* Freetype2 index. */ + FT_UInt index; + + /* texture id where this glyph is store. */ + GLuint tex; + + /* position inside the texture where this glyph is store. */ + int xoff; + int yoff; + + /* glyph width and height. */ + int width; + int height; + + /* glyph bounding box. */ + rctf box; + + /* uv coords. */ + float uv[2][2]; + + /* advance value. */ + float advance; + + /* X and Y bearing of the glyph. + * The X bearing is from the origin to the glyph left bbox edge. + * The Y bearing is from the baseline to the top of the glyph edge. + */ + float pos_x; + float pos_y; +} GlyphBLF; + +typedef struct FontBLF { + char *name; + + /* reference count. */ + int ref; + + /* aspect ratio or scale. */ + float aspect; + + /* initial position for draw the text. */ + float pos[3]; + + /* angle in degrees. */ + float angle[3]; + + /* this is the matrix that we load before rotate/scale/translate. */ + float mat[4][4]; + + /* clipping rectangle. */ + rctf clip_rec; + + /* and clipping mode. */ + int clip_mode; + + /* font dpi (default 72). */ + int dpi; + + /* font size. */ + int size; + + /* max texture size. */ + int max_tex_size; + + /* freetype2 face. */ + FT_Face face; + + /* list of glyph cache for this font. */ + ListBase cache; + + /* current glyph cache, size and dpi. */ + GlyphCacheBLF *glyph_cache; +} FontBLF; + +#endif /* zero!! */ + typedef struct LangBLF { struct LangBLF *next; struct LangBLF *prev; @@ -42,4 +185,8 @@ typedef struct LangBLF { #define BLF_LANG_FIND_BY_LANGUAGE 1 #define BLF_LANG_FIND_BY_CODE 2 +/* font->clip_mode */ +#define BLF_CLIP_DISABLE 0 +#define BLF_CLIP_OUT 1 + #endif /* BLF_INTERNAL_TYPES_H */ -- cgit v1.2.3