]> code.delx.au - gnu-emacs/blobdiff - src/ftfont.c
Merge from origin/emacs-25
[gnu-emacs] / src / ftfont.c
index 885fee61ba1ab8222e7a6e21d70b1c5269e4ec2c..1ae3f88daa31911e635cea8e0709d7f0dd4ac896 100644 (file)
@@ -1,5 +1,5 @@
 /* ftfont.c -- FreeType font driver.
 /* ftfont.c -- FreeType font driver.
-   Copyright (C) 2006-2015 Free Software Foundation, Inc.
+   Copyright (C) 2006-2016 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
@@ -8,8 +8,8 @@ This file is part of GNU Emacs.
 
 GNU Emacs is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 
 GNU Emacs 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 3 of the License, or
-(at your option) any later version.
+the Free Software Foundation, either version 3 of the License, or (at
+your option) any later version.
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 GNU Emacs is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
@@ -28,13 +28,10 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "lisp.h"
 #include "dispextern.h"
 
 #include "lisp.h"
 #include "dispextern.h"
-#include "frame.h"
-#include "blockinput.h"
 #include "character.h"
 #include "charset.h"
 #include "character.h"
 #include "charset.h"
-#include "coding.h"
+#include "category.h"
 #include "composite.h"
 #include "composite.h"
-#include "fontset.h"
 #include "font.h"
 #include "ftfont.h"
 
 #include "font.h"
 #include "ftfont.h"
 
@@ -85,6 +82,8 @@ 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);
 
+static Lisp_Object ftfont_combining_capability (struct font *);
+
 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
 
 static struct
 #define SYMBOL_FcChar8(SYM) (FcChar8 *) SDATA (SYMBOL_NAME (SYM))
 
 static struct
@@ -551,6 +550,10 @@ struct font_driver ftfont_driver =
 #endif
 
     ftfont_filter_properties, /* filter_properties */
 #endif
 
     ftfont_filter_properties, /* filter_properties */
+
+    NULL,                      /* cached_font_ok */
+
+    ftfont_combining_capability,
   };
 
 static Lisp_Object
   };
 
 static Lisp_Object
@@ -565,7 +568,6 @@ ftfont_get_charset (Lisp_Object registry)
   char *str = SSDATA (SYMBOL_NAME (registry));
   USE_SAFE_ALLOCA;
   char *re = SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
   char *str = SSDATA (SYMBOL_NAME (registry));
   USE_SAFE_ALLOCA;
   char *re = SAFE_ALLOCA (SBYTES (SYMBOL_NAME (registry)) * 2 + 1);
-  Lisp_Object regexp;
   int i, j;
 
   for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
   int i, j;
 
   for (i = j = 0; i < SBYTES (SYMBOL_NAME (registry)); i++, j++)
@@ -579,13 +581,13 @@ ftfont_get_charset (Lisp_Object registry)
        re[j] = '.';
     }
   re[j] = '\0';
        re[j] = '.';
     }
   re[j] = '\0';
-  regexp = make_unibyte_string (re, j);
-  SAFE_FREE ();
+  AUTO_STRING_WITH_LEN (regexp, re, j);
   for (i = 0; fc_charset_table[i].name; i++)
     if (fast_c_string_match_ignore_case
        (regexp, fc_charset_table[i].name,
         strlen (fc_charset_table[i].name)) >= 0)
       break;
   for (i = 0; fc_charset_table[i].name; i++)
     if (fast_c_string_match_ignore_case
        (regexp, fc_charset_table[i].name,
         strlen (fc_charset_table[i].name)) >= 0)
       break;
+  SAFE_FREE ();
   if (! fc_charset_table[i].name)
     return -1;
   if (! fc_charset_table[i].fc_charset)
   if (! fc_charset_table[i].name)
     return -1;
   if (! fc_charset_table[i].fc_charset)
