svn merge -r40197:40311 ^/trunk/blender
[blender.git] / source / blender / blenfont / intern / blf_glyph.c
index 1174197dce7f861c15290e9fbde38d0ece7477be..7a1fa8c80b07aaee7121fd72d1721416fee81fb6 100644 (file)
@@ -1,5 +1,5 @@
-/**
- * $Id:
+/*
+ * $Id$
  *
  * ***** BEGIN GPL LICENSE BLOCK *****
  *
@@ -15,7 +15,7 @@
  *
  * 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.
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
  *
  * The Original Code is Copyright (C) 2009 Blender Foundation.
  * All rights reserved.
  * ***** END GPL LICENSE BLOCK *****
  */
 
+/** \file blender/blenfont/intern/blf_glyph.c
+ *  \ingroup blf
+ */
+
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
 #include FT_FREETYPE_H
 #include FT_GLYPH_H
 #include FT_OUTLINE_H
+#include FT_BITMAP_H
 
 #include "MEM_guardedalloc.h"
 
-#include "DNA_listBase.h"
 #include "DNA_vec_types.h"
-
-#include "BKE_utildefines.h"
+#include "DNA_userdef_types.h"
 
 #include "BLI_blenlib.h"
-#include "BLI_linklist.h"      /* linknode */
-#include "BLI_string.h"
 
 #include "BIF_gl.h"
 #include "BLF_api.h"
@@ -72,7 +74,6 @@ GlyphCacheBLF *blf_glyph_cache_find(FontBLF *font, int size, int dpi)
 GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
 {
        GlyphCacheBLF *gc;
-       int i;
 
        gc= (GlyphCacheBLF *)MEM_mallocN(sizeof(GlyphCacheBLF), "blf_glyph_cache_new");
        gc->next= NULL;
@@ -80,10 +81,8 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
        gc->size= font->size;
        gc->dpi= font->dpi;
 
-       for (i= 0; i < 257; i++) {
-               gc->bucket[i].first= NULL;
-               gc->bucket[i].last= NULL;
-       }
+       memset(gc->glyph_ascii_table, 0, sizeof(gc->glyph_ascii_table));
+       memset(gc->bucket, 0, sizeof(gc->bucket));
 
        gc->textures= (GLuint *)malloc(sizeof(GLuint)*256);
        gc->ntex= 256;
@@ -118,6 +117,27 @@ GlyphCacheBLF *blf_glyph_cache_new(FontBLF *font)
        return(gc);
 }
 
+void blf_glyph_cache_clear(FontBLF *font)
+{
+       GlyphCacheBLF *gc;
+       GlyphBLF *g;
+       int i;
+
+       for(gc=font->cache.first; gc; gc=gc->next) {
+               for (i= 0; i < 257; i++) {
+                       while (gc->bucket[i].first) {
+                               g= gc->bucket[i].first;
+                               BLI_remlink(&(gc->bucket[i]), g);
+                               blf_glyph_free(g);
+                       }
+               }
+       }
+
+       if(font->glyph_cache) {
+               memset(font->glyph_cache->glyph_ascii_table, 0, sizeof(font->glyph_cache->glyph_ascii_table));
+       }
+}
+
 void blf_glyph_cache_free(GlyphCacheBLF *gc)
 {
        GlyphBLF *g;
@@ -165,7 +185,7 @@ static void blf_glyph_cache_texture(FontBLF *font, GlyphCacheBLF *gc)
        memset((void *)buf, 0, tot_mem);
 
        glGenTextures(1, &gc->textures[gc->cur_tex]);
-       glBindTexture(GL_TEXTURE_2D, gc->textures[gc->cur_tex]);
+       glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state= gc->textures[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);
@@ -190,12 +210,13 @@ GlyphBLF *blf_glyph_search(GlyphCacheBLF *gc, unsigned int c)
        return(NULL);
 }
 
-GlyphBLF *blf_glyph_add(FontBLF *font, FT_UInt index, unsigned int c)
+GlyphBLF *blf_glyph_add(FontBLF *font, unsigned int index, unsigned int c)
 {
        FT_GlyphSlot slot;
        GlyphBLF *g;
        FT_Error err;
-       FT_Bitmap bitmap;
+       FT_Bitmap bitmap, tempbitmap;
+       int sharp = (U.text_render & USER_TEXT_DISABLE_AA);
        FT_BBox bbox;
        unsigned int key;
 
@@ -203,14 +224,29 @@ GlyphBLF *blf_glyph_add(FontBLF *font, FT_UInt index, unsigned int c)
        if (g)
                return(g);
 
-       err= FT_Load_Glyph(font->face, index, FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP);
+       if (sharp)
+               err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_MONO);
+       else
+               err = FT_Load_Glyph(font->face, (FT_UInt)index, FT_LOAD_TARGET_NORMAL | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP); /* Sure about NO_* flags? */
        if (err)
                return(NULL);
 
        /* get the glyph. */
        slot= font->face->glyph;
 
