diff src/ftfont.c @ 100792:e829a2083df5

(ftfont_driver): Set the member get_variation_glyphs to ftfont_variation_glyphs. (setup_otf_gstring): New function. (ftfont_drive_otf): Use it. (ftfont_shape_by_flt): Handle variation selector. (ftfont_variation_glyphs): New function.
author Kenichi Handa <handa@m17n.org>
date Tue, 30 Dec 2008 23:40:16 +0000
parents d8bfaced209a
children e038c1a8307c
line wrap: on
line diff
--- a/src/ftfont.c	Tue Dec 30 23:36:56 2008 +0000
+++ b/src/ftfont.c	Tue Dec 30 23:40:16 2008 +0000
@@ -380,6 +380,8 @@
 				    int *, int *));
 static Lisp_Object ftfont_otf_capability P_ ((struct font *));
 static Lisp_Object ftfont_shape P_ ((Lisp_Object));
+static int ftfont_variation_glyphs P_ ((struct font *, int c,
+					unsigned variations[256]));
 
 struct font_driver ftfont_driver =
   {
@@ -389,35 +391,41 @@
     ftfont_list,
     ftfont_match,
     ftfont_list_family,
-    NULL,
+    NULL,			/* free_entity */
     ftfont_open,
     ftfont_close,
     /* We can't draw a text without device dependent functions.  */
-    NULL,
-    NULL,
+    NULL,			/* prepare_face */
+    NULL,			/* done_face */
     ftfont_has_char,
     ftfont_encode_char,
     ftfont_text_extents,
     /* We can't draw a text without device dependent functions.  */
-    NULL,
+    NULL,			/* draw */
     ftfont_get_bitmap,
-    NULL,
-    NULL,
-    NULL,
+    NULL,			/* get_bitmap */
+    NULL,			/* free_bitmap */
+    NULL,			/* get_outline */
     ftfont_anchor_point,
 #ifdef HAVE_LIBOTF
     ftfont_otf_capability,
 #else  /* not HAVE_LIBOTF */
     NULL,
 #endif	/* not HAVE_LIBOTF */
-    NULL,
-    NULL,
-    NULL,
+    NULL,			/* otf_drive */
+    NULL,			/* start_for_frame */
+    NULL,			/* end_for_frame */
 #if defined (HAVE_M17N_FLT) && defined (HAVE_LIBOTF)
-    ftfont_shape
+    ftfont_shape,
 #else  /* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
+    NULL,
+#endif	/* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
+    NULL,			/* check */
+#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
+    ftfont_variation_glyphs
+#else
     NULL
-#endif	/* not (HAVE_M17N_FLT && HAVE_LIBOTF) */
+#endif
   };
 
 extern Lisp_Object QCname;
@@ -1536,6 +1544,25 @@
 
 static OTF_GlyphString otf_gstring;
 
+static void
+setup_otf_gstring (int size)
+{
+  if (otf_gstring.size == 0)
+    {
+      otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * size);
+      otf_gstring.size = size;
+    }
+  else if (otf_gstring.size < size)
+    {
+      otf_gstring.glyphs = (OTF_Glyph *) realloc (otf_gstring.glyphs,
+						  sizeof (OTF_Glyph) * size);
+      otf_gstring.size = size;
+    }
+  otf_gstring.used = size;
+  memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * size);
+}
+
+
 static int
 ftfont_drive_otf (font, spec, in, from, to, out, adjustment)
      MFLTFont *font;
@@ -1588,19 +1615,7 @@
 	}
     }
 
