2.50: svn merge https://svn.blender.org/svnroot/bf-blender/trunk/blender -r19323...
[blender.git] / source / blender / blenlib / intern / freetypefont.c
index 4acc623450013c99246ea891315db399ef9845e0..4b7b5914b60f6dd2fd944ebcf8e3f75c2ef6fd43 100644 (file)
@@ -1,15 +1,12 @@
 /**
  * $Id$
  *
- * ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
+ * ***** 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. The Blender
- * Foundation also sells licenses for use in proprietary software under
- * the Blender License.  See http://www.blender.org/BL/ for information
- * about this.
+ * 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
@@ -25,7 +22,7 @@
  *
  * Contributor(s): none yet.
  *
- * ***** END GPL/BL DUAL LICENSE BLOCK *****
+ * ***** END GPL LICENSE BLOCK *****
  *
  * This code parses the Freetype font outline data to chains of Blender's beziertriples.
  * Additional information can be found at the bottom of this file.
@@ -42,6 +39,8 @@
 #include <ft2build.h>
 #include FT_FREETYPE_H
 #include FT_GLYPH_H
+#include FT_BBOX_H
+#include FT_SIZES_H
 #include <freetype/ttnameid.h>
 
 #include "MEM_guardedalloc.h"
 #include "BLI_blenlib.h"
 #include "BLI_arithb.h"  
 
-#include "BIF_toolbox.h"
+//XXX #include "BIF_toolbox.h"
 
+#include "BKE_global.h"
+#include "BKE_font.h"
 #include "BKE_utildefines.h"
 
+#include "DNA_vfont_types.h"
 #include "DNA_packedFile_types.h"
 #include "DNA_curve_types.h"
 
@@ -65,75 +67,54 @@ static FT_Library   library;
 static FT_Error                err;
 
 
-static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
+void freetypechar_to_vchar(FT_Face face, FT_ULong charcode, VFontData *vfd)
 {
        // Blender
-       VFontData *vfd;
        struct Nurb *nu;
+       struct VChar *che;
        struct BezTriple *bezt;
-
+       
        // Freetype2
-       FT_Face         face;
-       FT_GlyphSlot  glyph;
-       FT_UInt         glyph_index;
-       FT_Outline      ftoutline;
-/*
-    FT_CharMap  found = 0;
-       FT_CharMap  charmap;
-       FT_UShort my_platform_id = TT_PLATFORM_MICROSOFT;
-       FT_UShort my_encoding_id = TT_MS_ID_UNICODE_CS;
-       int         n;
-*/
-       //scale needs text_height from freetype metrics to make a standard linedist,
-       //is currently set to generic value
-       float scale= 1. / 1024.;
+       FT_GlyphSlot glyph;
+       FT_UInt glyph_index;
+       FT_Outline ftoutline;
+       float scale, height;
        float dx, dy;
