]> code.delx.au - gnu-emacs/blobdiff - src/ftfont.c
Merge from emacs-24; up to 117687
[gnu-emacs] / src / ftfont.c
index 0ad173af98a1041ac1f467081b1e8b9a28e1b3b1..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)
@@ -393,7 +391,7 @@ ftfont_lookup_cache (Lisp_Object key, enum ftfont_cache_for cache_for)
       cache_data = xmalloc (sizeof *cache_data);
       cache_data->ft_face = NULL;
       cache_data->fc_charset = NULL;
       cache_data = xmalloc (sizeof *cache_data);
       cache_data->ft_face = NULL;
       cache_data->fc_charset = NULL;
-      val = make_save_value (SAVE_TYPE_PTR_INT, cache_data, 0);
+      val = make_save_ptr_int (cache_data, 0);
       cache = Fcons (Qnil, val);
       Fputhash (key, cache, ft_face_cache);
     }
       cache = Fcons (Qnil, val);
       Fputhash (key, cache, ft_face_cache);
     }
@@ -493,16 +491,16 @@ ftfont_get_otf (struct ftfont_info *ftfont_info)
 }
 #endif /* HAVE_LIBOTF */
 
 }
 #endif /* HAVE_LIBOTF */
 
-static Lisp_Object ftfont_get_cache (FRAME_PTR);
-static Lisp_Object ftfont_list (Lisp_Object, Lisp_Object);
-static Lisp_Object ftfont_match (Lisp_Object, Lisp_Object);
-static Lisp_Object ftfont_list_family (Lisp_Object);
-static Lisp_Object ftfont_open (FRAME_PTR, Lisp_Object, int);
-static void ftfont_close (FRAME_PTR, struct font *);
+static Lisp_Object ftfont_get_cache (struct frame *);
+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 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,
@@ -568,7 +564,7 @@ struct font_driver ftfont_driver =
   };
 
 static Lisp_Object
   };
 
 static Lisp_Object
-ftfont_get_cache (FRAME_PTR f)
+ftfont_get_cache (struct frame *f)
 {
   return freetype_font_cache;
 }
 {
   return freetype_font_cache;
 }
@@ -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;
            }
@@ -884,7 +882,7 @@ ftfont_spec_pattern (Lisp_Object spec, char *otlayout, struct OpenTypeSpec **ots
 }
 
 static Lisp_Object
 }
 
 static Lisp_Object
-ftfont_list (Lisp_Object frame, Lisp_Object spec)
+ftfont_list (struct frame *f, Lisp_Object spec)
 {
   Lisp_Object val = Qnil, family, adstyle;
   int i;
 {
   Lisp_Object val = Qnil, family, adstyle;
   int i;
@@ -1011,6 +1009,7 @@ ftfont_list (Lisp_Object frame, 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 (Lisp_Object frame, 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 */
@@ -1080,7 +1081,7 @@ ftfont_list (Lisp_Object frame, Lisp_Object spec)
 }
 
 static Lisp_Object
 }
 
 static Lisp_Object
-ftfont_match (Lisp_Object frame, Lisp_Object spec)
+ftfont_match (struct frame *f, Lisp_Object spec)
 {
   Lisp_Object entity = Qnil;
   FcPattern *pattern, *match = NULL;
 {
   Lisp_Object entity = Qnil;
   FcPattern *pattern, *match = NULL;
@@ -1130,7 +1131,7 @@ ftfont_match (Lisp_Object frame, Lisp_Object spec)
 }
 
 static Lisp_Object
 }
 
 static Lisp_Object
-ftfont_list_family (Lisp_Object frame)
+ftfont_list_family (struct frame *f)
 {
   Lisp_Object list = Qnil;
   FcPattern *pattern = NULL;
 {
   Lisp_Object list = Qnil;
   FcPattern *pattern = NULL;
@@ -1173,7 +1174,7 @@ ftfont_list_family (Lisp_Object frame)
 
 
 static Lisp_Object
 
 
 static Lisp_Object
-ftfont_open (FRAME_PTR f, Lisp_Object entity, int pixel_size)
+ftfont_open (struct frame *f, Lisp_Object entity, int pixel_size)
 {
   struct ftfont_info *ftfont_info;
   struct font *font;
 {
   struct ftfont_info *ftfont_info;
   struct font *font;
@@ -1184,8 +1185,7 @@ ftfont_open (FRAME_PTR 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 (FRAME_PTR 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 (FRAME_PTR f, Lisp_Object entity, int pixel_size)
 }
 
 static void
 }
 
 static void
-ftfont_close (FRAME_PTR 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",
@@ -2703,13 +2676,12 @@ syms_of_ftfont (void)
   DEFSYM (Qsans__serif, "sans serif");
 
   staticpro (&freetype_font_cache);
   DEFSYM (Qsans__serif, "sans serif");
 
   staticpro (&freetype_font_cache);
-  freetype_font_cache = Fcons (Qt, Qnil);
+  freetype_font_cache = list1 (Qt);
 
   staticpro (&ftfont_generic_family_list);
 
   staticpro (&ftfont_generic_family_list);
-  ftfont_generic_family_list
-    = Fcons (Fcons (Qmonospace, Qt),
-            Fcons (Fcons (Qsans_serif, Qt),
-                   Fcons (Fcons (Qsans, Qt), Qnil)));
+  ftfont_generic_family_list = list3 (Fcons (Qmonospace, Qt),
+                                     Fcons (Qsans_serif, Qt),
+                                     Fcons (Qsans, Qt));
 
   staticpro (&ft_face_cache);
   ft_face_cache = Qnil;
 
   staticpro (&ft_face_cache);
   ft_face_cache = Qnil;