-  if (otf_gstring.size == 0)
-    {
-      otf_gstring.glyphs = (OTF_Glyph *) malloc (sizeof (OTF_Glyph) * len);
-      otf_gstring.size = len;
-    }
-  else if (otf_gstring.size < len)
-    {
-      otf_gstring.glyphs = (OTF_Glyph *) realloc (otf_gstring.glyphs,
-						  sizeof (OTF_Glyph) * len);
-      otf_gstring.size = len;
-    }
-  otf_gstring.used = len;
-  memset (otf_gstring.glyphs, 0, sizeof (OTF_Glyph) * len);
+  setup_otf_gstring (len);
   for (i = 0; i < len; i++)
     {
       otf_gstring.glyphs[i].c = in->glyphs[from + i].c;
@@ -1818,6 +1833,7 @@
   EMACS_UINT i;
   struct MFLTFontFT flt_font_ft;
   MFLT *flt = NULL;
+  int with_variation_selector = 0;
 
   if (! m17n_flt_initialized)
     {
@@ -1826,9 +1842,45 @@
     }
 
   for (i = 0; i < len; i++)
-    if (NILP (LGSTRING_GLYPH (lgstring, i)))
-      break;
+    {
+      Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
+      int c;
+
+      if (NILP (g))
+	break;
+      c = LGLYPH_CHAR (g);
+      if (CHAR_VARIATION_SELECTOR_P (c))
+	with_variation_selector++;
+    }
   len = i;
+  if (with_variation_selector)
+    {
+      setup_otf_gstring (len);
+      for (i = 0; i < len; i++)
+	{
+	  Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
+
+	  otf_gstring.glyphs[i].c = LGLYPH_CHAR (g);
+	  otf_gstring.glyphs[i].f.index.from = LGLYPH_FROM (g);
+	  otf_gstring.glyphs[i].f.index.to = LGLYPH_TO (g);
+	}
+      OTF_drive_cmap (otf, &otf_gstring);
+      for (i = 0; i < otf_gstring.used; i++)
+	{
+	  OTF_Glyph *otfg = otf_gstring.glyphs + i;
+	  Lisp_Object g0 = LGSTRING_GLYPH (lgstring, otfg->f.index.from);
+	  Lisp_Object g1 = LGSTRING_GLYPH (lgstring, otfg->f.index.to);
+
+	  LGLYPH_SET_CODE (g0, otfg->glyph_id);
+	  LGLYPH_SET_TO (g0, LGLYPH_TO (g1));
+	  LGSTRING_SET_GLYPH (lgstring, i, g0);
+	}
+      if (len > otf_gstring.used)
+	{
+	  len = otf_gstring.used;
+	  LGSTRING_SET_GLYPH (lgstring, len, Qnil);
+	}
+    }
 
   if (gstring.allocated == 0)
     {
@@ -1842,8 +1894,19 @@
       gstring.glyphs = realloc (gstring.glyphs,
 				sizeof (MFLTGlyph) * gstring.allocated);
     }
+  memset (gstring.glyphs, 0, sizeof (MFLTGlyph) * len);
   for (i = 0; i < len; i++)
-    gstring.glyphs[i].c = LGLYPH_CHAR (LGSTRING_GLYPH (lgstring, i));
+    {
+      Lisp_Object g = LGSTRING_GLYPH (lgstring, i);
+
+      gstring.glyphs[i].c = LGLYPH_CHAR (g);
+      if (with_variation_selector)
+	{
+	  gstring.glyphs[i].code = LGLYPH_CODE (g);
+	  gstring.glyphs[i].encoded = 1;
+	}
+    }
+
   gstring.used = len;
   gstring.r2l = 0;
 
@@ -1940,6 +2003,23 @@
   return ftfont_shape_by_flt (lgstring, font, ftfont_info->ft_size->face, otf);
 }
 
+#ifdef HAVE_OTF_GET_VARIATION_GLYPHS
+
+static int
+ftfont_variation_glyphs (font, c, variations)
+     struct font *font;
+     int c;
+     unsigned variations[256];
+{
+  struct ftfont_info *ftfont_info = (struct ftfont_info *) font;
+  OTF *otf = ftfont_get_otf (ftfont_info);
+
+  if (! otf)
+    return 0;
+  return OTF_get_variation_glyphs (otf, c, variations);
+}
+
+#endif	/* HAVE_OTF_GET_VARIATION_GLYPHS */
 #endif	/* HAVE_M17N_FLT */
 #endif	/* HAVE_LIBOTF */