4 new function, boundbox, width, height and rotation.
[blender-staging.git] / source / blender / blenfont / intern / blf_font.c
index 8c7ec7a480f010829b003b88fd16a676eaa873da..825de7a62d2cec1eae92cb4d4f9a1ff4fb4f9218 100644 (file)
  * ***** END GPL LICENSE BLOCK *****
  */
 
-#if 0
-
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 
+#ifdef WITH_FREETYPE2
+
 #include <ft2build.h>
 
 #include FT_FREETYPE_H
 #include FT_GLYPH_H
 
+#endif /* WITH_FREETYPE2 */
+
 #include "MEM_guardedalloc.h"
 
 #include "DNA_listBase.h"
+#include "DNA_vec_types.h"
 
 #include "BKE_utildefines.h"
 
 #include "BLI_blenlib.h"
 #include "BLI_linklist.h"      /* linknode */
 #include "BLI_string.h"
+#include "BLI_arithb.h"
+
+#include "BIF_gl.h"
 
 #include "blf_internal_types.h"
+#include "blf_internal.h"
 
 
+#ifdef WITH_FREETYPE2
+
 /* freetype2 handle. */
 FT_Library global_ft_lib;
 
@@ -60,37 +69,16 @@ int blf_font_init(void)
 
 void blf_font_exit(void)
 {
-       FT_Done_Freetype(global_ft_lib);
+       FT_Done_FreeType(global_ft_lib);
 }
 
-FontBLF *blf_font_new(char *name)
+void blf_font_fill(FontBLF *font)
 {
-       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;
+       font->angle= 0.0f;
        Mat4One(font->mat);
        font->clip_rec.xmin= 0.0f;
        font->clip_rec.xmax= 0.0f;
@@ -103,6 +91,57 @@ FontBLF *blf_font_new(char *name)
        font->cache.last= NULL;
        font->glyph_cache= NULL;
        glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&font->max_tex_size);
+}
+
+FontBLF *blf_font_new(char *name, char *filename)
+{
+       FontBLF *font;
+       FT_Error err;
+
+       font= (FontBLF *)MEM_mallocN(sizeof(FontBLF), "blf_font_new");
+       err= FT_New_Face(global_ft_lib, filename, 0, &font->face);
+       if (err) {
+               MEM_freeN(font);
+               return(NULL);
+       }
+
+       err= FT_Select_Charmap(font->face, ft_encoding_unicode);
+       if (err) {
+               printf("Can't set the unicode character map!\n");
+               FT_Done_Face(font->face);
+               MEM_freeN(font);
+               return(NULL);
+       }
+
+       font->name= BLI_strdup(name);
+       font->filename= BLI_strdup(filename);
+       blf_font_fill(font);
+       return(font);
+}
+
+FontBLF *blf_font_new_from_mem(char *name, unsigned char *mem, int mem_size)
+{
+       FontBLF *font;
+       FT_Error err;
+
+       font= (FontBLF *)MEM_mallocN(sizeof(FontBLF), "blf_font_new_from_mem");
+       err= FT_New_Memory_Face(global_ft_lib, mem, mem_size, 0, &font->face);
+       if (err) {
+               MEM_freeN(font);
+               return(NULL);
+       }
+
+       err= FT_Select_Charmap(font->face, ft_encoding_unicode);
+       if (err) {
+               printf("Can't set the unicode character map!\n");
+               FT_Done_Face(font->face);
+               MEM_freeN(font);
+               return(NULL);
+       }
+
+       font->name= BLI_strdup(name);
+       font->filename= NULL;
+       blf_font_fill(font);
        return(font);
 }
 
@@ -114,7 +153,7 @@ void blf_font_size(FontBLF *font, int size, int dpi)
        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);
+               printf("The current font don't support the size, %d and dpi, %d\n", size, dpi);
                return;
        }
 
@@ -128,7 +167,157 @@ void blf_font_size(FontBLF *font, int size, int dpi)
                gc= blf_glyph_cache_new(font);
                if (gc)
                        font->glyph_cache= gc;