-       err= FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
+       if (sharp) {
+               err = FT_Render_Glyph(slot, FT_RENDER_MODE_MONO);
+
+               /* Convert result from 1 bit per pixel to 8 bit per pixel */
+               /* Accum errors for later, fine if not interested beyond "ok vs any error" */
+               FT_Bitmap_New(&tempbitmap);
+               err += FT_Bitmap_Convert(font->ft_lib, &slot->bitmap, &tempbitmap, 1); /* Does Blender use Pitch 1 always? It works so far */
+               err += FT_Bitmap_Copy(font->ft_lib, &tempbitmap, &slot->bitmap);
+               err += FT_Bitmap_Done(font->ft_lib, &tempbitmap);
+       } else {
+               err = FT_Render_Glyph(slot, FT_RENDER_MODE_NORMAL);
+       }
+
        if (err || slot->format != FT_GLYPH_FORMAT_BITMAP)
                return(NULL);
 
@@ -218,7 +254,7 @@ GlyphBLF *blf_glyph_add(FontBLF *font, FT_UInt index, unsigned int c)
        g->next= NULL;
        g->prev= NULL;
        g->c= c;
-       g->idx= index;
+       g->idx= (FT_UInt)index;
        g->tex= 0;
        g->build_tex= 0;
        g->bitmap= NULL;
@@ -233,6 +269,14 @@ GlyphBLF *blf_glyph_add(FontBLF *font, FT_UInt index, unsigned int c)
        g->height= bitmap.rows;
 
        if (g->width && g->height) {
+               if (sharp) {
+                       /* Font buffer uses only 0 or 1 values, Blender expects full 0..255 range */
+                       int i;
+                       for (i=0; i < (g->width * g->height); i++) {
+                               bitmap.buffer[i] = 255 * bitmap.buffer[i];
+                       }
+               }
+
                g->bitmap= (unsigned char *)MEM_mallocN(g->width * g->height, "glyph bitmap");
                memcpy((void *)g->bitmap, (void *)bitmap.buffer, g->width * g->height);
        }
@@ -282,23 +326,25 @@ static void blf_texture_draw(float uv[2][2], float dx, float y1, float dx1, floa
        
 }
 
