]> code.delx.au - gnu-emacs/blobdiff - src/ftfont.c
Merge from emacs-24; up to 117687
[gnu-emacs] / src / ftfont.c
index 3636f86f5c4709898e585442b793744ab50b983f..4c12ef5d3afe0e467e39e552e33b7df269737cc2 100644 (file)
@@ -1,5 +1,5 @@
 /* ftfont.c -- FreeType font driver.
 /* ftfont.c -- FreeType font driver.
-   Copyright (C) 2006-2013 Free Software Foundation, Inc.
+   Copyright (C) 2006-2014 Free Software Foundation, Inc.
    Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H13PRO009
    Copyright (C) 2006, 2007, 2008, 2009, 2010, 2011
      National Institute of Advanced Industrial Science and Technology (AIST)
      Registration Number H13PRO009
@@ -24,6 +24,8 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 #include <fontconfig/fontconfig.h>
 #include <fontconfig/fcfreetype.h>
 
 #include <fontconfig/fontconfig.h>
 #include <fontconfig/fcfreetype.h>
 
+#include <c-strcase.h>
+
 #include "lisp.h"
 #include "dispextern.h"
 #include "frame.h"
 #include "lisp.h"
 #include "dispextern.h"
 #include "frame.h"
@@ -54,7 +56,7 @@ static Lisp_Object freetype_font_cache;
 /* Cache for FT_Face and FcCharSet. */
 static Lisp_Object ft_face_cache;
 
 /* Cache for FT_Face and FcCharSet. */
 static Lisp_Object ft_face_cache;
 
-/* The actual structure for FreeType font that can be casted to struct
+/* The actual structure for FreeType font that can be cast to struct
    font.  */
 
 struct ftfont_info
    font.  */
 
 struct ftfont_info
@@ -87,8 +89,6 @@ static Lisp_Object ftfont_lookup_cache (Lisp_Object,
 
 static void ftfont_filter_properties (Lisp_Object font, Lisp_Object alist);
 
 
 static void ftfont_filter_properties (Lisp_Object font, Lisp_Object alist);
 
-Lisp_Object ftfont_font_format (FcPattern *, Lisp_Object);
-
 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
 
 static struct
 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
 
 static struct
@@ -142,6 +142,12 @@ static struct
     { NULL }
   };
 
     { NULL }
   };
 