@@ -1780,9 +1782,11 @@ setup_otf_gstring (int size)
 {
   if (otf_gstring.size < size)
     {
 {
   if (otf_gstring.size < size)
     {
-      otf_gstring.glyphs = xnrealloc (otf_gstring.glyphs,
-                                     size, sizeof (OTF_Glyph));
-      otf_gstring.size = size;
+      ptrdiff_t new_size = otf_gstring.size;
+      xfree (otf_gstring.glyphs);
+      otf_gstring.glyphs = xpalloc (NULL, &new_size, size - otf_gstring.size,
+                                   INT_MAX, sizeof *otf_gstring.glyphs);
+      otf_gstring.size = new_size;
     }
   otf_gstring.used = size;
   memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * size);
     }
   otf_gstring.used = size;
   memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * size);
@@ -1934,6 +1938,10 @@ ftfont_drive_otf (MFLTFont *font,
              tag = PACK_OTF_TAG (tag);
              g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
            }
              tag = PACK_OTF_TAG (tag);
              g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
            }
+#ifdef OTF_POSITIONING_TYPE_GET_FORMAT
+         g->libotf_positioning_type
+           = otfg->positioning_type & OTF_positioning_type_components_mask;
+#endif
          for (i++, otfg++; (i < otf_gstring.used
                             && otfg->f.index.from == otfg[-1].f.index.from);
               i++, otfg++)
          for (i++, otfg++; (i < otf_gstring.used
                             && otfg->f.index.from == otfg[-1].f.index.from);
               i++, otfg++)
@@ -1957,6 +1965,10 @@ ftfont_drive_otf (MFLTFont *font,
                  tag = PACK_OTF_TAG (tag);
                  g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
                }
                  tag = PACK_OTF_TAG (tag);
                  g->g.internal = (g->g.internal & ~0x1FFFFFFF) | tag;
                }
+#ifdef OTF_POSITIONING_TYPE_GET_FORMAT
+             g->libotf_positioning_type
+               = otfg->positioning_type & OTF_positioning_type_components_mask;
+#endif
              out->used++;
            }
        }
              out->used++;
            }
        }
@@ -2226,6 +2238,8 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
                  MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
 {
   struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
                  MFLTGlyphString *out, MFLTGlyphAdjustment *adjustment)
 {
   struct MFLTFontFT *flt_font_ft = (struct MFLTFontFT *) font;
+  MFLTGlyphFT *in_glyphs = (MFLTGlyphFT *) (in->glyphs) + from;
+  MFLTGlyphFT *out_glyphs = out ? (MFLTGlyphFT *) (out->glyphs) : NULL;
   FT_Face ft_face = flt_font_ft->ft_face;
   OTF *otf = flt_font_ft->otf;
   int len = to - from;
   FT_Face ft_face = flt_font_ft->ft_face;
   OTF *otf = flt_font_ft->otf;
   int len = to - from;
@@ -2276,8 +2290,8 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
   setup_otf_gstring (len);
   for (i = 0; i < len; i++)
     {
   setup_otf_gstring (len);
   for (i = 0; i < len; i++)
     {
-      otf_gstring.glyphs[i].c = in->glyphs[from + i].c;
-      otf_gstring.glyphs[i].glyph_id = in->glyphs[from + i].code;
+      otf_gstring.glyphs[i].c = in_glyphs[i].g.c;
+      otf_gstring.glyphs[i].glyph_id = in_glyphs[i].g.code;
     }
 
   OTF_drive_gdef (otf, &otf_gstring);
     }
 
   OTF_drive_gdef (otf, &otf_gstring);
@@ -2299,17 +2313,17 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
          int min_from, max_to;
          int j;
 
          int min_from, max_to;
          int j;
 
-         g = out->glyphs + out->used;
-         *g = in->glyphs[from + otfg->f.index.from];
-         if (g->code != otfg->glyph_id)
+         g = out_glyphs + out->used;
+         *g = in_glyphs[otfg->f.index.from];
+         if (g->g.code != otfg->glyph_id)
            {
            {
-             g->c = 0;
-             g->code = otfg->glyph_id;
-             g->measured = 0;
+             g->g.c = 0;
+             g->g.code = otfg->glyph_id;
+             g->g.measured = 0;
            }
          out->used++;
            }
          out->used++;
-         min_from = g->from;
-         max_to = g->to;
+         min_from = g->g.from;
+         max_to = g->g.to;
          if (otfg->f.index.from < otfg->f.index.to)
            {
              /* OTFG substitutes multiple glyphs in IN.  */
          if (otfg->f.index.from < otfg->f.index.to)
            {
              /* OTFG substitutes multiple glyphs in IN.  */
@@ -2321,20 +2335,20 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
                  if (max_to < in->glyphs[j].to)
                    max_to = in->glyphs[j].to;
                }
                  if (max_to < in->glyphs[j].to)
                    max_to = in->glyphs[j].to;
                }
-             g->from = min_from;
-             g->to = max_to;
+             g->g.from = min_from;
+             g->g.to = max_to;
            }
          for (i++, otfg++; (i < otf_gstring.used
                             && otfg->f.index.from == otfg[-1].f.index.from);
               i++, otfg++)
            {
            }
          for (i++, otfg++; (i < otf_gstring.used
                             && otfg->f.index.from == otfg[-1].f.index.from);
               i++, otfg++)
            {
-             g = out->glyphs + out->used;
-             *g = in->glyphs[from + otfg->f.index.to];
-             if (g->code != otfg->glyph_id)
+             g = out_glyphs + out->used;
+             *g = in_glyphs[otfg->f.index.to];
+             if (g->g.code != otfg->glyph_id)
                {
                {
-                 g->c = 0;
-                 g->code = otfg->glyph_id;
-                 g->measured = 0;
+                 g->g.c = 0;
+                 g->g.code = otfg->glyph_id;
+                 g->g.measured = 0;
                }
              out->used++;
            }
                }
              out->used++;
            }
