Since Xft may only be available statically without shlib deps, check for

Tue Dec 19 22:47:16 2000  Owen Taylor  <otaylor@redhat.com>

	* configure.in pango-config.in pangoxft.pc.in
	modules/basic/Makefile.am: Since Xft may only be available
	statically without shlib deps, check for FreeType libs explicitly
	and include them when linking, otherwise things won't work. Also,
	define FREETYPE_CFLAGS from freetype-config --cflags.

	* modules/basic/basic-xft.c pango/pangoxft-font{,map}.c: Fool
	Xft into not converting glyph indices by loading the
	face unencoded then calling FT_Set_Charmap ourselves.

	* pango/Makefile.am pango/pango-ot.h pango/opentype/* :Add start
	of opentype handling - most of the actually meat of the code here
	is the OpenType layout code from FreeType 1 ported to freetype2
	and adapted slighlty for our purposes.  Also, includes a
	incomplete OpenType-table-dumping code useful for figuring
	out what is going on.

	* pango/pangoxft.h pango/pangoxft-font.h: Add calls for
	getting FT_Face and PangoOTInfo from PangoXftFont.

	* modules/arabic/{Makefile.am,arabic-ot.[ch],arabic-xft.c}:
	Initial support for rendering Arabic with OpenType fonts.
diff --git a/src/disasm.c b/src/disasm.c
new file mode 100644
index 0000000..2e064ec
--- /dev/null
+++ b/src/disasm.c
@@ -0,0 +1,317 @@
+/* Pango
+ * disasm.c: Dump OpenType layout tables
+ *
+ * Copyright (C) 2000 Red Hat Software
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#include <stdarg.h>
+
+#include "disasm.h"
+
+#define DUMP(args...) dump (stream, indent, args)
+#define DUMP_FINT(strct,fld) dump (stream, indent, "<" #fld ">%d</" #fld ">\n", (strct)->fld)
+#define DUMP_FUINT(strct,fld) dump (stream, indent, "<" #fld ">%u</" #fld ">\n", (strct)->fld)
+#define DUMP_FGLYPH(strct,fld) dump (stream, indent, "<" #fld ">%#4x</" #fld ">\n", (strct)->fld)
+
+#define DEF_DUMP(type) static void Dump_ ## type (TTO_ ## type *type, FILE *stream, int indent, FT_Bool is_gsub)
+#define RECURSE(name, type, val) do {  DUMP ("<" #name ">\n"); Dump_ ## type (val, stream, indent + 1, is_gsub); DUMP ("</" #name ">\n"); } while (0)
+
+static void
+do_indent (FILE *stream, int indent)
+{
+  int i;
+
+  for (i = 0; i < indent * 3; i++)
+    fputc (' ', stream);
+}
+
+static void 
+dump (FILE *stream, int indent, const char *format, ...) 
+{
+  va_list list;
+  
+  do_indent (stream, indent);
+  
+  va_start (list, format);
+  vfprintf (stream, format, list);
+  va_end (list);
+}
+
+static void 
+Print_Tag (FT_ULong tag, FILE *stream)
+{
+  fprintf (stream, "%c%c%c%c", 
+	   (unsigned char)(tag >> 24),
+	   (unsigned char)((tag & 0xff0000) >> 16),
+	   (unsigned char)((tag & 0xff00) >> 8),
+	   (unsigned char)(tag & 0xff));
+}
+
+DEF_DUMP (LangSys)
+{
+  int i;
+
+  DUMP_FUINT (LangSys, LookupOrderOffset);
+  DUMP_FUINT (LangSys, ReqFeatureIndex);
+  DUMP_FUINT (LangSys, FeatureCount);
+
+  for (i=0; i < LangSys->FeatureCount; i++)
+    DUMP("<FeatureIndex>%d</FeatureIndex>\n", LangSys->FeatureIndex[i]);
+}
+
+DEF_DUMP (Script)
+{
+  int i;
+
+  RECURSE (DefaultLangSys, LangSys, &Script->DefaultLangSys);
+
+  DUMP_FUINT (Script, LangSysCount);
+
+  for (i=0; i < Script->LangSysCount; i++)
+    {
+      do_indent (stream, indent);
+      fprintf (stream, "<LangSysTag>");
+      Print_Tag (Script->LangSysRecord[i].LangSysTag, stream);
+      fprintf (stream, "</LangSysTag>\n");
+      RECURSE (LangSys, LangSys, &Script->LangSysRecord[i].LangSys);
+    }
+}
+
+DEF_DUMP (ScriptList)
+{
+  int i;
+  
+  DUMP_FUINT (ScriptList, ScriptCount);
+
+  for (i=0; i < ScriptList->ScriptCount; i++)
+    { 
+      do_indent (stream, indent);
+      fprintf (stream, "<ScriptTag>");
+      Print_Tag (ScriptList->ScriptRecord[i].ScriptTag, stream);
+      fprintf (stream, "</ScriptTag>\n");
+      RECURSE (Script, Script, &ScriptList->ScriptRecord[i].Script);
+    }
+}
+
+DEF_DUMP (Feature)
+{
+  int i;
+  
+  DUMP_FUINT (Feature, FeatureParams);
+  DUMP_FUINT (Feature, LookupListCount);
+
+  for (i=0; i < Feature->LookupListCount; i++)
+    DUMP("<LookupIndex>%d</LookupIndex>\n", Feature->LookupListIndex[i]);
+}
+
+DEF_DUMP (FeatureList)
+{
+  int i;
+  
+  DUMP_FUINT (FeatureList, FeatureCount);
+
+  for (i=0; i < FeatureList->FeatureCount; i++)
+    { 
+      do_indent (stream, indent);
+      fprintf (stream, "<FeatureTag>");
+      Print_Tag (FeatureList->FeatureRecord[i].FeatureTag, stream);
+      fprintf (stream, "</FeatureTag>\n");
+      RECURSE (Feature, Feature, &FeatureList->FeatureRecord[i].Feature);
+    }
+}
+
+DEF_DUMP (Coverage)
+{
+  DUMP_FUINT (Coverage, CoverageFormat);
+
+  if (Coverage->CoverageFormat == 1)
+    {
+      int i;
+      DUMP_FUINT (&Coverage->cf.cf1, GlyphCount);
+
+      for (i = 0; i < Coverage->cf.cf1.GlyphCount; i++)
+	DUMP("<Glyph>%#4x</Glyph> <!-- %d -->\n", Coverage->cf.cf1.GlyphArray[i], i);
+    }
+  else
+    {
+    }
+}
+
+static void
+Dump_GSUB_Lookup_Single (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub)
+{
+  TTO_SingleSubst *SingleSubst = &subtable->st.gsub.single;
+
+  DUMP_FUINT (SingleSubst, SubstFormat);
+  RECURSE (Coverage, Coverage, &SingleSubst->Coverage);
+
+  if (SingleSubst->SubstFormat == 1)
+    {
+      DUMP_FINT (&SingleSubst->ssf.ssf1, DeltaGlyphID);
+    }
+  else
+    {
+      int i;
+      
+      DUMP_FINT (&SingleSubst->ssf.ssf2, GlyphCount);
+      for (i=0; i < SingleSubst->ssf.ssf2.GlyphCount; i++)
+	DUMP("<Substitute>%#4x</Substitute> <!-- %d -->\n", SingleSubst->ssf.ssf2.Substitute[i], i);
+    }
+}
+
+DEF_DUMP (Ligature)
+{
+  int i;
+  
+  DUMP_FGLYPH (Ligature, LigGlyph);
+  DUMP_FUINT (Ligature, ComponentCount);
+
+  for (i=0; i < Ligature->ComponentCount - 1; i++)
+    DUMP("<Component>%#4x</Component>\n", Ligature->Component[i]);
+}
+
+DEF_DUMP (LigatureSet)
+{
+  int i;
+  
+  DUMP_FUINT (LigatureSet, LigatureCount);
+
+  for (i=0; i < LigatureSet->LigatureCount; i++)
+    RECURSE (Ligature, Ligature, &LigatureSet->Ligature[i]);
+}
+
+static void
+Dump_GSUB_Lookup_Ligature (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub)
+{
+  int i;
+  TTO_LigatureSubst *LigatureSubst = &subtable->st.gsub.ligature;
+
+  DUMP_FUINT (LigatureSubst, SubstFormat);
+  RECURSE (Coverage, Coverage, &LigatureSubst->Coverage);
+
+  DUMP_FUINT (LigatureSubst, LigatureSetCount);
+
+  for (i=0; i < LigatureSubst->LigatureSetCount; i++)
+    RECURSE (LigatureSet, LigatureSet, &LigatureSubst->LigatureSet[i]);
+}
+
+DEF_DUMP (Lookup)
+{
+  int i;
+  const char *lookup_name = NULL;
+  void (*lookup_func) (TTO_SubTable *subtable, FILE *stream, int indent, FT_Bool is_gsub) = NULL;
+
+  if (is_gsub)
+    {
+      switch (Lookup->LookupType)
+	{
+	case  GSUB_LOOKUP_SINGLE:
+	  lookup_name = "SINGLE";
+	  lookup_func = Dump_GSUB_Lookup_Single;
+	  break;
+	case  GSUB_LOOKUP_MULTIPLE:
+	  lookup_name = "MULTIPLE";
+	  break;
+	case  GSUB_LOOKUP_ALTERNATE:
+	  lookup_name = "ALTERNATE";
+	  break;
+	case  GSUB_LOOKUP_LIGATURE:
+	  lookup_name = "LIGATURE";
+	  lookup_func = Dump_GSUB_Lookup_Ligature;
+	  break;
+	case  GSUB_LOOKUP_CONTEXT:
+	  lookup_name = "CONTEXT";
+	  break;
+	case  GSUB_LOOKUP_CHAIN:
+	  lookup_name = "CHAIN";
+	  break;
+	}
+    }
+  else
+    {
+      switch (Lookup->LookupType)
+	{
+	case GPOS_LOOKUP_SINGLE:
+	  lookup_name = "SINGLE";
+	  break;
+	case GPOS_LOOKUP_PAIR:
+	  lookup_name = "PAIR";
+	  break;
+	case GPOS_LOOKUP_CURSIVE:
+	  lookup_name = "CURSIVE";
+	  break;
+	case GPOS_LOOKUP_MARKBASE:
+	  lookup_name = "MARKBASE";
+	  break;
+	case GPOS_LOOKUP_MARKLIG:
+	  lookup_name = "MARKLIG";
+	  break;
+	case GPOS_LOOKUP_MARKMARK:
+	  lookup_name = "MARKMARK";
+	  break;
+	case GPOS_LOOKUP_CONTEXT:
+	  lookup_name = "CONTEXT";
+	  break;
+	case GPOS_LOOKUP_CHAIN:
+	  lookup_name = "CHAIN";
+	  break;
+	}
+    }
+
+  DUMP("<LookupType>%s</LookupType>\n", lookup_name);
+
+  for (i=0; i < Lookup->SubTableCount; i++)
+    {
+      DUMP ("<Subtable>\n");
+      if (lookup_func)
+	(*lookup_func) (&Lookup->SubTable[i], stream, indent + 1, is_gsub);
+      DUMP ("</Subtable>\n");
+    }
+}
+
+DEF_DUMP (LookupList)
+{
+  int i;
+
+  DUMP_FUINT (LookupList, LookupCount);
+
+  for (i=0; i < LookupList->LookupCount; i++)
+    RECURSE (Lookup, Lookup, &LookupList->Lookup[i]);
+}
+
+void
+TT_Dump_GSUB_Table (TTO_GSUB gsub, FILE *stream)
+{
+  int indent = 0;
+  FT_Bool is_gsub = 1;
+
+  RECURSE (ScriptList, ScriptList, &gsub->ScriptList);
+  RECURSE (FeatureList, FeatureList, &gsub->FeatureList);
+  RECURSE (LookupList, LookupList, &gsub->LookupList);
+}
+
+void
+TT_Dump_GPOS_Table (TTO_GPOS gpos, FILE *stream)
+{
+  int indent = 0;
+  FT_Bool is_gsub = 0;
+
+  RECURSE (ScriptList, ScriptList, &gpos->ScriptList);
+  RECURSE (FeatureList, FeatureList, &gpos->FeatureList);
+  RECURSE (LookupList, LookupList, &gpos->LookupList);
+}