+static bool
+matching_prefix (char const *str, ptrdiff_t len, char const *pat)
+{
+  return len == strlen (pat) && c_strncasecmp (str, pat, len) == 0;
+}
+
 /* Dirty hack for handing ADSTYLE property.
 
    Fontconfig (actually the underlying FreeType) gives such ADSTYLE
 /* Dirty hack for handing ADSTYLE property.
 
    Fontconfig (actually the underlying FreeType) gives such ADSTYLE
@@ -173,18 +179,10 @@ get_adstyle_property (FcPattern *p)
     return Qnil;
   str = (char *) fcstr;
   for (end = str; *end && *end != ' '; end++);
     return Qnil;
   str = (char *) fcstr;
   for (end = str; *end && *end != ' '; end++);
-  if (*end)
-    {
-      char *newstr = alloca (end - str + 1);
-      memcpy (newstr, str, end - str);
-      newstr[end - str] = '\0';
-      end = newstr + (end - str);
-      str = newstr;
-    }
-  if (xstrcasecmp (str, "Regular") == 0
-      || xstrcasecmp (str, "Bold") == 0
-      || xstrcasecmp (str, "Oblique") == 0
-      || xstrcasecmp (str, "Italic") == 0)
+  if (matching_prefix (str, end - str, "Regular")
+      || matching_prefix (str, end - str, "Bold")
+      || matching_prefix (str, end - str, "Oblique")
+      || matching_prefix (str, end - str, "Italic"))
     return Qnil;
   adstyle = font_intern_prop (str, end - str, 1);
   if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0)
     return Qnil;
   adstyle = font_intern_prop (str, end - str, 1);
   if (font_style_to_value (FONT_WIDTH_INDEX, adstyle, 0) >= 0)
@@ -498,11 +496,11 @@ static Lisp_Object ftfont_list (struct frame *, Lisp_Object);
 static Lisp_Object ftfont_match (struct frame *, Lisp_Object);
 static Lisp_Object ftfont_list_family (struct frame *);
 static Lisp_Object ftfont_open (struct frame *, Lisp_Object, int);
 static Lisp_Object ftfont_match (struct frame *, Lisp_Object);
 static Lisp_Object ftfont_list_family (struct frame *);
 static Lisp_Object ftfont_open (struct frame *, Lisp_Object, int);
-static void ftfont_close (struct frame *, struct font *);
+static void ftfont_close (struct font *);
 static int ftfont_has_char (Lisp_Object, int);
 static unsigned ftfont_encode_char (struct font *, int);
 static int ftfont_has_char (Lisp_Object, int);
 static unsigned ftfont_encode_char (struct font *, int);
-static int ftfont_text_extents (struct font *, unsigned *, int,
-                                struct font_metrics *);
+static void ftfont_text_extents (struct font *, unsigned *, int,
+                                struct font_metrics *);
 static int ftfont_get_bitmap (struct font *, unsigned,
                               struct font_bitmap *, int);
 static int ftfont_anchor_point (struct font *, unsigned, int,
 static int ftfont_get_bitmap (struct font *, unsigned,
                               struct font_bitmap *, int);
 static int ftfont_anchor_point (struct font *, unsigned, int,
@@ -540,8 +538,6 @@ struct font_driver ftfont_driver =
     NULL,                      /* draw */
     ftfont_get_bitmap,
     NULL,                      /* free_bitmap */
     NULL,                      /* draw */
     ftfont_get_bitmap,
     NULL,                      /* free_bitmap */
-    NULL,                      /* get_outline */
-    NULL,                      /* free_outline */
     ftfont_anchor_point,
 #ifdef HAVE_LIBOTF
     ftfont_otf_capability,
     ftfont_anchor_point,
 #ifdef HAVE_LIBOTF
     ftfont_otf_capability,