-static void blf_texture5_draw(float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture5_draw(const float shadow_col[4], float uv[2][2], float x1, float y1, float x2, float y2)
 {
-       float soft[25]= {
-               1/60.0f, 1/60.0f, 2/60.0f, 1/60.0f, 1/60.0f, 
-               1/60.0f, 3/60.0f, 5/60.0f, 3/60.0f, 1/60.0f, 
-               2/60.0f, 5/60.0f, 8/60.0f, 5/60.0f, 2/60.0f, 
-               1/60.0f, 3/60.0f, 5/60.0f, 3/60.0f, 1/60.0f, 
-               1/60.0f, 1/60.0f, 2/60.0f, 1/60.0f, 1/60.0f};
+       float soft[25]= {1/60.0f, 1/60.0f, 2/60.0f, 1/60.0f, 1/60.0f,
+                        1/60.0f, 3/60.0f, 5/60.0f, 3/60.0f, 1/60.0f,
+                        2/60.0f, 5/60.0f, 8/60.0f, 5/60.0f, 2/60.0f,
+                        1/60.0f, 3/60.0f, 5/60.0f, 3/60.0f, 1/60.0f,
+                        1/60.0f, 1/60.0f, 2/60.0f, 1/60.0f, 1/60.0f};
        
        float color[4], *fp= soft;
        int dx, dy;
-       
-       glGetFloatv(GL_CURRENT_COLOR, color);
+
+       color[0]= shadow_col[0];
+       color[1]= shadow_col[1];
+       color[2]= shadow_col[2];
        
        for(dx=-2; dx<3; dx++) {
                for(dy=-2; dy<3; dy++, fp++) {
-                       glColor4f(color[0], color[1], color[2], fp[0]*color[3]);
+                       color[3]= *(fp) * shadow_col[3];
+                       glColor4fv(color);
                        blf_texture_draw(uv, x1+dx, y1+dy, x2+dx, y2+dy);
                }
        }
@@ -306,17 +352,23 @@ static void blf_texture5_draw(float uv[2][2], float x1, float y1, float x2, floa
        glColor4fv(color);
 }
 
-static void blf_texture3_draw(float uv[2][2], float x1, float y1, float x2, float y2)
+static void blf_texture3_draw(const float shadow_col[4], float uv[2][2], float x1, float y1, float x2, float y2)
 {
-       float soft[9]= {1/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 4/16.0f, 2/16.0f, 1/16.0f, 2/16.0f, 1/16.0f};
+       float soft[9]= {1/16.0f, 2/16.0f, 1/16.0f,
+                       2/16.0f,4/16.0f, 2/16.0f,
+                       1/16.0f, 2/16.0f, 1/16.0f};
+
        float color[4], *fp= soft;
        int dx, dy;
-       
-       glGetFloatv(GL_CURRENT_COLOR, color);
-       
+
+       color[0]= shadow_col[0];
+       color[1]= shadow_col[1];
+       color[2]= shadow_col[2];
+
        for(dx=-1; dx<2; dx++) {
                for(dy=-1; dy<2; dy++, fp++) {
-                       glColor4f(color[0], color[1], color[2], fp[0]*color[3]);
+                       color[3]= *(fp) * shadow_col[3];
+                       glColor4fv(color);
                        blf_texture_draw(uv, x1+dx, y1+dy, x2+dx, y2+dy);
                }
        }
@@ -326,18 +378,15 @@ static void blf_texture3_draw(float uv[2][2], float x1, float y1, float x2, floa
 
 int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
 {
-       GlyphCacheBLF *gc;
-       GLint cur_tex;
        float dx, dx1;
        float y1, y2;
        float xo, yo;
-       float color[4];
 
        if ((!g->width) || (!g->height))
                return(1);
 
        if (g->build_tex == 0) {
-               gc= font->glyph_cache;
+               GlyphCacheBLF *gc= font->glyph_cache;
 
                if (font->max_tex_size == -1)
                        glGetIntegerv(GL_MAX_TEXTURE_SIZE, (GLint *)&font->max_tex_size);
@@ -409,22 +458,27 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
                        return(0);
        }
 
-       glGetIntegerv(GL_TEXTURE_2D_BINDING_EXT, &cur_tex);
-       if (cur_tex != g->tex)
-               glBindTexture(GL_TEXTURE_2D, g->tex);
+       if (font->tex_bind_state != g->tex) {
+               glBindTexture(GL_TEXTURE_2D, (font->tex_bind_state= g->tex));
+       }
 
        if (font->flags & BLF_SHADOW) {
-               glGetFloatv(GL_CURRENT_COLOR, color);
-               glColor4fv(font->shadow_col);
-
-               if (font->shadow == 3)
-                       blf_texture3_draw(g->uv, dx, y1, dx1, y2);
-               else if (font->shadow == 5)
-                       blf_texture5_draw(g->uv, dx, y1, dx1, y2);
-               else
-                       blf_texture_draw(g->uv, dx, y1, dx1, y2);
 
-               glColor4fv(color);
+               switch(font->shadow) {
+                       case 3:
+                               blf_texture3_draw(font->shadow_col, g->uv, dx, y1, dx1, y2);
+                               break;
+                       case 5:
+                               blf_texture5_draw(font->shadow_col, g->uv, dx, y1, dx1, y2);
+                               break;
+                       default:
+                               glColor4fv(font->shadow_col);
+                               blf_texture_draw(g->uv, dx, y1, dx1, y2);
+                               break;
+               }
+
+               glColor4fv(font->orig_col);
+
                x= xo;
                y= yo;
 
@@ -434,12 +488,17 @@ int blf_glyph_render(FontBLF *font, GlyphBLF *g, float x, float y)
                y2= y + g->pos_y - g->height;
        }
 
-       if (font->blur==3)
-               blf_texture3_draw(g->uv, dx, y1, dx1, y2);
-       else if (font->blur==5)
-               blf_texture5_draw(g->uv, dx, y1, dx1, y2);
-       else
-               blf_texture_draw(g->uv, dx, y1, dx1, y2);
+       switch(font->blur) {
+               case 3:
+                       blf_texture3_draw(font->orig_col, g->uv, dx, y1, dx1, y2);
+                       break;
+               case 5:
+                       blf_texture5_draw(font->orig_col, g->uv, dx, y1, dx1, y2);
+                       break;
+               default:
+                       blf_texture_draw(g->uv, dx, y1, dx1, y2);
+                       break;
+       }
 
        return(1);
 }