@@ -2348,7 +2362,7 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
          return -2;
        }
       for (i = 0; i < len; i++)
          return -2;
        }
       for (i = 0; i < len; i++)
-       out->glyphs[out->used++] = in->glyphs[from + i];
+       out_glyphs[out->used++] = in_glyphs[i];
     }
 
   if (gpos_features)
     }
 
   if (gpos_features)
@@ -2368,7 +2382,7 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
       x_scale = ft_face->size->metrics.x_scale;
       y_scale = ft_face->size->metrics.y_scale;
 
       x_scale = ft_face->size->metrics.x_scale;
       y_scale = ft_face->size->metrics.y_scale;
 
-      for (i = 0, otfg = otf_gstring.glyphs, g = out->glyphs + gidx;
+      for (i = 0, otfg = otf_gstring.glyphs, g = out_glyphs + gidx;
           i < otf_gstring.used; i++, otfg++, g++)
        {
          MFLTGlyphFT *prev;
           i < otf_gstring.used; i++, otfg++, g++)
        {
          MFLTGlyphFT *prev;
@@ -2436,10 +2450,10 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
                mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;
 
                if (otfg->f.f4.base_anchor->AnchorFormat != 1)
                mark_y = otfg->f.f4.mark_anchor->YCoordinate * y_scale / 0x10000;
 
                if (otfg->f.f4.base_anchor->AnchorFormat != 1)
-                 adjust_anchor (ft_face, otfg->f.f4.base_anchor,
-                                prev->code, x_ppem, y_ppem, &base_x, &base_y);
+                 adjust_anchor (ft_face, otfg->f.f4.base_anchor, prev->g.code,
+                                x_ppem, y_ppem, &base_x, &base_y);
                if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
                if (otfg->f.f4.mark_anchor->AnchorFormat != 1)
-                 adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->code,
+                 adjust_anchor (ft_face, otfg->f.f4.mark_anchor, g->g.code,
                                 x_ppem, y_ppem, &mark_x, &mark_y);
                adjustment[i].xoff = (base_x - mark_x);
                adjustment[i].yoff = - (base_y - mark_y);
                                 x_ppem, y_ppem, &mark_x, &mark_y);
                adjustment[i].xoff = (base_x - mark_x);
                adjustment[i].yoff = - (base_y - mark_y);
@@ -2447,19 +2461,19 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
                adjustment[i].xadv = 0;
                adjustment[i].advance_is_absolute = 1;
                adjustment[i].set = 1;
                adjustment[i].xadv = 0;
                adjustment[i].advance_is_absolute = 1;
                adjustment[i].set = 1;
-               this_from = g->from;
-               this_to = g->to;
+               this_from = g->g.from;
+               this_to = g->g.to;
                for (j = 0; prev + j < g; j++)
                  {
                for (j = 0; prev + j < g; j++)
                  {
-                   if (this_from > prev[j].from)
-                     this_from = prev[j].from;
-                   if (this_to < prev[j].to)
-                     this_to = prev[j].to;
+                   if (this_from > prev[j].g.from)
+                     this_from = prev[j].g.from;
+                   if (this_to < prev[j].g.to)
+                     this_to = prev[j].g.to;
                  }
                for (; prev <= g; prev++)
                  {
                  }
                for (; prev <= g; prev++)
                  {
-                   prev->from = this_from;
-                   prev->to = this_to;
+                   prev->g.from = this_from;
+                   prev->g.to = this_to;
                  }
              }
            }
                  }
              }
            }
