]> git.wh0rd.org - fontconfig.git/blobdiff - src/fcfreetype.c
Add Low Saxon orthography (Kenneth Rohde Christiansen <kenneth@gnu.org>)
[fontconfig.git] / src / fcfreetype.c
index 5f032e14ae1057a41b7739d30fbf91bde228895e..75da7357424dcf105d0f5b8bc29ca1865faff768 100644 (file)
 #include <stdio.h>
 #include <string.h>
 #include "fcint.h"
-#include <freetype/freetype.h>
-#include <freetype/internal/ftobjs.h>
-#include <freetype/tttables.h>
-#include <freetype/ftsnames.h>
-#include <freetype/ttnameid.h>
-#include <freetype/t1tables.h>
-
-#if (FREETYPE_MINOR > 1 || (FREETYPE_MINOR == 1 && FREETYPE_PATCH >= 4))
-#include <freetype/ftbdf.h>
-#include <freetype/ftmodule.h>
-#define USE_FTBDF
+#include <ft2build.h>
+#include FT_FREETYPE_H
+#include FT_INTERNAL_OBJECTS_H
+#include FT_TRUETYPE_TABLES_H
+#include FT_SFNT_NAMES_H
+#include FT_TRUETYPE_IDS_H
+#include FT_TYPE1_TABLES_H
+
+#if HAVE_FT_GET_BDF_PROPERTY
+#include FT_BDF_H
+#include FT_MODULE_H
 #define HAS_BDF_PROPERTY(f) ((f) && (f)->driver && \
                             (f)->driver->root.clazz->get_interface)
 #define MY_Get_BDF_Property(f,n,p) (HAS_BDF_PROPERTY(f) ? \
                                    FT_Err_Invalid_Argument)
 #endif
 
+#if !HAVE_FT_GET_BDF_PROPERTY
+#warning "No FT_Get_BDF_Property"
+#endif
+
+#if !HAVE_FT_GET_PS_FONT_INFO
+#warning "No FT_Get_Font_Info"
+#endif
 
 /*
  * Keep Han languages separated by eliminating languages
@@ -337,6 +344,23 @@ static const FcStringConst  slantConsts[] = {
 #define FcIsSlant(s)       FcStringIsConst(s,slantConsts,NUM_SLANT_CONSTS)
 #define FcContainsSlant(s)  FcStringContainsConst (s,slantConsts,NUM_SLANT_CONSTS)
 
+static double
+FcGetPixelSize (FT_Face face, int i)
+{
+#ifdef HAVE_FT_GET_BDF_PROPERTY
+    if (face->num_fixed_sizes == 1)
+    {
+       BDF_PropertyRec prop;
+       int             rc;
+
+       rc = MY_Get_BDF_Property (face, "PIXEL_SIZE", &prop);
+       if (rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
+           return (double) prop.u.integer;
+    }
+#endif
+    return (double) face->available_sizes[i].y_ppem / 64.0;
+}
+
 FcPattern *
 FcFreeTypeQuery (const FcChar8 *file,
                 int            id,
@@ -357,7 +381,12 @@ FcFreeTypeQuery (const FcChar8     *file,
     const FcChar8   *foundry = 0;
     int                    spacing;
     TT_OS2         *os2;
+#if HAVE_FT_GET_PS_FONT_INFO
     PS_FontInfoRec  psfontinfo;
+#endif
+#if HAVE_FT_GET_BDF_PROPERTY
+    BDF_PropertyRec prop;
+#endif
     TT_Header      *head;
     const FcChar8   *exclusiveLang = 0;
     FT_SfntName            sname;
@@ -790,6 +819,7 @@ FcFreeTypeQuery (const FcChar8      *file,
      * Code from g2@magestudios.net (Gerard Escalante)
      */
     