-       int i, j, k, l, m;
-
-       // load the freetype font
-       err = FT_New_Memory_Face( library,
-                                               pf->data,
-                                               pf->size,
-                                               0,
-                                               &face );
-
-       if(err) return NULL;
-/*
-    for ( n = 0; n < face->num_charmaps; n++ )
-    {
-      charmap = face->charmaps[n];
-      if ( charmap->platform_id == my_platform_id &&
-           charmap->encoding_id == my_encoding_id )
-      {
-        found = charmap;
-        break;
-      }
-    }
-
-    if ( !found ) { return NULL; }
-
-    // now, select the charmap for the face object
-    err = FT_Set_Charmap( face, found );
-    if ( err ) { return NULL; }
-*/
-
-       // allocate blender font
-       vfd= MEM_callocN(sizeof(*vfd), "FTVFontData");
-       strcpy(vfd->name, FT_Get_Postscript_Name(face)); 
-
-       // extract generic ascii character range
-       for(i = myMIN_ASCII; i <= myMAX_ASCII; i++) {
-
-               int  *npoints;  //total points of each contour
-               int  *onpoints; //num points on curve
-
-               glyph_index = FT_Get_Char_Index( face, i );
-               err = FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
-               glyph = face->glyph;
-               ftoutline = glyph->outline;
-
-               vfd->width[i] = glyph->advance.x* scale;
-
+       int j,k,l,m=0;
+       
+       // adjust font size
+       height= ((double) face->bbox.yMax - (double) face->bbox.yMin);
+       if(height != 0.0)
+               scale = 1.0 / height;
+       else
+               scale = 1.0 / 1000.0;
+       
+       //      
+       // Generate the character 3D data
+       //
+       // Get the FT Glyph index and load the Glyph
+       glyph_index= FT_Get_Char_Index(face, charcode);
+       err= FT_Load_Glyph(face, glyph_index, FT_LOAD_NO_SCALE | FT_LOAD_NO_BITMAP);
+       
+       // If loading succeeded, convert the FT glyph to the internal format
+       if(!err)
+       {
+               int *npoints;
+               int *onpoints;
+               
+               // First we create entry for the new character to the character list
+               che= (VChar *) MEM_callocN(sizeof(struct VChar), "objfnt_char");
+               BLI_addtail(&vfd->characters, che);
+               
+               // Take some data for modifying purposes
+               glyph= face->glyph;
+               ftoutline= glyph->outline;
+               
+               // Set the width and character code
+               che->index= charcode;
+               che->width= glyph->advance.x * scale;
+               
+               // Start converting the FT data
                npoints = (int *)MEM_callocN((ftoutline.n_contours)* sizeof(int),"endpoints") ;
                onpoints = (int *)MEM_callocN((ftoutline.n_contours)* sizeof(int),"onpoints") ;
 
@@ -150,9 +131,8 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
                        l = 0;
                        for(k = 0; k < npoints[j]; k++) {
                                if(j > 0) l = k + ftoutline.contours[j - 1] + 1; else l = k;
-
-                               if(ftoutline.tags[l] == FT_Curve_Tag_On)
-                                       onpoints[j]++;
+                                       if(ftoutline.tags[l] == FT_Curve_Tag_On)
+                                               onpoints[j]++;
 
                                if(k < npoints[j] - 1 )
                                        if( ftoutline.tags[l]   == FT_Curve_Tag_Conic &&
@@ -166,21 +146,22 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
                        // add new curve
                        nu  =  (Nurb*)MEM_callocN(sizeof(struct Nurb),"objfnt_nurb");
                        bezt = (BezTriple*)MEM_callocN((onpoints[j])* sizeof(BezTriple),"objfnt_bezt") ;
-                       BLI_addtail(&vfd->nurbsbase[i], nu);
+                       BLI_addtail(&che->nurbsbase, nu);
 
                        nu->type= CU_BEZIER+CU_2D;
                        nu->pntsu = onpoints[j];
                        nu->resolu= 8;
-                       nu->flagu= 1;
+                       nu->flagu= CU_CYCLIC;
                        nu->bezt = bezt;
 
                        //individual curve loop, start-end
                        for(k = 0; k < npoints[j]; k++) {
                                if(j > 0) l = k + ftoutline.contours[j - 1] + 1; else l = k;
                                if(k == 0) m = l;
-                               
+                                       
                                //virtual conic on-curve points
                                if(k < npoints[j] - 1 )
+                               {
                                        if( ftoutline.tags[l] == FT_Curve_Tag_Conic && ftoutline.tags[l+1] == FT_Curve_Tag_Conic) {
                                                dx = (ftoutline.points[l].x + ftoutline.points[l+1].x)* scale / 2.0;
                                                dy = (ftoutline.points[l].y + ftoutline.points[l+1].y)* scale / 2.0;
@@ -198,8 +179,10 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
                                                bezt->vec[2][1] = (dy + (2 * ftoutline.points[l+1].y)* scale) / 3.0;
 
                                                bezt->h1= bezt->h2= HD_ALIGN;
+                                               bezt->radius= 1.0f;
                                                bezt++;
                                        }
+                               }
 
                                //on-curve points
                                if(ftoutline.tags[l] == FT_Curve_Tag_On) {
@@ -283,15 +266,143 @@ static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
                                        {
                                                bezt->h1= bezt->h2= HD_ALIGN;
                                        }
+                                       bezt->radius= 1.0f;
                                        bezt++;
                                }
                        }
                }
-
                if(npoints) MEM_freeN(npoints);
-               if(onpoints) MEM_freeN(onpoints);
+               if(onpoints) MEM_freeN(onpoints);       
        }
-       return vfd;
+}
+
+int objchr_to_ftvfontdata(VFont *vfont, FT_ULong charcode)
+{
+       // Freetype2
+       FT_Face face;
+       struct TmpFont *tf;
+       
+       // Find the correct FreeType font
+       tf= vfont_find_tmpfont(vfont);
+       
+       // What, no font found. Something strange here
+       if(!tf) return FALSE;
+       
+       // Load the font to memory
+       if(tf->pf)
+       {
+               err= FT_New_Memory_Face( library,
+                       tf->pf->data,
+                       tf->pf->size,
+                       0,
+                       &face);                 
+       }
+       else
+               err= TRUE;
+               
+       // Read the char
+       freetypechar_to_vchar(face, charcode, vfont->data);
+       
+       // And everything went ok
+       return TRUE;
+}
+
+
+static VFontData *objfnt_to_ftvfontdata(PackedFile * pf)
+{
+       // Variables
+       FT_Face face;
+       FT_ULong charcode = 0, lcode;
+       FT_UInt glyph_index;
+       const char *fontname;
+       VFontData *vfd;
+
+/*
+       FT_CharMap  found = 0;
+       FT_CharMap  charmap;
+       FT_UShort my_platform_id = TT_PLATFORM_MICROSOFT;
+       FT_UShort my_encoding_id = TT_MS_ID_UNICODE_CS;
+       int         n;
+*/
+
+       // load the freetype font
+       err = FT_New_Memory_Face( library,
+                                               pf->data,
+                                               pf->size,
+                                               0,
+                                               &face );
+
+       if(err) return NULL;
+/*
+       for ( n = 0; n < face->num_charmaps; n++ )
+       {
+               charmap = face->charmaps[n];
+               if ( charmap->platform_id == my_platform_id &&
+                       charmap->encoding_id == my_encoding_id )
+               {
+                       found = charmap;
+                       break;
+               }
+       }
+
+       if ( !found ) { return NULL; }
+
+       // now, select the charmap for the face object
+       err = FT_Set_Charmap( face, found );
+       if ( err ) { return NULL; }
+*/
+
+       // allocate blender font
+       vfd= MEM_callocN(sizeof(*vfd), "FTVFontData");
+
+       // get the name
+       fontname = FT_Get_Postscript_Name(face);
+       strcpy(vfd->name, (fontname == NULL) ? "Fontname not available" : fontname);
+
+       // Extract the first 256 character from TTF
+       lcode= charcode= FT_Get_First_Char(face, &glyph_index);
+
+       // No charmap found from the ttf so we need to figure it out
+       if(glyph_index == 0)
+       {
+               FT_CharMap  found = 0;
+               FT_CharMap  charmap;
+               int n;
+
+               for ( n = 0; n < face->num_charmaps; n++ )
+               {
+                       charmap = face->charmaps[n];
+                       if (charmap->encoding == FT_ENCODING_APPLE_ROMAN)
+                       {
+                               found = charmap;
+                               break;
+                       }
+               }
+
+               err = FT_Set_Charmap( face, found );
+
+               if( err ) 
+                       return NULL;
+
+               lcode= charcode= FT_Get_First_Char(face, &glyph_index);
+       }
+
+       // Load characters
+       while(charcode < 256)
+       {
+               // Generate the font data
+               freetypechar_to_vchar(face, charcode, vfd);
+
+               // Next glyph
+               charcode = FT_Get_Next_Char(face, charcode, &glyph_index);
+
+               // Check that we won't start infinite loop
+               if(charcode <= lcode)
+                       break;
+               lcode = charcode;
+       }
+
+       return vfd;     
 }
 
 
@@ -316,7 +427,7 @@ static int check_freetypefont(PackedFile * pf)
                                                        &face );
        if(err) {
                success = 0;
-           error("This is not a valid font");
+           //XXX error("This is not a valid font");
        }
        else {
 /*
@@ -345,7 +456,7 @@ static int check_freetypefont(PackedFile * pf)
                        if (glyph->format == ft_glyph_format_outline ) {
                                success = 1;
                        } else {
-                               error("Selected Font has no outline data");
+                               //XXX error("Selected Font has no outline data");
                                success = 0;
                        }
                }
@@ -363,7 +474,7 @@ VFontData *BLI_vfontdata_from_freetypefont(PackedFile *pf)
        //init Freetype 
        err = FT_Init_FreeType( &library);
        if(err) {
-           error("Failed to load the Freetype font library");
+               //XXX error("Failed to load the Freetype font library");
                return 0;
        }
 
@@ -379,6 +490,30 @@ VFontData *BLI_vfontdata_from_freetypefont(PackedFile *pf)
        return vfd;
 }
 
+int BLI_vfontchar_from_freetypefont(VFont *vfont, unsigned long character)
+{
+       int success = FALSE;
+
+       if(!vfont) return FALSE;
+
+       // Init Freetype
+       err = FT_Init_FreeType(&library);
+       if(err) {
+               //XXX error("Failed to load the Freetype font library");
+               return 0;
+       }
+
+       // Load the character
+       success = objchr_to_ftvfontdata(vfont, character);
+       if(success == FALSE) return FALSE;
+
+       // Free Freetype
+       FT_Done_FreeType(library);
+
+       // Ahh everything ok
+       return TRUE;
+}
+
 #endif // WITH_FREETYPE2