@@ -2479,8 +2493,8 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
   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);
-  memcpy (out->glyphs + out->used, in->glyphs + from,
-         sizeof (MFLTGlyph) * len);
+  memcpy (out_glyphs + out->used, in_glyphs,
+         sizeof (MFLTGlyphFT) * len);
   out->used += len;
   return to;
 }
   out->used += len;
   return to;
 }
@@ -2499,8 +2513,7 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
   ptrdiff_t i;
   struct MFLTFontFT flt_font_ft;
   MFLT *flt = NULL;
   ptrdiff_t i;
   struct MFLTFontFT flt_font_ft;
   MFLT *flt = NULL;
-  bool with_variation_selector = 0;
-  MFLTGlyphFT *glyphs;
+  bool with_variation_selector = false;
 
   if (! m17n_flt_initialized)
     {
 
   if (! m17n_flt_initialized)
     {
@@ -2521,12 +2534,12 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
        break;
       c = LGLYPH_CHAR (g);
       if (CHAR_VARIATION_SELECTOR_P (c))
        break;
       c = LGLYPH_CHAR (g);
       if (CHAR_VARIATION_SELECTOR_P (c))
-       with_variation_selector = 1;
+       with_variation_selector = true;
     }
 
   len = i;
 
     }
 
   len = i;
 
-  if (with_variation_selector)
+  if (otf && with_variation_selector)
     {
       setup_otf_gstring (len);
       for (i = 0; i < len; i++)
     {
       setup_otf_gstring (len);
       for (i = 0; i < len; i++)
@@ -2555,38 +2568,6 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
        }
     }
 
        }
     }
 
-  if (INT_MAX / 2 < len)
-    memory_full (SIZE_MAX);
-
-  if (gstring.allocated == 0)
-    {
-      gstring.glyph_size = sizeof (MFLTGlyphFT);
-      gstring.glyphs = xnmalloc (len * 2, sizeof (MFLTGlyphFT));
-      gstring.allocated = len * 2;
-    }
-  else if (gstring.allocated < len * 2)
-    {
-      gstring.glyphs = xnrealloc (gstring.glyphs, len * 2,
-                                 sizeof (MFLTGlyphFT));
-      gstring.allocated = len * 2;
-    }
-  glyphs = (MFLTGlyphFT *) (gstring.glyphs);
-  memset (glyphs, 0, len * sizeof (MFLTGlyphFT));
-  for (i = 0; i < len; i++)
-    {
-      Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
-
-      glyphs[i].g.c = LGLYPH_CHAR (g);
-      if (with_variation_selector)
-       {
-         glyphs[i].g.code = LGLYPH_CODE (g);
-         glyphs[i].g.encoded = 1;
-       }
-    }
-
-  gstring.used = len;
-  gstring.r2l = 0;
-
   {
     Lisp_Object family = Ffont_get (LGSTRING_FONT (lgstring), QCfamily);
 
   {
     Lisp_Object family = Ffont_get (LGSTRING_FONT (lgstring), QCfamily);
 
@@ -2607,23 +2588,62 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
   flt_font_ft.ft_face = ft_face;
   flt_font_ft.otf = otf;
   flt_font_ft.matrix = matrix->xx != 0 ? matrix : 0;
   flt_font_ft.ft_face = ft_face;
   flt_font_ft.otf = otf;
   flt_font_ft.matrix = matrix->xx != 0 ? matrix : 0;
-  if (len > 1
-      && gstring.glyphs[1].c >= 0x300 && gstring.glyphs[1].c <= 0x36F)
-    /* A little bit ad hoc.  Perhaps, shaper must get script and
-       language information, and select a proper flt for them
-       here.  */
-    flt = mflt_get (msymbol ("combining"));
-  for (i = 0; i < 3; i++)
-    {
-      int result = mflt_run (&gstring, 0, len, &flt_font_ft.flt_font, flt);
-      if (result != -2)
-       break;
-      if (INT_MAX / 2 < gstring.allocated)
-       memory_full (SIZE_MAX);
-      gstring.glyphs = xnrealloc (gstring.glyphs,
-                                 gstring.allocated, 2 * sizeof (MFLTGlyphFT));
-      gstring.allocated *= 2;
+
+  if (1 < len)
+    {
+      /* A little bit ad hoc.  Perhaps, shaper must get script and
+        language information, and select a proper flt for them
+        here.  */
+      int c1 = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, 1));
+      /* For the combining characters in the range U+300..U+36F,
+        "combining" is the sole FLT provided by the m17n-lib.  In
+        addition, it is the sole FLT that can handle the other
+        combining characters with non-OTF fonts.  */
+      if ((0x300 <= c1 && c1 <= 0x36F)
+         || (! otf && CHAR_HAS_CATEGORY (c1, '^')))
+       flt = mflt_get (msymbol ("combining"));
     }
     }
