]> code.delx.au - gnu-emacs/blobdiff - src/ftfont.c
Merge from origin/emacs-25
[gnu-emacs] / src / ftfont.c
index 885fee61ba1ab8222e7a6e21d70b1c5269e4ec2c..bb8af96d7b195d9fac298de5c952f30a51291d8d 100644 (file)
@@ -1,5 +1,5 @@
 /* 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
@@ -28,13 +28,10 @@ along with GNU Emacs.  If not, see <http://www.gnu.org/licenses/>.  */
 
 #include "lisp.h"
 #include "dispextern.h"
-#include "frame.h"
-#include "blockinput.h"
 #include "character.h"
 #include "charset.h"
-#include "coding.h"
+#include "category.h"
 #include "composite.h"
-#include "fontset.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 Lisp_Object ftfont_combining_capability (struct font *);
+
 #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 */
+
+    NULL,                      /* cached_font_ok */
+
+    ftfont_combining_capability,
   };
 
 static Lisp_Object
@@ -1780,9 +1783,11 @@ setup_otf_gstring (int 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);
@@ -1934,6 +1939,10 @@ ftfont_drive_otf (MFLTFont *font,
              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++)
@@ -1957,6 +1966,10 @@ ftfont_drive_otf (MFLTFont *font,
                  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++;
            }
        }
@@ -2226,6 +2239,8 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
                  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;
@@ -2276,8 +2291,8 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
   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);
@@ -2299,17 +2314,17 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
          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++;
-         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.  */
@@ -2321,20 +2336,20 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
                  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++)
            {
-             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++;
            }
@@ -2348,7 +2363,7 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
          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)
@@ -2368,7 +2383,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;
 
-      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;
@@ -2436,10 +2451,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)
-                 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)
-                 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);
@@ -2447,19 +2462,19 @@ ftfont_drive_otf (MFLTFont *font, MFLTOtfSpec *spec, MFLTGlyphString *in,
                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++)
                  {
-                   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++)
                  {
-                   prev->from = this_from;
-                   prev->to = this_to;
+                   prev->g.from = this_from;
+                   prev->g.to = this_to;
                  }
              }
            }
@@ -2479,8 +2494,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);
-  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;
 }
@@ -2499,8 +2514,7 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
   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)
     {
@@ -2521,12 +2535,12 @@ ftfont_shape_by_flt (Lisp_Object lgstring, struct font *font,
        break;
       c = LGLYPH_CHAR (g);
       if (CHAR_VARIATION_SELECTOR_P (c))
-       with_variation_selector = 1;
+       with_variation_selector = true;
     }
 
   len = i;
 
-  if (with_variation_selector)
+  if (otf && with_variation_selector)
     {
       setup_otf_gstring (len);
       for (i = 0; i < len; i++)
@@ -2555,38 +2569,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);
 
@@ -2607,23 +2589,55 @@ 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;
-  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 || ! otf)
+    {
+      /* 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));
+      if (CHAR_HAS_CATEGORY (c1, '^'))
+       flt = mflt_get (msymbol ("combining"));
+      else if (! 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++)
@@ -2673,8 +2687,6 @@ ftfont_shape (Lisp_Object lgstring)
   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);
 }
@@ -2748,6 +2760,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)
 {