+#if HAVE_FT_GET_PS_FONT_INFO
     if (FT_Get_PS_Font_Info(face, &psfontinfo) == 0)
     {
        if (weight == -1 && psfontinfo.weight)
@@ -814,8 +844,9 @@ FcFreeTypeQuery (const FcChar8      *file,
         if(!foundry)
             foundry = FcNoticeFoundry(psfontinfo.notice);
     }
+#endif /* HAVE_FT_GET_PS_FONT_INFO */
     
-#ifdef USE_FTBDF
+#if HAVE_FT_GET_BDF_PROPERTY
     /*
      * Finally, look for a FOUNDRY BDF property if no other
      * mechanism has managed to locate a foundry
@@ -832,7 +863,6 @@ FcFreeTypeQuery (const FcChar8      *file,
 
     if (width == -1)
     {
-       BDF_PropertyRec prop;
        if (MY_Get_BDF_Property(face, "RELATIVE_SETWIDTH", &prop) == 0 &&
            (prop.type == BDF_PROPERTY_TYPE_INTEGER ||
             prop.type == BDF_PROPERTY_TYPE_CARDINAL))
@@ -864,7 +894,6 @@ FcFreeTypeQuery (const FcChar8      *file,
                printf ("\tsetwidth %s maps to %d\n", prop.u.atom, width);
        }
     }
-
 #endif
 
     /*
@@ -932,7 +961,7 @@ FcFreeTypeQuery (const FcChar8      *file,
     if (!cs)
        goto bail1;
 
-#ifdef USE_FTBDF
+#if HAVE_FT_GET_BDF_PROPERTY
     /* For PCF fonts, override the computed spacing with the one from
        the property */
     if(MY_Get_BDF_Property(face, "SPACING", &prop) == 0 &&
@@ -964,7 +993,12 @@ FcFreeTypeQuery (const FcChar8     *file,
        goto bail2;
 
     if (!FcPatternAddLangSet (pat, FC_LANG, ls))
+    {
+       FcLangSetDestroy (ls);
        goto bail2;
+    }
+
+    FcLangSetDestroy (ls);
 
     if (spacing != FC_PROPORTIONAL)
        if (!FcPatternAddInteger (pat, FC_SPACING, spacing))
@@ -974,27 +1008,16 @@ FcFreeTypeQuery (const FcChar8   *file,
     {
        for (i = 0; i < face->num_fixed_sizes; i++)
            if (!FcPatternAddDouble (pat, FC_PIXEL_SIZE,
-                                    (double) face->available_sizes[i].height))
+                                    FcGetPixelSize (face, i)))
                goto bail1;
        if (!FcPatternAddBool (pat, FC_ANTIALIAS, FcFalse))
            goto bail1;
-#ifdef USE_FTBDF
+#if HAVE_FT_GET_BDF_PROPERTY
         if(face->num_fixed_sizes == 1) {
             int rc;
             int value;
             BDF_PropertyRec prop;
 
-            rc = MY_Get_BDF_Property(face, "PIXEL_SIZE", &prop);
-            if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
-                value = prop.u.integer;
-            else if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_CARDINAL)
-                value = prop.u.cardinal;
-            else
-                goto nevermind;
-            if(value != face->available_sizes[0].height)
-                /* ``impossible'' */
-                goto nevermind;
-
             rc = MY_Get_BDF_Property(face, "POINT_SIZE", &prop);
             if(rc == 0 && prop.type == BDF_PROPERTY_TYPE_INTEGER)
                 value = prop.u.integer;
@@ -1055,31 +1078,10 @@ bail:
 }
 
 
-/*
- * Figure out whether the available freetype has FT_Get_Next_Char
- */
-
-#if FREETYPE_MAJOR > 2
-# define HAS_NEXT_CHAR
-#else
-# if FREETYPE_MAJOR == 2
-#  if FREETYPE_MINOR > 0
-#   define HAS_NEXT_CHAR
-#  else
-#   if FREETYPE_MINOR == 0
-#    if FREETYPE_PATCH >= 9
-#     define HAS_NEXT_CHAR
-#    endif
-#   endif
-#  endif
-# endif
-#endif
-
 /*
  * For our purposes, this approximation is sufficient
  */
-#ifndef HAS_NEXT_CHAR
-#define FT_Get_First_Char(face, gi) ((*(gi) = 1), 1)
+#if !HAVE_FT_GET_NEXT_CHAR
 #define FT_Get_Next_Char(face, ucs4, gi) ((ucs4) >= 0xffffff ? \
                                          (*(gi) = 0), 0 : \
                                          (*(gi) = 1), (ucs4) + 1)
@@ -1604,6 +1606,7 @@ FcHashGlyphName (const FcChar8 *name)
     return h;
 }
 
+#if HAVE_FT_HAS_PS_GLYPH_NAMES
 /*
  * Use Type1 glyph names for fonts which have reliable names
  * and which export an Adobe Custom mapping
@@ -1689,6 +1692,7 @@ FcFreeTypeGlyphNameIndex (FT_Face face, FcChar8 *name)
     }
     return 0;
 }
+#endif
 
 /*
  * Map a UCS4 glyph to a glyph index.  Use all available encoding
@@ -1736,6 +1740,7 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
        if (glyphindex)
            return glyphindex;
     }
+#if HAVE_FT_HAS_PS_GLYPH_NAMES
     /*
      * Check postscript name table if present
      */
@@ -1749,6 +1754,7 @@ FcFreeTypeCharIndex (FT_Face face, FcChar32 ucs4)
                return glyphindex;
        }
     }
+#endif
     return 0;
 }
 