@@ -577,7 +573,8 @@ static int
 ftfont_get_charset (Lisp_Object registry)
 {
   char *str = SSDATA (SYMBOL_NAME (registry));
 ftfont_get_charset (Lisp_Object registry)
 {
   char *str = SSDATA (SYMBOL_NAME (registry));
-  char *re = alloca (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
+  USE_SAFE_ALLOCA;
+  char *re = SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
   Lisp_Object regexp;
   int i, j;
 
   Lisp_Object regexp;
   int i, j;
 
@@ -593,6 +590,7 @@ ftfont_get_charset (Lisp_Object registry)
     }
   re[j] = '\0';
   regexp = make_unibyte_string (re, j);
     }
   re[j] = '\0';
   regexp = make_unibyte_string (re, j);
+  SAFE_FREE ();
   for (i = 0; fc_charset_table[i].name; i++)
     if (fast_c_string_match_ignore_case
        (regexp, fc_charset_table[i].name,
   for (i = 0; fc_charset_table[i].name; i++)
     if (fast_c_string_match_ignore_case
        (regexp, fc_charset_table[i].name,
@@ -806,7 +804,7 @@ ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **ots
              *otspec = ftfont_get_open_type_spec (val);
              if (! *otspec)
                return NULL;
              *otspec = ftfont_get_open_type_spec (val);
              if (! *otspec)
                return NULL;
-             strcat (otlayout, "otlayout:");
+             strcpy (otlayout, "otlayout:");
              OTF_TAG_STR ((*otspec)->script_tag, otlayout + 9);
              script = (*otspec)->script;
            }
              OTF_TAG_STR ((*otspec)->script_tag, otlayout + 9);
              script = (*otspec)->script;
            }
@@ -1011,6 +1009,7 @@ ftfont_list (struct frame *f, Lisp_Object spec)
       if (otspec)
        {
          FcChar8 *file;
       if (otspec)
        {
          FcChar8 *file;
+         bool passed;
          OTF *otf;
 
          if (FcPatternGetString (fontset->fonts[i], FC_FILE, 0, &file)
          OTF *otf;
 
          if (FcPatternGetString (fontset->fonts[i], FC_FILE, 0, &file)
@@ -1019,14 +1018,16 @@ ftfont_list (struct frame *f, Lisp_Object spec)
          otf = OTF_open ((char *) file);
          if (! otf)
            continue;
          otf = OTF_open ((char *) file);
          if (! otf)
            continue;
-         if (OTF_check_features (otf, 1,
-                                 otspec->script_tag, otspec->langsys_tag,
-                                 otspec->features[0],
-                                 otspec->nfeatures[0]) != 1
-             || OTF_check_features (otf, 0,
-                                    otspec->script_tag, otspec->langsys_tag,
-                                    otspec->features[1],
-                                    otspec->nfeatures[1]) != 1)
+         passed = (OTF_check_features (otf, 1, otspec->script_tag,
+                                       otspec->langsys_tag,
+                                       otspec->features[0],
+                                       otspec->nfeatures[0]) == 1
+                   && OTF_check_features (otf, 0, otspec->script_tag,
+                                          otspec->langsys_tag,
+                                          otspec->features[1],
+                                          otspec->nfeatures[1]) == 1);
+         OTF_close (otf);
+         if (!passed)
            continue;
        }
 #endif /* HAVE_LIBOTF */
            continue;
        }
 #endif /* HAVE_LIBOTF */
@@ -1184,8 +1185,7 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
   Lisp_Object val, filename, idx, cache, font_object;
   bool scalable;
   int spacing;
   Lisp_Object val, filename, idx, cache, font_object;
   bool scalable;
   int spacing;
-  char name[256];
-  int i, len;
+  int i;
   int upEM;
 
   val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
   int upEM;
 
   val = assq_no_quit (QCfont_entity, AREF (entity, FONT_EXTRA_INDEX));
@@ -1222,19 +1222,9 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
       return Qnil;
     }
 
       return Qnil;
     }
 
-  font_object = font_make_object (VECSIZE (struct ftfont_info), entity, size);
-  ASET (font_object, FONT_TYPE_INDEX, Qfreetype);
-  len = font_unparse_xlfd (entity, size, name, 256);
-  if (len > 0)
-    ASET (font_object, FONT_NAME_INDEX, make_string (name, len));
-  len = font_unparse_fcname (entity, size, name, 256);
-  if (len > 0)
-    ASET (font_object, FONT_FULLNAME_INDEX, make_string (name, len));
-  else
-    ASET (font_object, FONT_FULLNAME_INDEX,
-         AREF (font_object, FONT_NAME_INDEX));
+  font_object = font_build_object (VECSIZE (struct ftfont_info),
+                                  Qfreetype, entity, size);
   ASET (font_object, FONT_FILE_INDEX, filename);
   ASET (font_object, FONT_FILE_INDEX, filename);
-  ASET (font_object, FONT_FORMAT_INDEX, ftfont_font_format (NULL, filename));
   font = XFONT_OBJECT (font_object);
   ftfont_info = (struct ftfont_info *) font;
   ftfont_info->ft_size = ft_face->size;
   font = XFONT_OBJECT (font_object);
   ftfont_info = (struct ftfont_info *) font;
   ftfont_info->ft_size = ft_face->size;
@@ -1317,7 +1307,7 @@ ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
 }
 
 static void
 }
 
 static void
-ftfont_close (struct frame *f, struct font *font)
+ftfont_close (struct font *font)
 {
   struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
   Lisp_Object val, cache;
 {
   struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
   Lisp_Object val, cache;
@@ -1383,19 +1373,18 @@ ftfont_encode_char (struct font *font, int c)
   return (code > 0 ? code : FONT_INVALID_CODE);
 }
 
   return (code > 0 ? code : FONT_INVALID_CODE);
 }
 
-static int
-ftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct font_metrics *metrics)
+static void
+ftfont_text_extents (struct font *font, unsigned int *code,
+                    int nglyphs, struct font_metrics *metrics)
 {
   struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
   FT_Face ft_face = ftfont_info->ft_size->face;
 {
   struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
   FT_Face ft_face = ftfont_info->ft_size->face;
-  int width = 0;
-  int i;
+  int i, width = 0;
   bool first;
 
   if (ftfont_info->ft_size != ft_face->size)
     FT_Activate_Size (ftfont_info->ft_size);
   bool first;
 
   if (ftfont_info->ft_size != ft_face->size)
     FT_Activate_Size (ftfont_info->ft_size);
-  if (metrics)
-    memset (metrics, 0, sizeof (struct font_metrics));
+
   for (i = 0, first = 1; i < nglyphs; i++)
     {
       if (FT_Load_Glyph (ft_face, code[i], FT_LOAD_DEFAULT) == 0)
   for (i = 0, first = 1; i < nglyphs; i++)
     {
       if (FT_Load_Glyph (ft_face, code[i], FT_LOAD_DEFAULT) == 0)
@@ -1404,39 +1393,28 @@ ftfont_text_extents (struct font *font, unsigned int *code, int nglyphs, struct
 
          if (first)
            {
 
          if (first)
            {
-             if (metrics)
-               {
-                 metrics->lbearing = m->horiBearingX >> 6;
-                 metrics->rbearing = (m->horiBearingX + m->width) >> 6;
-                 metrics->ascent = m->horiBearingY >> 6;
-                 metrics->descent = (m->height - m->horiBearingY) >> 6;
-               }
+             metrics->lbearing = m->horiBearingX >> 6;
+             metrics->rbearing = (m->horiBearingX + m->width) >> 6;
+             metrics->ascent = m->horiBearingY >> 6;
+             metrics->descent = (m->height - m->horiBearingY) >> 6;
              first = 0;
            }
              first = 0;
            }
-         if (metrics)
-           {
-             if (metrics->lbearing > width + (m->horiBearingX >> 6))
-               metrics->lbearing = width + (m->horiBearingX >> 6);
-             if (metrics->rbearing
-                 < width + ((m->horiBearingX + m->width) >> 6))
-               metrics->rbearing
-                 = width + ((m->horiBearingX + m->width) >> 6);
-             if (metrics->ascent < (m->horiBearingY >> 6))
-               metrics->ascent = m->horiBearingY >> 6;
-             if (metrics->descent > ((m->height - m->horiBearingY) >> 6))
-               metrics->descent = (m->height - m->horiBearingY) >> 6;
-           }
+         if (metrics->lbearing > width + (m->horiBearingX >> 6))
+           metrics->lbearing = width + (m->horiBearingX >> 6);
+         if (metrics->rbearing
+             < width + ((m->horiBearingX + m->width) >> 6))
+           metrics->rbearing
+             = width + ((m->horiBearingX + m->width) >> 6);
+         if (metrics->ascent < (m->horiBearingY >> 6))
+           metrics->ascent = m->horiBearingY >> 6;
+         if (metrics->descent > ((m->height - m->horiBearingY) >> 6))
+           metrics->descent = (m->height - m->horiBearingY) >> 6;
          width += m->horiAdvance >> 6;
        }
       else
          width += m->horiAdvance >> 6;
        }
       else
-       {
-         width += font->space_width;
-       }
+       width += font->space_width;
     }
     }
-  if (metrics)
-    metrics->width = width;
-
-  return width;
+  metrics->width = width;
 }
 
 static int
 }
 
 static int