+  if (! flt && ! otf)
+    {
+      flt = mflt_find (LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, 0)),
+                      &flt_font_ft.flt_font);
+      if (! flt)
+       return make_number (0);
+    }
+
+  MFLTGlyphFT *glyphs = (MFLTGlyphFT *) gstring.glyphs;
+  ptrdiff_t allocated = gstring.allocated;
+  ptrdiff_t incr_min = len - allocated;
+
+  do
+    {
+      if (0 < incr_min)
+       {
+         xfree (glyphs);
+         glyphs = xpalloc (NULL, &allocated, incr_min, INT_MAX, sizeof *glyphs);
+       }
+      incr_min = 1;
+
+      for (i = 0; i < len; i++)
+       {
+         Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
+         memset (&glyphs[i], 0, sizeof glyphs[i]);
+         glyphs[i].g.c = LGLYPH_CHAR (g);
+         if (with_variation_selector)
+           {
+             glyphs[i].g.code = LGLYPH_CODE (g);
+             glyphs[i].g.encoded = 1;
+           }
+       }
+
+      gstring.glyph_size = sizeof *glyphs;
+      gstring.glyphs = (MFLTGlyph *) glyphs;
+      gstring.allocated = allocated;
+      gstring.used = len;
+      gstring.r2l = 0;
+    }
+  while (mflt_run (&gstring, 0, len, &flt_font_ft.flt_font, flt) == -2);
+
   if (gstring.used > LGSTRING_GLYPH_LEN (lgstring))
     return Qnil;
   for (i = 0; i < gstring.used; i++)
   if (gstring.used > LGSTRING_GLYPH_LEN (lgstring))
     return Qnil;
   for (i = 0; i < gstring.used; i++)
@@ -2673,8 +2693,6 @@ ftfont_shape (Lisp_Object lgstring)
   struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
   OTF *otf = ftfont_get_otf (ftfont_info);
 
   struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
   OTF *otf = ftfont_get_otf (ftfont_info);
 
-  if (! otf)
-    return make_number (0);
   return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf,
                              &ftfont_info->matrix);
 }
   return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf,
                              &ftfont_info->matrix);
 }
@@ -2748,6 +2766,16 @@ ftfont_filter_properties (Lisp_Object font, Lisp_Object alist)
 }
 
 
 }
 
 
+static Lisp_Object
+ftfont_combining_capability (struct font *font)
+{
+#ifdef HAVE_M17N_FLT
+  return Qt;
+#else
+  return Qnil;
+#endif
+}
+
 void
 syms_of_ftfont (void)
 {
 void
 syms_of_ftfont (void)
 {