@@ -1760,6 +1766,12 @@ FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4,
     FT_Int         load_flags = FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH | FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
     FT_GlyphSlot    slot;
     
+    /*
+     * For bitmap-only fonts, assume that they're OK.
+     */
+    if ((face->face_flags & FT_FACE_FLAG_SCALABLE) == 0)
+       return FcTrue;
+
     /*
      * When using scalable fonts, only report those glyphs
      * which can be scaled; otherwise those fonts will
@@ -1808,6 +1820,8 @@ FcFreeTypeCheckGlyph (FT_Face face, FcChar32 ucs4,
     return FcFalse;
 }
 
+#define APPROXIMATELY_EQUAL(x,y) (ABS ((x) - (y)) <= MAX (ABS (x), ABS (y)) / 33)
+
 FcCharSet *
 FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
 {
@@ -1821,8 +1835,8 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
     int                    o;
     int                    i;
     FT_UInt        glyph;
-    FT_Pos         advance, all_advance = 0;
-    FcBool         has_advance = FcFalse, fixed_advance = FcTrue;
+    FT_Pos         advance, advance_one = 0, advance_two = 0;
+    FcBool         has_advance = FcFalse, fixed_advance = FcTrue, dual_advance = FcFalse;
 
     fcs = FcCharSetCreate ();
     if (!fcs)
@@ -1852,10 +1866,20 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
                    if (!has_advance)
                    {
                        has_advance = FcTrue;
-                       all_advance = advance;
+                       advance_one = advance;
                    }
-                   else if (advance != all_advance)
-                       fixed_advance = FcFalse;
+                   else if (!APPROXIMATELY_EQUAL (advance, advance_one))
+                    {
+                        if (fixed_advance)
+                        {
+                            dual_advance = FcTrue;
+                            fixed_advance = FcFalse;
+                            advance_two = advance;
+                        }
+                        else if (!APPROXIMATELY_EQUAL (advance, advance_two))
+                            dual_advance = FcFalse;
+                    }
+
                    leaf = FcCharSetFindLeafCreate (fcs, ucs4);
                    if (!leaf)
                        goto bail1;
@@ -1900,10 +1924,20 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
                        if (!has_advance)
                        {
                            has_advance = FcTrue;
-                           all_advance = advance;
+                           advance_one = advance;
                        }
-                       else if (advance != all_advance)
-                           fixed_advance = FcFalse;
+                       else if (!APPROXIMATELY_EQUAL (advance, advance_one))
+                        {
+                            if (fixed_advance)
+                            {
+                                dual_advance = FcTrue;
+                                fixed_advance = FcFalse;
+                                advance_two = advance;
+                            }
+                            else if (!APPROXIMATELY_EQUAL (advance, advance_two))
+                                dual_advance = FcFalse;
+                        }
+
                        if (!leaf)
                        {
                            leaf = FcCharSetFindLeafCreate (fcs, ucs4);
@@ -1938,6 +1972,7 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
 #endif
        }
     }
+#if HAVE_FT_HAS_PS_GLYPH_NAMES
     /*
      * Add mapping from PS glyph names if available
      */
@@ -1956,10 +1991,19 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
                    if (!has_advance)
                    {
                        has_advance = FcTrue;
-                       all_advance = advance;
+                       advance_one = advance;
                    }
-                   else if (advance != all_advance)
-                       fixed_advance = FcFalse;
+                   else if (!APPROXIMATELY_EQUAL (advance, advance_one))
+                    {
+                        if (fixed_advance)
+                        {
+                            dual_advance = FcTrue;
+                            fixed_advance = FcFalse;
+                            advance_two = advance;
+                        }
+                        else if (!APPROXIMATELY_EQUAL (advance, advance_two))
+                            dual_advance = FcFalse;
+                    }
                    leaf = FcCharSetFindLeafCreate (fcs, ucs4);
                    if (!leaf)
                        goto bail1;
@@ -1972,6 +2016,7 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
            }
        }
     }
+#endif
 #ifdef CHECK
     printf ("%d glyphs %d encoded\n", (int) face->num_glyphs, FcCharSetCount (fcs));
     for (ucs4 = 0; ucs4 <= font_max; ucs4++)
@@ -1992,6 +2037,8 @@ FcFreeTypeCharSetAndSpacing (FT_Face face, FcBlanks *blanks, int *spacing)
 #endif
     if (fixed_advance)
        *spacing = FC_MONO;
+    else if (dual_advance && APPROXIMATELY_EQUAL (2 * MIN (advance_one, advance_two), MAX (advance_one, advance_two)))
+        *spacing = FC_DUAL;
     else
        *spacing = FC_PROPORTIONAL;
     return fcs;