@@ -1478,7 +1456,6 @@ ftfont_get_bitmap (struct font *font, unsigned int code, struct font_bitmap *bit
   bitmap->left = ft_face->glyph->bitmap_left;
   bitmap->top = ft_face->glyph->bitmap_top;
   bitmap->advance = ft_face->glyph->metrics.horiAdvance >> 6;
   bitmap->left = ft_face->glyph->bitmap_left;
   bitmap->top = ft_face->glyph->bitmap_top;
   bitmap->advance = ft_face->glyph->metrics.horiAdvance >> 6;
-  bitmap->extra = NULL;
 
   return 0;
 }
 
   return 0;
 }
@@ -1713,7 +1690,8 @@ ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
        else if (! otf)
          return 0;
        for (n = 1; spec->features[i][n]; n++);
        else if (! otf)
          return 0;
        for (n = 1; spec->features[i][n]; n++);
-       tags = alloca (sizeof (OTF_Tag) * n);
+       USE_SAFE_ALLOCA;
+       SAFE_NALLOCA (tags, 1, n);
        for (n = 0, negative = 0; spec->features[i][n]; n++)
          {
            if (spec->features[i][n] == 0xFFFFFFFF)
        for (n = 0, negative = 0; spec->features[i][n]; n++)
          {
            if (spec->features[i][n] == 0xFFFFFFFF)
@@ -1723,16 +1701,17 @@ ftfont_check_otf (MFLTFont *font, MFLTOtfSpec *spec)
            else
              tags[n] = spec->features[i][n];
          }
            else
              tags[n] = spec->features[i][n];
          }