+               else
+                       font->glyph_cache= NULL;
+       }
+}
+
+void blf_font_draw(FontBLF *font, char *str)
+{
+       unsigned int c;
+       GlyphBLF *g, *g_prev;
+       FT_Vector delta;
+       FT_UInt glyph_index;
+       int pen_x, pen_y;
+       int i, has_kerning;
+
+       i= 0;
+       pen_x= 0;
+       pen_y= 0;
+       has_kerning= FT_HAS_KERNING(font->face);
+       g_prev= NULL;
+
+       while (str[i]) {
+               c= blf_utf8_next((unsigned char *)str, &i);
+               if (c == 0)
+                       break;
+
+               glyph_index= FT_Get_Char_Index(font->face, c);
+               g= blf_glyph_search(font->glyph_cache, glyph_index);
+               if (!g)
+                       g= blf_glyph_add(font, glyph_index, c);
+
+               /* if we don't found a glyph, skip it. */
+               if (!g)
+                       continue;
+
+               if (has_kerning && g_prev) {
+                       delta.x= 0;
+                       delta.y= 0;
+
+                       FT_Get_Kerning(font->face, g_prev->index, glyph_index, FT_KERNING_UNFITTED, &delta);
+                       pen_x += delta.x >> 6;
+               }
+
+               blf_glyph_render(g, (float)pen_x, (float)pen_y);
+               pen_x += g->advance;
+               g_prev= g;
        }
 }
 
-#endif /* zero!! */
+void blf_font_boundbox(FontBLF *font, char *str, rctf *box)
+{
+       unsigned int c;
+       GlyphBLF *g, *g_prev;
+       FT_Vector delta;
+       FT_UInt glyph_index;
+       rctf gbox;
+       int pen_x, pen_y;
+       int i, has_kerning;
+
+       box->xmin= 32000.0f;
+       box->xmax= -32000.0f;
+       box->ymin= 32000.0f;
+       box->ymax= -32000.0f;
+
+       i= 0;
+       pen_x= 0;
+       pen_y= 0;
+       has_kerning= FT_HAS_KERNING(font->face);
+       g_prev= NULL;
+
+       while (str[i]) {
+               c= blf_utf8_next((unsigned char *)str, &i);
+               if (c == 0)
+                       break;
+
+               glyph_index= FT_Get_Char_Index(font->face, c);
+               g= blf_glyph_search(font->glyph_cache, glyph_index);
+               if (!g)
+                       g= blf_glyph_add(font, glyph_index, c);
+
+               /* if we don't found a glyph, skip it. */
+               if (!g)
+                       continue;
+
+               if (has_kerning && g_prev) {
+                       delta.x= 0;
+                       delta.y= 0;
+
+                       FT_Get_Kerning(font->face, g_prev->index, glyph_index, FT_KERNING_UNFITTED, &delta);
+                       pen_x += delta.x >> 6;
+               }
+
+               gbox.xmin= g->box.xmin + pen_x;
+               gbox.xmax= g->box.xmax + pen_x;
+               gbox.ymin= g->box.ymin + pen_y;
+               gbox.ymax= g->box.ymax + pen_y;
+
+               if (gbox.xmin < box->xmin)
+                       box->xmin= gbox.xmin;
+               if (gbox.ymin < box->ymin)
+                       box->ymin= gbox.ymin;
+
+               if (gbox.xmax > box->xmax)
+                       box->xmax= gbox.xmax;
+               if (gbox.ymax > box->ymax)
+                       box->ymax= gbox.ymax;
+
+               pen_x += g->advance;
+               g_prev= g;
+       }
+
+       if (box->xmin > box->xmax) {
+               box->xmin= 0.0f;
+               box->ymin= 0.0f;
+               box->xmax= 0.0f;
+               box->ymax= 0.0f;
+       }
+}
+
+float blf_font_width(FontBLF *font, char *str)
+{
+       rctf box;
+
+       blf_font_boundbox(font, str, &box);
+       return((box.xmax - box.xmin) * font->aspect);
+}
+
+float blf_font_height(FontBLF *font, char *str)
+{
+       rctf box;
+
+       blf_font_boundbox(font, str, &box);
+       return((box.ymax - box.ymin) * font->aspect);
+}
+
+void blf_font_free(FontBLF *font)
+{
+       GlyphCacheBLF *gc;
+
+       font->glyph_cache= NULL;
+       while (font->cache.first) {
+               gc= font->cache.first;
+               BLI_remlink(&font->cache, gc);
+               blf_glyph_cache_free(gc);
+       }
+
+       FT_Done_Face(font->face);
+       if (font->filename)
+               MEM_freeN(font->filename);
+       if (font->name)
+               MEM_freeN(font->name);
+       MEM_freeN(font);
+}
+
+#endif /* WITH_FREETYPE2 */