blob: 2e064ec20c2a5d96149f6165fb6806fc1d1df3dd [file] [log] [blame]
/* 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);
}