-#ifdef M17N_FLT_USE_NEW_FEATURE
-       if (OTF_check_features (otf, i == 0, spec->script, spec->langsys,
-                               tags, n - negative) != 1)
-         return 0;
-#else  /* not M17N_FLT_USE_NEW_FEATURE */
-       if (n - negative > 0
-           && OTF_check_features (otf, i == 0, spec->script, spec->langsys,
-                                  tags, n - negative) != 1)
+       bool passed = true;
+#ifndef M17N_FLT_USE_NEW_FEATURE
+       passed = n - negative > 0;
+#endif
+       if (passed)
+         passed = (OTF_check_features (otf, i == 0, spec->script,
+                                       spec->langsys, tags, n - negative)
+                   != 1);
+       SAFE_FREE ();
+       if (passed)
          return 0;
          return 0;
-#endif /* not M17N_FLT_USE_NEW_FEATURE */
       }
   return 1;
 #undef FEATURE_NONE
       }
   return 1;
 #undef FEATURE_NONE
@@ -1824,11 +1803,15 @@ ftfont_drive_otf (MFLTFont *font,
   if (len == 0)
     return from;
   OTF_tag_name (spec->script, script);
   if (len == 0)
     return from;
   OTF_tag_name (spec->script, script);
+
+  char langsysbuf[5];
   if (spec->langsys)
     {
   if (spec->langsys)
     {
-      langsys = alloca (5);
+      langsys = langsysbuf;
       OTF_tag_name (spec->langsys, langsys);
     }
       OTF_tag_name (spec->langsys, langsys);
     }
+
+  USE_SAFE_ALLOCA;
   for (i = 0; i < 2; i++)
     {
       char *p;
   for (i = 0; i < 2; i++)
     {
       char *p;
@@ -1836,10 +1819,11 @@ ftfont_drive_otf (MFLTFont *font,
       if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
        {
          for (j = 0; spec->features[i][j]; j++);
       if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
        {
          for (j = 0; spec->features[i][j]; j++);
+         SAFE_NALLOCA (p, 6, j);
          if (i == 0)
          if (i == 0)
-           p = gsub_features = alloca (6 * j);
+           gsub_features = p;
          else
          else
-           p = gpos_features = alloca (6 * j);
+           gpos_features = p;
          for (j = 0; spec->features[i][j]; j++)
            {
              if (spec->features[i][j] == 0xFFFFFFFF)
          for (j = 0; spec->features[i][j]; j++)
            {
              if (spec->features[i][j] == 0xFFFFFFFF)
@@ -1871,7 +1855,10 @@ ftfont_drive_otf (MFLTFont *font,
                                   gsub_features) < 0)
        goto simple_copy;
       if (out->allocated < out->used + otf_gstring.used)
                                   gsub_features) < 0)
        goto simple_copy;
       if (out->allocated < out->used + otf_gstring.used)
-       return -2;
+       {
+         SAFE_FREE ();
+         return -2;
+       }
       features = otf->gsub->FeatureList.Feature;
       for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
        {
       features = otf->gsub->FeatureList.Feature;
       for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
        {
@@ -1960,7 +1947,10 @@ ftfont_drive_otf (MFLTFont *font,
   else if (out)
     {
       if (out->allocated < out->used + len)
   else if (out)
     {
       if (out->allocated < out->used + len)
-       return -2;
+       {
+         SAFE_FREE ();
+         return -2;
+       }
       for (i = 0; i < len; i++)
        out->glyphs[out->used++] = in->glyphs[from + i];
     }
       for (i = 0; i < len; i++)
        out->glyphs[out->used++] = in->glyphs[from + i];
     }
@@ -1972,7 +1962,10 @@ ftfont_drive_otf (MFLTFont *font,
 
       if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
                                   gpos_features) < 0)
 
       if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
                                   gpos_features) < 0)
-       return to;
+       {
+         SAFE_FREE ();
+         return to;
+       }
       features = otf->gpos->FeatureList.Feature;
       x_ppem = ft_face->size->metrics.x_ppem;
       y_ppem = ft_face->size->metrics.y_ppem;
       features = otf->gpos->FeatureList.Feature;
       x_ppem = ft_face->size->metrics.x_ppem;
       y_ppem = ft_face->size->metrics.y_ppem;
@@ -2094,7 +2087,10 @@ ftfont_drive_otf (MFLTFont *font,
     {
       if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
                                   gpos_features) < 0)
     {
       if (OTF_drive_gpos_with_log (otf, &otf_gstring, script, langsys,
                                   gpos_features) < 0)
-       return to;
+       {
+         SAFE_FREE ();
+         return to;
+       }
       features = otf->gpos->FeatureList.Feature;
       for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used;
           i++, otfg++)
       features = otf->gpos->FeatureList.Feature;
       for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used;
           i++, otfg++)
@@ -2114,9 +2110,11 @@ ftfont_drive_otf (MFLTFont *font,
              }
          }
     }
              }
          }
     }
+  SAFE_FREE ();
   return to;
 
  simple_copy:
   return to;
 
  simple_copy:
+  SAFE_FREE ();
   if (! out)
     return to;
   if (out->allocated < out->used + len)
   if (! out)
     return to;
   if (out->allocated < out->used + len)
@@ -2154,11 +2152,15 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
   if (len == 0)
     return from;
   OTF_tag_name (spec->script, script);
   if (len == 0)
     return from;
   OTF_tag_name (spec->script, script);
+
+  char langsysbuf[5];
   if (spec->langsys)
     {
   if (spec->langsys)
     {
-      langsys = alloca (5);
+      langsys = langsysbuf;
       OTF_tag_name (spec->langsys, langsys);
     }
       OTF_tag_name (spec->langsys, langsys);
     }
+
+  USE_SAFE_ALLOCA;
   for (i = 0; i < 2; i++)
     {
       char *p;
   for (i = 0; i < 2; i++)
     {
       char *p;
@@ -2166,10 +2168,11 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
       if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
        {
          for (j = 0; spec->features[i][j]; j++);
       if (spec->features[i] && spec->features[i][1] != 0xFFFFFFFF)
        {
          for (j = 0; spec->features[i][j]; j++);
+         SAFE_NALLOCA (p, 6, j);
          if (i == 0)
          if (i == 0)
-           p = gsub_features = alloca (6 * j);
+           gsub_features = p;
          else
          else
-           p = gpos_features = alloca (6 * j);
+           gpos_features = p;
          for (j = 0; spec->features[i][j]; j++)
            {
              if (spec->features[i][j] == 0xFFFFFFFF)
          for (j = 0; spec->features[i][j]; j++)
            {
              if (spec->features[i][j] == 0xFFFFFFFF)
@@ -2201,7 +2204,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
          < 0)
        goto simple_copy;
       if (out->allocated < out->used + otf_gstring.used)
          < 0)
        goto simple_copy;
       if (out->allocated < out->used + otf_gstring.used)
-       return -2;
+       {
+         SAFE_FREE ();
+         return -2;
+       }
       for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
        {
          MFLTGlyph *g;
       for (i = 0, otfg = otf_gstring.glyphs; i < otf_gstring.used; )
        {
          MFLTGlyph *g;
@@ -2252,7 +2258,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
   else
     {
       if (out->allocated < out->used + len)
   else
     {
       if (out->allocated < out->used + len)
-       return -2;
+       {
+         SAFE_FREE ();
+         return -2;
+       }
       for (i = 0; i < len; i++)
        out->glyphs[out->used++] = in->glyphs[from + i];
     }
       for (i = 0; i < len; i++)
        out->glyphs[out->used++] = in->glyphs[from + i];
     }
@@ -2264,7 +2273,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
 
       if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features)
          < 0)
 
       if (OTF_drive_gpos (otf, &otf_gstring, script, langsys, gpos_features)
          < 0)
-       return to;
+       {
+         SAFE_FREE ();
+         return to;
+       }
 
       x_ppem = ft_face->size->metrics.x_ppem;
       y_ppem = ft_face->size->metrics.y_ppem;
 
       x_ppem = ft_face->size->metrics.x_ppem;
       y_ppem = ft_face->size->metrics.y_ppem;
@@ -2374,9 +2386,11 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
            base = g;
        }
     }
            base = g;
        }
     }
+  SAFE_FREE ();
   return to;
 
  simple_copy:
   return to;
 
  simple_copy:
+  SAFE_FREE ();
   if (out->allocated < out->used + len)
     return -2;
   font->get_metrics (font, in, from, to);
   if (out->allocated < out->used + len)
     return -2;
   font->get_metrics (font, in, from, to);
@@ -2425,7 +2439,6 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
     }
 
   len = i;
     }
 
   len = i;
-  lint_assume (len <= STRING_BYTES_BOUND);
 
   if (with_variation_selector)
     {
 
   if (with_variation_selector)
     {
@@ -2600,46 +2613,6 @@ ftfont_variation_glyphs (struct font *font, int c, unsigned variations[256])
 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
 #endif /* HAVE_LIBOTF */
 
 #endif /* HAVE_OTF_GET_VARIATION_GLYPHS */
 #endif /* HAVE_LIBOTF */
 
-Lisp_Object
-ftfont_font_format (FcPattern *pattern, Lisp_Object filename)
-{
-  FcChar8 *str;
-
-#ifdef FC_FONTFORMAT
-  if (pattern)
-    {
-      if (FcPatternGetString (pattern, FC_FONTFORMAT, 0, &str) != FcResultMatch)
-       return Qnil;
-      if (strcmp ((char *) str, "TrueType") == 0)
-       return intern ("truetype");
-      if (strcmp ((char *) str, "Type 1") == 0)
-       return intern ("type1");
-      if (strcmp ((char *) str, "PCF") == 0)
-       return intern ("pcf");
-      if (strcmp ((char *) str, "BDF") == 0)
-       return intern ("bdf");
-    }
-#endif  /* FC_FONTFORMAT */
-  if (STRINGP (filename))
-    {
-      int len = SBYTES (filename);
-
-      if (len >= 4)
-       {
-         str = (FcChar8 *) (SDATA (filename) + len - 4);
-         if (xstrcasecmp ((char *) str, ".ttf") == 0)
-           return intern ("truetype");
-         if (xstrcasecmp ((char *) str, ".pfb") == 0)
-           return intern ("type1");
-         if (xstrcasecmp ((char *) str, ".pcf") == 0)
-           return intern ("pcf");
-         if (xstrcasecmp ((char *) str, ".bdf") == 0)
-           return intern ("bdf");
-       }
-    }
-  return intern ("unknown");
-}
-
 static const char *const ftfont_booleans [] = {
   ":antialias",
   ":hinting",
 static const char *const ftfont_booleans [] = {
   ":antialias",
   ":hinting",