diff options
author | Peter Breitenlohner <peb@mppmu.mpg.de> | 2011-12-01 13:24:38 +0000 |
---|---|---|
committer | Peter Breitenlohner <peb@mppmu.mpg.de> | 2011-12-01 13:24:38 +0000 |
commit | 3131715fb5bce44da6c7584315237731aa752eba (patch) | |
tree | b4e748ed3b19d603c4ac1b29f33340c196003e0e | |
parent | 9417d53067c450b541cecd8c3ae224e5d17b8e54 (diff) |
ttfdump: Added functionality
- do not segfault for fonts without loca table
- allow cmap subtables with format 8, 10, 12, and 13
- handle GPOS and GSUB tables
- additional tests
git-svn-id: svn://tug.org/texlive/trunk@24713 c570f23f-e606-0410-a88d-b1316a301751
28 files changed, 4566 insertions, 515 deletions
diff --git a/Build/source/texk/ttfdump/ChangeLog b/Build/source/texk/ttfdump/ChangeLog index a9cc2d5786c..9713680022a 100644 --- a/Build/source/texk/ttfdump/ChangeLog +++ b/Build/source/texk/ttfdump/ChangeLog @@ -1,3 +1,41 @@ +2011-12-01 Peter Breitenlohner <peb@mppmu.mpg.de> + + * include/gpos.h (new): GPOS table format. + * include/gsub.h (new): GSUB table format. + * include/otftables.h (new): OpenType common table formats. + * libttf/gpos.c (new): Load, print, and free GPOS table. + * libttf/gsub.c (new): Load, print, and free GSUB table. + * libttf/otfcommon.c (new): Handle common table formats. + * include/loadtable.h, include/tables.h, include/ttf.h, + libttf/font.c, src/ttfdump.c: Add GPOS and GSUB tables. + * Makefile.am (libttf_a_SOURCES): Add the new files. + * docs/ttfdump.1: Mention GPOS and GSUB tables. + + * tests/ttfdump.test: Add tests for GPOS and GSUB tables. + * tests/ttfdump.{gpos,gsub} (new): Expected output. + * Makefile.am: Adapted. + +2011-11-21 Peter Breitenlohner <peb@mppmu.mpg.de> + + Additional 'cmap' SubTable Formats. + * include/tables.h: Declare data structures for 'cmap' SubTable + Formats 8, 10, 12, 13, and 14. + * libttf/cmap.c: Separate Encoding Records from SubTables; + several Encodings may refer to the same SubTable. + Add support for SubTable Formats 8, 10, 12, 13, and 14. + FIXME: Format 14 is not yet implemented. + * include/loadtable.h, include/ttf.h, libttf/glyf.c: Adapted. + +2011-11-10 Peter Breitenlohner <peb@mppmu.mpg.de> + + * include/tables.h, libttf/head.c: Print created and modified. + * libttf/font.c: Index to location ('loca') table is optional. + * libttf/loca.c: Avoid segfault for missing 'loca' table. + * src/ttfdump.c: Avoid segfault for missing 'loca' table (do not + try to print glyphs). Print sfnt version. + + * tests/ttfdump.test: Perform all sub-tests and report failed ones. + 2011-11-08 Peter Breitenlohner <peb@mppmu.mpg.de> Major update. diff --git a/Build/source/texk/ttfdump/Makefile.am b/Build/source/texk/ttfdump/Makefile.am index e5d7547ca8a..018623bc1d8 100644 --- a/Build/source/texk/ttfdump/Makefile.am +++ b/Build/source/texk/ttfdump/Makefile.am @@ -12,9 +12,12 @@ noinst_LIBRARIES = libttf.a libttf_a_SOURCES = \ include/gcache.h \ + include/gpos.h \ include/gstate.h \ + include/gsub.h \ include/loadtable.h \ include/os2_P.h \ + include/otftables.h \ include/protos.h \ include/tables.h \ include/ttc.h \ @@ -28,7 +31,9 @@ libttf_a_SOURCES = \ libttf/gasp.c \ libttf/gcache.c \ libttf/glyf.c \ + libttf/gpos.c \ libttf/gstate.c \ + libttf/gsub.c \ libttf/hdmx.c \ libttf/head.c \ libttf/hhea.c \ @@ -39,6 +44,7 @@ libttf_a_SOURCES = \ libttf/maxp.c \ libttf/name.c \ libttf/os2.c \ + libttf/otfcommon.c \ libttf/pclt.c \ libttf/post.c \ libttf/prep.c \ @@ -78,8 +84,15 @@ TESTS = tests/ttfdump.test EXTRA_DIST += $(TESTS) DISTCLEANFILES = ## tests/ttfdump.test -EXTRA_DIST += tests/FonetikaDaniaIwonaeRegular.ttf tests/ttfdump.glyf tests/ttfdump.head -DISTCLEANFILES += FonetikaDaniaIwonaeRegular.ttf ttfdump.glyf ttfdump.head +EXTRA_DIST += \ + tests/FonetikaDaniaIwonaeRegular.ttf \ + tests/ttfdump.glyf \ + tests/ttfdump.gpos \ + tests/ttfdump.gsub \ + tests/ttfdump.head +DISTCLEANFILES += \ + FonetikaDaniaIwonaeRegular.ttf \ + ttftest.* ## Not used ## diff --git a/Build/source/texk/ttfdump/Makefile.in b/Build/source/texk/ttfdump/Makefile.in index 28090ee782f..1ae5c003152 100644 --- a/Build/source/texk/ttfdump/Makefile.in +++ b/Build/source/texk/ttfdump/Makefile.in @@ -73,9 +73,10 @@ libttf_a_AR = $(AR) $(ARFLAGS) libttf_a_LIBADD = am_libttf_a_OBJECTS = cmap.$(OBJEXT) cvt.$(OBJEXT) disasm.$(OBJEXT) \ font.$(OBJEXT) fpgm.$(OBJEXT) gasp.$(OBJEXT) gcache.$(OBJEXT) \ - glyf.$(OBJEXT) gstate.$(OBJEXT) hdmx.$(OBJEXT) head.$(OBJEXT) \ - hhea.$(OBJEXT) hmtx.$(OBJEXT) kern.$(OBJEXT) loca.$(OBJEXT) \ - ltsh.$(OBJEXT) maxp.$(OBJEXT) name.$(OBJEXT) os2.$(OBJEXT) \ + glyf.$(OBJEXT) gpos.$(OBJEXT) gstate.$(OBJEXT) gsub.$(OBJEXT) \ + hdmx.$(OBJEXT) head.$(OBJEXT) hhea.$(OBJEXT) hmtx.$(OBJEXT) \ + kern.$(OBJEXT) loca.$(OBJEXT) ltsh.$(OBJEXT) maxp.$(OBJEXT) \ + name.$(OBJEXT) os2.$(OBJEXT) otfcommon.$(OBJEXT) \ pclt.$(OBJEXT) post.$(OBJEXT) prep.$(OBJEXT) \ tabledir.$(OBJEXT) ttc.$(OBJEXT) ttfread.$(OBJEXT) \ ttfutil.$(OBJEXT) vdmx.$(OBJEXT) vhea.$(OBJEXT) vmtx.$(OBJEXT) @@ -262,9 +263,12 @@ AM_CFLAGS = $(WARNING_CFLAGS) noinst_LIBRARIES = libttf.a libttf_a_SOURCES = \ include/gcache.h \ + include/gpos.h \ include/gstate.h \ + include/gsub.h \ include/loadtable.h \ include/os2_P.h \ + include/otftables.h \ include/protos.h \ include/tables.h \ include/ttc.h \ @@ -278,7 +282,9 @@ libttf_a_SOURCES = \ libttf/gasp.c \ libttf/gcache.c \ libttf/glyf.c \ + libttf/gpos.c \ libttf/gstate.c \ + libttf/gsub.c \ libttf/hdmx.c \ libttf/head.c \ libttf/hhea.c \ @@ -289,6 +295,7 @@ libttf_a_SOURCES = \ libttf/maxp.c \ libttf/name.c \ libttf/os2.c \ + libttf/otfcommon.c \ libttf/pclt.c \ libttf/post.c \ libttf/prep.c \ @@ -303,13 +310,13 @@ libttf_a_SOURCES = \ EXTRA_DIST = libttf/fixed.c libttf/interp.c libttf/stack.c \ docs/ttfdump.dvi docs/ttfdump.html docs/ttfdump.ps $(TESTS) \ tests/FonetikaDaniaIwonaeRegular.ttf tests/ttfdump.glyf \ - tests/ttfdump.head ILX NOTE README.bg5 + tests/ttfdump.gpos tests/ttfdump.gsub tests/ttfdump.head ILX \ + NOTE README.bg5 ttfdump_SOURCES = src/ttfdump.c LDADD = libttf.a dist_man1_MANS = docs/ttfdump.1 TESTS = tests/ttfdump.test -DISTCLEANFILES = FonetikaDaniaIwonaeRegular.ttf ttfdump.glyf \ - ttfdump.head +DISTCLEANFILES = FonetikaDaniaIwonaeRegular.ttf ttftest.* all: config.h $(MAKE) $(AM_MAKEFLAGS) all-am @@ -434,7 +441,9 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gasp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gcache.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/glyf.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gpos.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gstate.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/gsub.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hdmx.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/head.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/hhea.Po@am__quote@ @@ -445,6 +454,7 @@ distclean-compile: @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/maxp.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/name.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os2.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/otfcommon.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pclt.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/post.Po@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/prep.Po@am__quote@ @@ -590,6 +600,20 @@ glyf.obj: libttf/glyf.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o glyf.obj `if test -f 'libttf/glyf.c'; then $(CYGPATH_W) 'libttf/glyf.c'; else $(CYGPATH_W) '$(srcdir)/libttf/glyf.c'; fi` +gpos.o: libttf/gpos.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gpos.o -MD -MP -MF $(DEPDIR)/gpos.Tpo -c -o gpos.o `test -f 'libttf/gpos.c' || echo '$(srcdir)/'`libttf/gpos.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/gpos.Tpo $(DEPDIR)/gpos.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libttf/gpos.c' object='gpos.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gpos.o `test -f 'libttf/gpos.c' || echo '$(srcdir)/'`libttf/gpos.c + +gpos.obj: libttf/gpos.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gpos.obj -MD -MP -MF $(DEPDIR)/gpos.Tpo -c -o gpos.obj `if test -f 'libttf/gpos.c'; then $(CYGPATH_W) 'libttf/gpos.c'; else $(CYGPATH_W) '$(srcdir)/libttf/gpos.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/gpos.Tpo $(DEPDIR)/gpos.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libttf/gpos.c' object='gpos.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gpos.obj `if test -f 'libttf/gpos.c'; then $(CYGPATH_W) 'libttf/gpos.c'; else $(CYGPATH_W) '$(srcdir)/libttf/gpos.c'; fi` + gstate.o: libttf/gstate.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gstate.o -MD -MP -MF $(DEPDIR)/gstate.Tpo -c -o gstate.o `test -f 'libttf/gstate.c' || echo '$(srcdir)/'`libttf/gstate.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/gstate.Tpo $(DEPDIR)/gstate.Po @@ -604,6 +628,20 @@ gstate.obj: libttf/gstate.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gstate.obj `if test -f 'libttf/gstate.c'; then $(CYGPATH_W) 'libttf/gstate.c'; else $(CYGPATH_W) '$(srcdir)/libttf/gstate.c'; fi` +gsub.o: libttf/gsub.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gsub.o -MD -MP -MF $(DEPDIR)/gsub.Tpo -c -o gsub.o `test -f 'libttf/gsub.c' || echo '$(srcdir)/'`libttf/gsub.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/gsub.Tpo $(DEPDIR)/gsub.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libttf/gsub.c' object='gsub.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gsub.o `test -f 'libttf/gsub.c' || echo '$(srcdir)/'`libttf/gsub.c + +gsub.obj: libttf/gsub.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT gsub.obj -MD -MP -MF $(DEPDIR)/gsub.Tpo -c -o gsub.obj `if test -f 'libttf/gsub.c'; then $(CYGPATH_W) 'libttf/gsub.c'; else $(CYGPATH_W) '$(srcdir)/libttf/gsub.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/gsub.Tpo $(DEPDIR)/gsub.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libttf/gsub.c' object='gsub.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o gsub.obj `if test -f 'libttf/gsub.c'; then $(CYGPATH_W) 'libttf/gsub.c'; else $(CYGPATH_W) '$(srcdir)/libttf/gsub.c'; fi` + hdmx.o: libttf/hdmx.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT hdmx.o -MD -MP -MF $(DEPDIR)/hdmx.Tpo -c -o hdmx.o `test -f 'libttf/hdmx.c' || echo '$(srcdir)/'`libttf/hdmx.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/hdmx.Tpo $(DEPDIR)/hdmx.Po @@ -744,6 +782,20 @@ os2.obj: libttf/os2.c @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ @am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o os2.obj `if test -f 'libttf/os2.c'; then $(CYGPATH_W) 'libttf/os2.c'; else $(CYGPATH_W) '$(srcdir)/libttf/os2.c'; fi` +otfcommon.o: libttf/otfcommon.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT otfcommon.o -MD -MP -MF $(DEPDIR)/otfcommon.Tpo -c -o otfcommon.o `test -f 'libttf/otfcommon.c' || echo '$(srcdir)/'`libttf/otfcommon.c +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/otfcommon.Tpo $(DEPDIR)/otfcommon.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libttf/otfcommon.c' object='otfcommon.o' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o otfcommon.o `test -f 'libttf/otfcommon.c' || echo '$(srcdir)/'`libttf/otfcommon.c + +otfcommon.obj: libttf/otfcommon.c +@am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT otfcommon.obj -MD -MP -MF $(DEPDIR)/otfcommon.Tpo -c -o otfcommon.obj `if test -f 'libttf/otfcommon.c'; then $(CYGPATH_W) 'libttf/otfcommon.c'; else $(CYGPATH_W) '$(srcdir)/libttf/otfcommon.c'; fi` +@am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/otfcommon.Tpo $(DEPDIR)/otfcommon.Po +@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='libttf/otfcommon.c' object='otfcommon.obj' libtool=no @AMDEPBACKSLASH@ +@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@ +@am__fastdepCC_FALSE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -c -o otfcommon.obj `if test -f 'libttf/otfcommon.c'; then $(CYGPATH_W) 'libttf/otfcommon.c'; else $(CYGPATH_W) '$(srcdir)/libttf/otfcommon.c'; fi` + pclt.o: libttf/pclt.c @am__fastdepCC_TRUE@ $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) -MT pclt.o -MD -MP -MF $(DEPDIR)/pclt.Tpo -c -o pclt.o `test -f 'libttf/pclt.c' || echo '$(srcdir)/'`libttf/pclt.c @am__fastdepCC_TRUE@ $(am__mv) $(DEPDIR)/pclt.Tpo $(DEPDIR)/pclt.Po diff --git a/Build/source/texk/ttfdump/docs/ttfdump.1 b/Build/source/texk/ttfdump/docs/ttfdump.1 index 45ce77ce811..f0d5e4cd4d8 100644 --- a/Build/source/texk/ttfdump/docs/ttfdump.1 +++ b/Build/source/texk/ttfdump/docs/ttfdump.1 @@ -1,4 +1,4 @@ -.TH TTFDUMP 1 "4 May 2011" "ILX Project" +.TH TTFDUMP 1 "14 November 2011" "ILX Project" .SH NAME ttfdump \- Dumping the contents of a TrueType Font file .SH SYNOPSIS @@ -8,9 +8,9 @@ ttfdump \- Dumping the contents of a TrueType Font file .IR tablename ] .RB [ \-g .IR glyphnumber ] -.RB [\ -c +.RB [ \-c .IR collection ] -.RB [\ -o +.RB [ \-o .IR dumpfile ] .RB [ \-i ] .I ttfile @@ -18,7 +18,7 @@ ttfdump \- Dumping the contents of a TrueType Font file \fBttfdump\fP dumps the contents of a TrueType font file in ASCII form. A TrueType font file is consist of various tables. Those table are divided into two categories - \fIRequired Tables\fP and \fIOptional Tables\fP. Mulitiple -TrueType fonts and be merged to a TrueType Collection. +TrueType fonts can be merged to a TrueType Collection. .SS Options .TP \fB-h\fP @@ -96,6 +96,14 @@ vertical metrics header .TP \fIvmtx\fP vertical metrics +.TP +\fBAdditional OpenType Tables\fR +.TP +\fIGPOS\fP +glyph positioning table +.TP +\fIGSUB\fP +glyph substitution table .RE .TP \fB-g\fI glyphnumber\fR diff --git a/Build/source/texk/ttfdump/include/gpos.h b/Build/source/texk/ttfdump/include/gpos.h new file mode 100644 index 00000000000..23e5bda0846 --- /dev/null +++ b/Build/source/texk/ttfdump/include/gpos.h @@ -0,0 +1,229 @@ +/* gpos.h -- define data structures for Glyph Positioning Table + */ + +#ifndef __TTF_GPOS_H +#define __TTF_GPOS_H + +/* ValueFormat Bits */ +#define ValueFormat_XPlacement 0x0001 << 0 +#define ValueFormat_YPlacement 0x0001 << 1 +#define ValueFormat_XAdvance 0x0001 << 2 +#define ValueFormat_YAdvance 0x0001 << 3 +#define ValueFormat_AllDesign 0x000f +#define ValueFormat_XPlaDevice 0x0010 << 0 +#define ValueFormat_YPlaDevice 0x0010 << 1 +#define ValueFormat_XAdvDevice 0x0010 << 2 +#define ValueFormat_YAdvDevice 0x0010 << 3 +#define ValueFormat_AllDevice 0x00f0 +#define ValueFormat_Reserved 0xff00 + +/* Positioning LookupType Values */ +#define PosLookup_SingleAdjustment 1 +#define PosLookup_PairAdjustment 2 +#define PosLookup_CursiveAttachment 3 +#define PosLookup_MarkToBaseAttachment 4 +#define PosLookup_MarkToLigatureAttachment 5 +#define PosLookup_MarkToMarkAttachment 6 +#define PosLookup_ContextPositioning 7 +#define PosLookup_ChainedContextPositioning 8 +#define PosLookup_ExtensionPositioning 9 +#define PosLookup_Max 9 + +typedef struct +{ + SHORT valDesign[4]; + DevicePtr valDevice[4]; +} +ValueRecord, *ValueRecordPtr; + +typedef struct +{ + USHORT anchorFormat; /* = 1 */ + SHORT xCoordinate; + SHORT yCoordinate; +} +Anchor1, *Anchor1Ptr; + +typedef struct +{ + USHORT anchorFormat; /* = 2 */ + SHORT xCoordinate; + SHORT yCoordinate; + USHORT anchorPoint; +} +Anchor2, *Anchor2Ptr; + +typedef struct +{ + USHORT anchorFormat; /* = 3 */ + SHORT xCoordinate; + SHORT yCoordinate; + DevicePtr xDevice; + DevicePtr yDevice; +} +Anchor3, *Anchor3Ptr; + +typedef union +{ + Anchor1Ptr anchor1; + Anchor2Ptr anchor2; + Anchor3Ptr anchor3; +} +AnchorPtr; + +typedef struct +{ + USHORT class; + AnchorPtr markAnchor; +} +MarkRecord, *MarkRecordPtr; + +typedef struct +{ + USHORT lookupType; /* = 1 */ + USHORT lookupFormat; /* = 1 */ + CoveragePtr coverage; + USHORT valueFormat; + ValueRecordPtr value; +} +Pos11, *Pos11Ptr; + +typedef struct +{ + USHORT lookupType; /* = 1 */ + USHORT lookupFormat; /* = 2 */ + CoveragePtr coverage; + USHORT valueFormat; + USHORT valueCount; + ValueRecordPtr *value; /* length = valueCount */ +} +Pos12, *Pos12Ptr; + +typedef struct +{ + USHORT secondGlyph; + ValueRecordPtr value1; + ValueRecordPtr value2; +} +PairValueRecord, *PairValueRecordPtr; + +typedef struct +{ + USHORT pairValueCount; + PairValueRecordPtr pairValue; /* length = pairValueCount */ +} +PairSet, *PairSetPtr; + +typedef struct +{ + USHORT lookupType; /* = 2 */ + USHORT lookupFormat; /* = 1 */ + CoveragePtr coverage; + USHORT valueFormat1; + USHORT valueFormat2; + USHORT pairSetCount; + PairSetPtr pairSet; /* length = pairSetCount */ +} +Pos21, *Pos21Ptr; + +typedef struct +{ + USHORT lookupType; /* = 2 */ + USHORT lookupFormat; /* = 2 */ + CoveragePtr coverage; + USHORT valueFormat1; + USHORT valueFormat2; + ClassDefPtr classDef1; + ClassDefPtr classDef2; + USHORT class1Count; + USHORT class2Count; + ValueRecordPtr *values; /* length = 2 * class1Count * class2Count */ +} +Pos22, *Pos22Ptr; + +typedef struct +{ + USHORT lookupType; /* = 3 */ + USHORT lookupFormat; /* = 1 */ + CoveragePtr coverage; + USHORT entryExitCount; + AnchorPtr *entryExit; /* length = 2 * entryExitCount */ +} +Pos31, *Pos31Ptr; + +typedef struct +{ + USHORT lookupType; /* = 4 */ + USHORT lookupFormat; /* = 1 */ + CoveragePtr markCoverage; + CoveragePtr baseCoverage; + USHORT markCount; + USHORT baseCount; + USHORT classCount; + MarkRecordPtr markArray; /* length = markCount */ + AnchorPtr *baseArray; /* length = baseCount * classCount */ +} +Pos41, *Pos41Ptr; + +typedef struct +{ + USHORT componentCount; + AnchorPtr *componentRecord; /* length = componentCount * classCount */ +} +LigatureAttach, *LigatureAttachPtr; + +typedef struct +{ + USHORT lookupType; /* = 5 */ + USHORT lookupFormat; /* = 1 */ + CoveragePtr markCoverage; + CoveragePtr ligatureCoverage; + USHORT markCount; + USHORT ligatureCount; + USHORT classCount; + MarkRecordPtr markArray; /* length = markCount */ + LigatureAttachPtr ligatureArray; /* length = ligatureCount */ +} +Pos51, *Pos51Ptr; + +typedef struct +{ + USHORT lookupType; /* = 6 */ + USHORT lookupFormat; /* = 1 */ + CoveragePtr mark1Coverage; + CoveragePtr mark2Coverage; + USHORT mark1Count; + USHORT mark2Count; + USHORT classCount; + MarkRecordPtr mark1Array; /* length = mark1Count */ + AnchorPtr *mark2Array; /* length = mark2Count * classCount */ +} +Pos61, *Pos61Ptr; + +#define Pos71Ptr OtfCtx1Ptr +#define Pos72Ptr OtfCtx2Ptr +#define Pos73Ptr OtfCtx3Ptr +#define Pos81Ptr OtfChn1Ptr +#define Pos82Ptr OtfChn2Ptr +#define Pos83Ptr OtfChn3Ptr + +typedef union +{ + Pos11Ptr pos11; + Pos12Ptr pos12; + Pos21Ptr pos21; + Pos22Ptr pos22; + Pos31Ptr pos31; + Pos41Ptr pos41; + Pos51Ptr pos51; + Pos61Ptr pos61; + Pos71Ptr pos71; + Pos72Ptr pos72; + Pos73Ptr pos73; + Pos81Ptr pos81; + Pos82Ptr pos82; + Pos83Ptr pos83; +} +PosLookupPtr; + +#endif /* __TTF_GPOS_H */ diff --git a/Build/source/texk/ttfdump/include/gsub.h b/Build/source/texk/ttfdump/include/gsub.h new file mode 100644 index 00000000000..725d60e8cde --- /dev/null +++ b/Build/source/texk/ttfdump/include/gsub.h @@ -0,0 +1,134 @@ +/* gsub.h -- define data structures for Glyph Substitution Table + */ + +#ifndef __TTF_GSUB_H +#define __TTF_GSUB_H + +/* Substitution LookupType Values */ +#define SubLookup_Single 1 +#define SubLookup_Multiple 2 +#define SubLookup_Alternate 3 +#define SubLookup_Ligature 4 +#define SubLookup_Context 5 +#define SubLookup_ChainingContext 6 +#define SubLookup_ExtensionSubstitution 7 +#define SubLookup_ReverseChainingContextSingle 8 +#define SubLookup_Max 8 + +typedef struct +{ + USHORT lookupType; /* = 1 */ + USHORT lookupFormat; /* = 1 */ + CoveragePtr coverage; + SHORT deltaGlyphID; +} +Sub11, *Sub11Ptr; + +typedef struct +{ + USHORT lookupType; /* = 1 */ + USHORT lookupFormat; /* = 2 */ + CoveragePtr coverage; + USHORT glyphCount; + USHORT *substitute; /* length = glyphCount */ +} +Sub12, *Sub12Ptr; + +typedef struct +{ + USHORT glyphCount; + USHORT *substitute; /* length = glyphCount */ +} +Sequence, *SequencePtr; + +typedef struct +{ + USHORT lookupType; /* = 2 */ + USHORT lookupFormat; /* = 1 */ + CoveragePtr coverage; + USHORT sequenceCount; + SequencePtr sequence; /* length = sequenceCount */ +} +Sub21, *Sub21Ptr; + +typedef struct +{ + USHORT glyphCount; + USHORT *alternate; /* length = glyphCount */ +} +AlternateSet, *AlternateSetPtr; + +typedef struct +{ + USHORT lookupType; /* = 3 */ + USHORT lookupFormat; /* = 1 */ + CoveragePtr coverage; + USHORT alternateSetCount; + AlternateSetPtr alternateSet; /* length = alternateSetCount */ +} +Sub31, *Sub31Ptr; + +typedef struct +{ + USHORT ligGlyph; + USHORT compCount; + USHORT *component; /* length = compCount - 1 */ +} +Ligature, *LigaturePtr; + +typedef struct +{ + USHORT ligatureCount; + LigaturePtr ligature; /* length = ligatureCount */ +} +LigatureSet, *LigatureSetPtr; + +typedef struct +{ + USHORT lookupType; /* = 4 */ + USHORT lookupFormat; /* = 1 */ + CoveragePtr coverage; + USHORT ligSetCount; + LigatureSetPtr ligatureSet; /* length = ligSetCount */ +} +Sub41, *Sub41Ptr; + +#define Sub51Ptr OtfCtx1Ptr +#define Sub52Ptr OtfCtx2Ptr +#define Sub53Ptr OtfCtx3Ptr +#define Sub61Ptr OtfChn1Ptr +#define Sub62Ptr OtfChn2Ptr +#define Sub63Ptr OtfChn3Ptr + +typedef struct +{ + USHORT lookupType; /* = 8 */ + USHORT lookupFormat; /* = 1 */ + CoveragePtr coverage; + USHORT backtrackGlyphCount; + CoveragePtr *backtrack; /* length = backtrackGlyphCount */ + USHORT lookaheadGlyphCount; + CoveragePtr *lookahead; /* length = lookaheadGlyphCount */ + USHORT glyphCount; + USHORT *substitute; /* length = glyphCount */ +} +Sub81, *Sub81Ptr; + +typedef union +{ + Sub11Ptr sub11; + Sub12Ptr sub12; + Sub21Ptr sub21; + Sub31Ptr sub31; + Sub41Ptr sub41; + Sub51Ptr sub51; + Sub52Ptr sub52; + Sub53Ptr sub53; + Sub61Ptr sub61; + Sub62Ptr sub62; + Sub63Ptr sub63; + Sub81Ptr sub81; +} +SubLookupPtr; + +#endif /* __TTF_SUB_H */ diff --git a/Build/source/texk/ttfdump/include/loadtable.h b/Build/source/texk/ttfdump/include/loadtable.h index 9bf74f0b5ab..f44c12dc69c 100644 --- a/Build/source/texk/ttfdump/include/loadtable.h +++ b/Build/source/texk/ttfdump/include/loadtable.h @@ -9,6 +9,8 @@ void ttfLoadRequiredTables(TTFontPtr font); void ttfFreeRequiredTables(TTFontPtr font); void ttfLoadOptionalTables(TTFontPtr font); void ttfFreeOptionalTables(TTFontPtr font); +void ttfLoadOpenTypeTables(TTFontPtr font); +void ttfFreeOpenTypeTables(TTFontPtr font); void ttfInitTableDir(TTFontPtr font, ULONG offset); void ttfPrintTableDir(FILE *fp, TableDirPtr p); @@ -17,8 +19,7 @@ TableDirPtr ttfLookUpTableDir(ULONG tag, TTFontPtr font); void ttfInitCMAP(TTFontPtr font); void ttfPrintCMAP(FILE *fp, CMAPPtr cmap); -USHORT ttfLookUpCMAP(SubTablePtr subTable, USHORT cc); -SubTablePtr ttfSelectCMAP(CMAPPtr cmap, USHORT PlatformID, USHORT EncodingID); +USHORT ttfLookUpCMAP(MapPtr map, USHORT cc); void ttfFreeCMAP(CMAPPtr cmap); void ttfInitGLYF(TTFontPtr font); @@ -93,6 +94,37 @@ void ttfInitVDMX(TTFontPtr font); void ttfPrintVDMX(FILE *fp, VDMXPtr vdmx); void ttfFreeVDMX(VDMXPtr vdmx); +ScriptListPtr otfMakeScriptList(FILE *fp, ULONG offset); +void otfPrintScriptList(FILE *fp, ScriptListPtr scriptList); +void otfFreeScriptList(ScriptListPtr scriptList); + +FeatureListPtr otfMakeFeatureList(FILE *fp, ULONG offset); +void otfPrintFeatureList(FILE *fp, FeatureListPtr featureList); +void otfFreeFeatureList(FeatureListPtr featureList); + +LookupListPtr otfMakeLookupList(FILE *fp, ULONG offset, MakeLookupFunc makeLookup); +void otfPrintLookupList(FILE *fp, LookupListPtr lookupList, PrintLookupFunc printLookup); +void otfFreeLookupList(LookupListPtr lookupList, FreeLookupFunc freeLookup); + +CoveragePtr otfMakeCoverage(FILE *fp, ULONG offset); +void otfPrintCoverage(FILE *fp, CoveragePtr coverage); +void otfFreeCoverage(CoveragePtr coverage); + +ClassDefPtr otfMakeClassDef(FILE *fp, ULONG offset); +void otfPrintClassDef(FILE *fp, ClassDefPtr classDef); +void otfFreeClassDef(ClassDefPtr classDef); + +DevicePtr otfMakeDevice(FILE *fp, ULONG offset); +void otfPrintDevice(FILE *fp, DevicePtr device); + +void ttfInitGPOS(TTFontPtr font); +void ttfPrintGPOS(FILE *fp, GPOSPtr gpos); +void ttfFreeGPOS(GPOSPtr gpos); + +void ttfInitGSUB(TTFontPtr font); +void ttfPrintGSUB(FILE *fp, GSUBPtr gsub); +void ttfFreeGSUB(GSUBPtr gsub); + void ttfInitGraphicsState(TTFontPtr font); void ttfInitStack(TTFontPtr font); void ttfInitStorageArea(TTFontPtr font); diff --git a/Build/source/texk/ttfdump/include/otftables.h b/Build/source/texk/ttfdump/include/otftables.h new file mode 100644 index 00000000000..5a6cc54c57e --- /dev/null +++ b/Build/source/texk/ttfdump/include/otftables.h @@ -0,0 +1,368 @@ +/* otftables.h -- define data structures for various OpenType Tables + * See Also: OpenType Specification + */ + +#ifndef __TTF_OTFTABLES_H +#define __TTF_OTFTABLES_H + +typedef struct +{ + USHORT reqFeatureIndex; + USHORT featureCount; + USHORT *featureIndex; /* length = featureCount */ +} +LangSys, *LangSysPtr; + +typedef struct +{ + ULONG tag; + LangSysPtr langSys; +} +LangSysRecord, *LangSysRecordPtr; + +typedef struct +{ + ULONG tag; + LangSysPtr defaultLangSys; + USHORT langSysCount; + LangSysRecord *langSysRecord; /* length = langSysCount */ +} +ScriptRecord, *ScriptRecordPtr; + +typedef struct +{ + USHORT scriptCount; + ScriptRecord *scriptRecord; /* length = scriptCount */ +} +ScriptList, *ScriptListPtr; + +typedef struct +{ + ULONG tag; + USHORT featureParams; + USHORT lookupCount; + USHORT *lookupListIndex; /* length = lookupCount */ +} +FeatureRecord, *FeatureRecordPtr; + +typedef struct +{ + USHORT featureCount; + FeatureRecord *featureRecord; /* length = featureCount */ +} +FeatureList, *FeatureListPtr; + +typedef struct +{ + USHORT start; + USHORT end; + USHORT startCoverageIndex; +} +RangeRecord, *RangeRecordPtr; + +typedef struct +{ + USHORT coverageFormat; /* = 1 */ + USHORT glyphCount; + USHORT *glyphArray; /* length = glyphCount */ +} +Coverage1, *Coverage1Ptr; + +typedef struct +{ + USHORT coverageFormat; /* = 2 */ + USHORT rangeCount; + RangeRecordPtr rangeRecord; /* length = rangeCount */ +} +Coverage2, *Coverage2Ptr; + +typedef union +{ + USHORT *format; + Coverage1Ptr coverage1; + Coverage2Ptr coverage2; +} +CoveragePtr; + +typedef struct +{ + USHORT start; + USHORT end; + USHORT classValue; +} +ClassRangeRecord, *ClassRangeRecordPtr; + +typedef struct +{ + USHORT classFormat; /* = 1 */ + USHORT startGlyph; + USHORT glyphCount; + USHORT *classValueArray; /* length = glyphCount */ +} +ClassDef1, *ClassDef1Ptr; + +typedef struct +{ + USHORT classFormat; /* = 2 */ + USHORT classRangeCount; + ClassRangeRecordPtr classRangeRecord; /* length = classRangeCount */ +} +ClassDef2, *ClassDef2Ptr; + +typedef union +{ + USHORT *format; + ClassDef1Ptr classDef1; + ClassDef2Ptr classDef2; +} +ClassDefPtr; + +typedef struct +{ + USHORT startSize; + USHORT endSize; + USHORT deltaFormat; /* = 1, 2, or 3 */ + USHORT deltaValue[1]; /* variable size + * (endSize-startSize+1) entries + * 8, 4, or 2 entries per array element */ +} +Device, *DevicePtr; + +typedef struct +{ + USHORT sequenceIndex; + USHORT lookupListIndex; +} +OtfLookupRecord, *OtfLookupRecordPtr; + +typedef struct +{ + USHORT glyphCount; + USHORT otfCount; + USHORT *input; /* length = glyphCount - 1 */ + OtfLookupRecordPtr otf; /* length = otfCount */ +} +OtfRule, *OtfRulePtr; + +typedef struct +{ + USHORT otfRuleCount; + OtfRulePtr otfRule; /* length = otfRuleCount */ +} +OtfRuleSet, *OtfRuleSetPtr; + +typedef struct +{ + USHORT lookupType; /* = 7 (GPOS) or 5 (GSUB) */ + USHORT lookupFormat; /* = 1 */ + CoveragePtr coverage; + USHORT otfRuleSetCount; + OtfRuleSetPtr otfRuleSet; /* length = otfRuleSetCount */ +} +OtfCtx1, *OtfCtx1Ptr; + +OtfCtx1Ptr makeOTFCtx1 (FILE *fp, ULONG offset); +void printOTFCtx1 (FILE *fp, OtfCtx1Ptr otf); +void freeOTFCtx1 (OtfCtx1Ptr otf); + +typedef struct +{ + USHORT glyphCount; + USHORT otfCount; + USHORT *class; /* length = glyphCount - 1 */ + OtfLookupRecordPtr otf; /* length = otfCount */ +} +OtfClassRule, *OtfClassRulePtr; + +typedef struct +{ + USHORT otfClassRuleCnt; + OtfClassRulePtr otfClassRule; /* length = otfClassRuleCnt */ +} +OtfClassSet, *OtfClassSetPtr; + +typedef struct +{ + USHORT lookupType; /* = 7 (GPOS) or 5 (GSUB) */ + USHORT lookupFormat; /* = 2 */ + CoveragePtr coverage; + ClassDefPtr classDef; + USHORT otfClassSetCnt; + OtfClassSetPtr otfClassSet; /* length = otfClassSetCnt */ +} +OtfCtx2, *OtfCtx2Ptr; + +OtfCtx2Ptr makeOTFCtx2 (FILE *fp, ULONG offset); +void printOTFCtx2 (FILE *fp, OtfCtx2Ptr otf); +void freeOTFCtx2 (OtfCtx2Ptr otf); + +typedef struct +{ + USHORT lookupType; /* = 7 (GPOS) or 5 (GSUB) */ + USHORT lookupFormat; /* = 3 */ + USHORT glyphCount; + USHORT otfCount; + CoveragePtr *glyphs; /* length = glyphCount */ + OtfLookupRecordPtr otf; /* length = otfCount */ +} +OtfCtx3, *OtfCtx3Ptr; + +OtfCtx3Ptr makeOTFCtx3 (FILE *fp, ULONG offset); +void printOTFCtx3 (FILE *fp, OtfCtx3Ptr otf); +void freeOTFCtx3 (OtfCtx3Ptr otf); + +typedef struct +{ + USHORT backtrackGlyphCount; + USHORT *backtrack; /* length = backtrackGlyphCount */ + USHORT inputGlyphCount; + USHORT *input; /* length = inputGlyphCount - 1 */ + USHORT lookaheadGlyphCount; + USHORT *lookahead; /* length = lookaheadGlyphCount */ + USHORT otfCount; + OtfLookupRecordPtr otf; /* length = otfCount */ +} +ChainOtfRule, *ChainOtfRulePtr; + +typedef struct +{ + USHORT chainOtfRuleCount; + ChainOtfRulePtr chainOtfRule; /* length = chainOtfRuleCount */ +} +ChainOtfRuleSet, *ChainOtfRuleSetPtr; + +typedef struct +{ + USHORT lookupType; /* = 8 (GPOS) or 6 (GSUB) */ + USHORT lookupFormat; /* = 1 */ + CoveragePtr coverage; + USHORT chainOtfRuleSetCount; + ChainOtfRuleSetPtr chainOtfRuleSet; /* length = chainOtfRuleSetCount */ +} +OtfChn1, *OtfChn1Ptr; + +OtfChn1Ptr makeOTFChn1 (FILE *fp, ULONG offset); +void printOTFChn1 (FILE *fp, OtfChn1Ptr otf); +void freeOTFChn1 (OtfChn1Ptr otf); + +typedef struct +{ + USHORT backtrackGlyphCount; + USHORT *backtrack; /* length = backtrackGlyphCount */ + USHORT inputGlyphCount; + USHORT *input; /* length = inputGlyphCount - 1 */ + USHORT lookaheadGlyphCount; + USHORT *lookahead; /* length = lookaheadGlyphCount */ + USHORT otfCount; + OtfLookupRecordPtr otf; /* length = otfCount */ +} +ChainOtfClassRule, *ChainOtfClassRulePtr; + +typedef struct +{ + USHORT chainOtfClassRuleCnt; + ChainOtfClassRulePtr chainOtfClassRule; /* length = chainOtfClassRuleCnt */ +} +ChainOtfClassSet, *ChainOtfClassSetPtr; + +typedef struct +{ + USHORT lookupType; /* = 8 (GPOS) or 6 (GSUB) */ + USHORT lookupFormat; /* = 2 */ + CoveragePtr coverage; + ClassDefPtr backtrackClassDef; + ClassDefPtr inputClassDef; + ClassDefPtr lookaheadClassDef; + USHORT chainOtfClassSetCnt; + ChainOtfClassSetPtr chainOtfClassSet; /* length = chainOtfClassSetCnt */ +} +OtfChn2, *OtfChn2Ptr; + +OtfChn2Ptr makeOTFChn2 (FILE *fp, ULONG offset); +void printOTFChn2 (FILE *fp, OtfChn2Ptr otf); +void freeOTFChn2 (OtfChn2Ptr otf); + +typedef struct +{ + USHORT lookupType; /* = 8 (GPOS) or 6 (GSUB) */ + USHORT lookupFormat; /* = 3 */ + USHORT backtrackGlyphCount; + CoveragePtr *backtrack; /* length = backtrackGlyphCount */ + USHORT inputGlyphCount; + CoveragePtr *input; /* length = inputGlyphCount */ + USHORT lookaheadGlyphCount; + CoveragePtr *lookahead; /* length = lookaheadGlyphCount */ + USHORT otfCount; + OtfLookupRecordPtr otf; /* length = otfCount */ +} +OtfChn3, *OtfChn3Ptr; + +OtfChn3Ptr makeOTFChn3 (FILE *fp, ULONG offset); +void printOTFChn3 (FILE *fp, OtfChn3Ptr otf); +void freeOTFChn3 (OtfChn3Ptr otf); + +#include "gpos.h" +#include "gsub.h" + +typedef struct +{ + USHORT lookupType; + USHORT lookupFormat; +} +OtfLookup, *OtfLookupPtr; + +typedef union +{ + OtfLookupPtr otf; + PosLookupPtr pos; + SubLookupPtr sub; +} +LookupPtr; + +typedef struct +{ + USHORT lookupFlag; + USHORT subTableCount; + USHORT markFilteringSet; + LookupPtr *lookup; /* length = subTableCount */ +} LookupRecord, *LookupRecordPtr; + +/* LookupFlag Bits */ +#define LookupFlag_RightToLeft 0x0001 +#define lookupFlag_IgnoreBaseGlyphs 0x0002 +#define lookupFlag_IgnoreLigatures 0x0004 +#define lookupFlag_IgnoreMarks 0x0008 +#define lookupFlag_UseMarkFilteringSet 0x0010 +#define lookupFlag_Reserved 0x00e0 +#define lookupFlag_MarkAttachmentType 0xff00 + +typedef struct +{ + USHORT lookupCount; + LookupRecord *lookupRecord; +} +LookupList, *LookupListPtr; + +typedef LookupPtr (MakeLookupFunc) (FILE *fp, USHORT lookupType, ULONG offset); +typedef void (PrintLookupFunc) (FILE *fp, LookupPtr lookup); +typedef void (FreeLookupFunc) (LookupPtr lookup); + +typedef struct +{ + Fixed version; + ScriptListPtr scriptList; + FeatureListPtr featureList; + LookupListPtr lookupList; +} +GPOS, *GPOSPtr; + +typedef struct +{ + Fixed version; + ScriptListPtr scriptList; + FeatureListPtr featureList; + LookupListPtr lookupList; +} +GSUB, *GSUBPtr; + +#endif /* __TTF_OTFTABLES_H */ diff --git a/Build/source/texk/ttfdump/include/tables.h b/Build/source/texk/ttfdump/include/tables.h index cef49726cb9..ed05e4f5385 100644 --- a/Build/source/texk/ttfdump/include/tables.h +++ b/Build/source/texk/ttfdump/include/tables.h @@ -1,16 +1,16 @@ -/* table.h -- define data structures for various ttf file internal tables +/* tables.h -- define data structures for various ttf file internal tables * See Also: True Type Font Specification */ -#ifndef __TTF_TABLE_H -#define __TTF_TABLE_H +#ifndef __TTF_TABLES_H +#define __TTF_TABLES_H /* $Id: tables.h,v 1.2 1998/07/06 06:07:01 werner Exp $ */ /* Offset Table: * Into the beginning of a True Type font file */ -typedef struct _OffsetTable +typedef struct { Fixed version; USHORT numTables; @@ -23,7 +23,7 @@ OffsetTable, *OffsetTablePtr; /* Table Directory: * The directory to find each table in a True Type font file */ -typedef struct _TableDir +typedef struct { ULONG tag; ULONG checksum; @@ -34,16 +34,19 @@ TableDir, *TableDirPtr; /* cmap: Character to Glyph Index Mapping Table - * There are four kinds of cmap, format 0, 2, 4, and 6. They are defined - * as follows + * There are nine kinds of cmap, format 0, 2, 4, 6, 8, 10, 12, + * 13, and 14. They are defined as follows */ typedef struct { + USHORT format; /* = 0 */ + USHORT length; + USHORT version; BYTE glyphIndexArray[256]; } CMAP0; -typedef struct _subHeaders +typedef struct { USHORT firstCode; USHORT entryCount; @@ -54,6 +57,9 @@ SubHeader, *SubHeaderPtr; typedef struct { + USHORT format; /* = 2 */ + USHORT length; + USHORT version; USHORT subHeaderKeys[256]; SubHeaderPtr subHeaders; USHORT *glyphIndexArray; @@ -62,6 +68,9 @@ CMAP2; typedef struct { + USHORT format; /* = 4 */ + USHORT length; + USHORT version; USHORT segCountX2; USHORT searchRange; USHORT entrySelector; @@ -73,43 +82,125 @@ typedef struct USHORT *idRangeOffset; USHORT *glyphIndexArray; } - CMAP4; + typedef struct { + USHORT format; /* = 6 */ + USHORT length; + USHORT version; USHORT firstCode; USHORT entryCount; USHORT *glyphIndexArray; } CMAP6; -/* SubTable: one for each encoding scheme */ +typedef struct +{ + ULONG startCharCode; + ULONG endCharCode; + ULONG startGlyphID; +} +CharGroup, *CharGroupPtr; + +typedef struct +{ + USHORT format; /* = 8 */ + ULONG length; + ULONG version; + BYTE is32[8192]; + ULONG nGroups; + CharGroupPtr charGroup; /* size = nGroups */ +} +CMAP8; + +typedef struct +{ + USHORT format; /* = 10 */ + ULONG length; + ULONG version; + ULONG startCharCode; + ULONG numChars; + USHORT *glyphs; +} +CMAP10; + +typedef struct +{ + USHORT format; /* = 12 */ + ULONG length; + ULONG version; + ULONG nGroups; + CharGroupPtr charGroup; /* size = nGroups */ +} +CMAP12; + +typedef struct +{ + USHORT format; /* = 13 */ + ULONG length; + ULONG version; + ULONG nGroups; + CharGroupPtr charGroup; /* size = nGroups */ +} +CMAP13; + +typedef struct +{ + int notYet; +} +VarSelRec, *VarSelRecPtr; + +typedef struct +{ + USHORT format; /* = 14 */ + ULONG length; + ULONG numVarSelRec; + VarSelRecPtr varSelRec; /* size = numVarSelRec */ +} +CMAP14; + +typedef union +{ + USHORT *format; + CMAP0 *cmap0; + CMAP2 *cmap2; + CMAP4 *cmap4; + CMAP6 *cmap6; + CMAP8 *cmap8; + CMAP10 *cmap10; + CMAP12 *cmap12; + CMAP13 *cmap13; + CMAP14 *cmap14; +} +MapPtr; + +/* Encoding: one for each encoding scheme */ typedef struct { /* encoding table */ USHORT PlatformID; USHORT EncodingID; ULONG offset; + USHORT mapindex; + MapPtr map; +} +Encoding, *EncodingPtr; - USHORT format; - USHORT length; - USHORT version; - union - { - CMAP0 *cmap0; - CMAP2 *cmap2; - CMAP4 *cmap4; - CMAP6 *cmap6; - } - map; +typedef struct +{ + ULONG offset; + MapPtr map; } SubTable, *SubTablePtr; -typedef struct _cmap +typedef struct { USHORT version; USHORT numberOfEncodings; - SubTablePtr subTables; /* size = numberOfEncodings */ + USHORT numberOfMaps; + EncodingPtr encoding; /* size = numberOfEncodings */ + SubTablePtr subTable; /* size = numberOfMaps */ } CMAP, *CMAPPtr; @@ -209,8 +300,8 @@ typedef struct ULONG magicNumber; USHORT flags; USHORT unitsPerEm; - BYTE created[8]; - BYTE modified[8]; + ULONG created[2]; + ULONG modified[2]; FWord xMin; FWord yMin; FWord xMax; @@ -258,7 +349,7 @@ HHEA, *HHEAPtr; /* for a new created HMTX, one have to fill numberofHMetrics manually for * hhea */ -typedef struct _longHorMetric +typedef struct { uFWord advanceWidth; FWord lsb; @@ -579,7 +670,10 @@ typedef struct } VMTX, *VMTXPtr; -#endif /* __TTF_TABLE_H */ +/* Additional OpenType Tables */ +#include "otftables.h" + +#endif /* __TTF_TABLES_H */ /* end of tables.h */ diff --git a/Build/source/texk/ttfdump/include/ttf.h b/Build/source/texk/ttfdump/include/ttf.h index dd226235b23..57fa03ed1a3 100644 --- a/Build/source/texk/ttfdump/include/ttf.h +++ b/Build/source/texk/ttfdump/include/ttf.h @@ -121,7 +121,7 @@ typedef struct * OffsetTables */ ULONG glyphOffset; /* where the glyph table starts */ TableDirPtr dir; /* Pointer to Table Directories */ - SubTablePtr encoding; /* `encoding' is the currently used encoding + EncodingPtr encoding; /* `encoding' is the currently used encoding * table */ USHORT numCacheElements; /* number of glyph cache elements */ @@ -158,6 +158,10 @@ typedef struct VDMXPtr vdmx; VHEAPtr vhea; VMTXPtr vmtx; + + /* Additional OpenType Tables */ + GPOSPtr gpos; + GSUBPtr gsub; } TTFont, *TTFontPtr; diff --git a/Build/source/texk/ttfdump/include/ttfutil.h b/Build/source/texk/ttfdump/include/ttfutil.h index e660bfce5fa..28be2cdd070 100644 --- a/Build/source/texk/ttfdump/include/ttfutil.h +++ b/Build/source/texk/ttfdump/include/ttfutil.h @@ -16,6 +16,7 @@ char *TagToStr(ULONG tag); /* Functions copied or adapted from kpathsea. */ void xfseek (FILE *fp, long offset, int wherefrom, const char *funcname); +long xftell (FILE *fp, const char *funcname); void *xmalloc (size_t size); void *xcalloc (size_t nelem, size_t elsize); char *xstrdup(const char *s); diff --git a/Build/source/texk/ttfdump/libttf/cmap.c b/Build/source/texk/ttfdump/libttf/cmap.c index d876cfb8a96..c3ae65f3b61 100644 --- a/Build/source/texk/ttfdump/libttf/cmap.c +++ b/Build/source/texk/ttfdump/libttf/cmap.c @@ -54,32 +54,56 @@ typedef union _TwoBytes { unsigned char c[2]; } TwoBytes; -static void ttfLoadCMAP(FILE *fp,CMAPPtr cmap,ULONG offset); - -static void ttfLoadEncodingTable(FILE *fp,SubTablePtr subTable,ULONG offset); -static void ttfLoadSubTable(FILE *fp,SubTablePtr subTable,ULONG offset); -static void ttfPrintSubTable(FILE* fp,SubTablePtr ptable); -static void ttfFreeSubTable(SubTablePtr ptable); - -static void ttfLoadCMAP0(FILE *fp,SubTablePtr subTable,ULONG offset); -static void ttfPrintCMAP0(FILE *fp,SubTablePtr subTable); -static USHORT ttfLookUpCMAP0(SubTablePtr subTable,USHORT cc); -static void ttfFreeCMAP0(SubTablePtr subTable); - -static void ttfLoadCMAP2(FILE *fp,SubTablePtr subTable,ULONG offset); -static void ttfPrintCMAP2(FILE *fp,SubTablePtr subTable); -static USHORT ttfLookUpCMAP2(SubTablePtr subTable,USHORT cc); -static void ttfFreeCMAP2(SubTablePtr subTable); - -static void ttfLoadCMAP4(FILE *fp,SubTablePtr subTable,ULONG offset); -static void ttfPrintCMAP4(FILE *fp,SubTablePtr subTable); -static USHORT ttfLookUpCMAP4(SubTablePtr subTable,USHORT cc); -static void ttfFreeCMAP4(SubTablePtr subTable); - -static void ttfLoadCMAP6(FILE *fp,SubTablePtr subTable,ULONG offset); -static void ttfPrintCMAP6(FILE *fp, SubTablePtr sbuTable); -static USHORT ttfLookUpCMAP6(SubTablePtr subTable,USHORT cc); -static void ttfFreeCMAP6(SubTablePtr subTable); +static void ttfLoadCMAP(FILE *fp, CMAPPtr cmap, ULONG offset); + +static void ttfLoadSubTable(FILE *fp, SubTablePtr subTable, ULONG offset); +static void ttfPrintSubTable(FILE* fp, SubTablePtr subTable); +static void ttfFreeSubTable(SubTablePtr subTable); + +static void ttfLoadCMAP0(FILE *fp, MapPtr *map); +static void ttfPrintCMAP0(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP0(MapPtr map, USHORT cc); +static void ttfFreeCMAP0(MapPtr map); + +static void ttfLoadCMAP2(FILE *fp, MapPtr *map); +static void ttfPrintCMAP2(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP2(MapPtr map, USHORT cc); +static void ttfFreeCMAP2(MapPtr map); + +static void ttfLoadCMAP4(FILE *fp, MapPtr *map); +static void ttfPrintCMAP4(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP4(MapPtr map, USHORT cc); +static void ttfFreeCMAP4(MapPtr map); + +static void ttfLoadCMAP6(FILE *fp, MapPtr *map); +static void ttfPrintCMAP6(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP6(MapPtr map, USHORT cc); +static void ttfFreeCMAP6(MapPtr map); + +static void ttfLoadCMAP8(FILE *fp, MapPtr *map); +static void ttfPrintCMAP8(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP8(MapPtr map, ULONG cc); +static void ttfFreeCMAP8(MapPtr map); + +static void ttfLoadCMAP10(FILE *fp, MapPtr *map); +static void ttfPrintCMAP10(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP10(MapPtr map, ULONG cc); +static void ttfFreeCMAP10(MapPtr map); + +static void ttfLoadCMAP12(FILE *fp, MapPtr *map); +static void ttfPrintCMAP12(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP12(MapPtr map, ULONG cc); +static void ttfFreeCMAP12(MapPtr map); + +static void ttfLoadCMAP13(FILE *fp, MapPtr *map); +static void ttfPrintCMAP13(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP13(MapPtr map, ULONG cc); +static void ttfFreeCMAP13(MapPtr map); + +static void ttfLoadCMAP14(FILE *fp, MapPtr *map); +static void ttfPrintCMAP14(FILE *fp, MapPtr map); +static USHORT ttfLookUpCMAP14(MapPtr map, ULONG cc); +static void ttfFreeCMAP14(MapPtr map); void ttfInitCMAP(TTFontPtr font) { @@ -87,34 +111,47 @@ void ttfInitCMAP(TTFontPtr font) TableDirPtr ptd; if ((ptd = ttfLookUpTableDir(tag,font)) != NULL) - { - font->cmap = XCALLOC1 (CMAP); - ttfLoadCMAP(font->fp,font->cmap,ptd->offset); - } + { + font->cmap = XCALLOC1 (CMAP); + ttfLoadCMAP(font->fp,font->cmap,ptd->offset); + } } static void ttfLoadCMAP(FILE *fp,CMAPPtr cmap,ULONG offset) { USHORT i,n; - ULONG posEnc; /* beginning of the Encoding Table */ - ULONG baseSub = offset; /* base of SubTable offset */ + int k = 0; xfseek(fp, offset, SEEK_SET, "ttfLoadCMAP"); cmap->version = ttfGetUSHORT(fp); cmap->numberOfEncodings = n = ttfGetUSHORT(fp); - cmap->subTables = XCALLOC (cmap->numberOfEncodings, SubTable); - - posEnc = baseSub + sizeof(USHORT)*2; /* step over the beginning of encoding - * table */ - - /* for each encoding scheme, load the encoding table (EncodingTable) and - * the real cmap data (SubTable) */ - for (i=0;i<n;i++,posEnc += 8) - { /* 8 == ushort*2 + ulong*1 */ - ttfLoadEncodingTable(fp,cmap->subTables+i,posEnc); - ttfLoadSubTable(fp,cmap->subTables+i,baseSub); - } + cmap->encoding = XCALLOC (cmap->numberOfEncodings, Encoding); + + for (i = 0; i < n; i++) + { + int j; + + cmap->encoding[i].PlatformID = ttfGetUSHORT(fp); + cmap->encoding[i].EncodingID = ttfGetUSHORT(fp); + cmap->encoding[i].offset = ttfGetULONG(fp); + cmap->encoding[i].mapindex = k++; + for (j = 0; j < i; j++) { + if (cmap->encoding[i].offset == cmap->encoding[j].offset) + { + cmap->encoding[i].mapindex = cmap->encoding[j].mapindex; + k--; + break; + + } + } + } + cmap->numberOfMaps = k; + cmap->subTable = XCALLOC (cmap->numberOfMaps, SubTable); + for (i = 0; i < n; i++) + cmap->subTable[cmap->encoding[i].mapindex].offset = cmap->encoding[i].offset; + for (i = 0; i < k; i++) + ttfLoadSubTable(fp, cmap->subTable+i, offset); } void ttfPrintCMAP(FILE *fp,CMAPPtr cmap) { @@ -122,75 +159,79 @@ void ttfPrintCMAP(FILE *fp,CMAPPtr cmap) fprintf(fp,"'cmap' Table - Character to Glyph Index Mapping Table\n"); fprintf(fp,"-----------------------------------------------------\n"); - fprintf(fp,"\t 'cmap' version: %d\n",cmap->version); - fprintf(fp,"\t number of encoding: %d\n\n",cmap->numberOfEncodings); - - for (i=0;i<cmap->numberOfEncodings;i++) - { - fprintf(fp,"Subtable %3d.\t",i); - ttfPrintSubTable(fp,cmap->subTables+i); - fprintf(fp,"\n"); - } + fprintf(fp,"\t 'cmap' version: %d\n", cmap->version); + fprintf(fp,"\t number of encodings: %d\n", cmap->numberOfEncodings); + fprintf(fp,"\t number of subtables: %d\n\n", cmap->numberOfMaps); + + for (i = 0; i < cmap->numberOfEncodings; i++) + { + fprintf(fp, "Encoding %3d.\t PlatformID: %2d\n", i, + cmap->encoding[i].PlatformID); + fprintf(fp, "\t\t EcodingID: %2d\n", + cmap->encoding[i].EncodingID); + fprintf(fp, "\t\t SubTable: %d, Offset: 0x%08x\n\n", + cmap->encoding[i].mapindex, cmap->encoding[i].offset); + } + for (i = 0; i < cmap->numberOfMaps; i++) + { + fprintf(fp,"SubTable %3d.\t",i); + ttfPrintSubTable(fp, cmap->subTable+i); + fprintf(fp,"\n"); + } } -USHORT ttfLookUpCMAP(SubTablePtr subTable,USHORT cc) +USHORT ttfLookUpCMAP(MapPtr map, USHORT cc) { - USHORT idx,format = subTable->format; + USHORT idx,format = *map.format; switch (format) - { - case 0: - idx = ttfLookUpCMAP0(subTable,cc); - break; - case 2: - idx = ttfLookUpCMAP2(subTable,cc); - break; - case 4: - idx = ttfLookUpCMAP4(subTable,cc); - break; - case 6: - idx = ttfLookUpCMAP6(subTable,cc); - break; - default: - ttfError("Unrecognized CMAP format\n"); - return 0; - } + { + case 0: + idx = ttfLookUpCMAP0(map, cc); + break; + case 2: + idx = ttfLookUpCMAP2(map, cc); + break; + case 4: + idx = ttfLookUpCMAP4(map, cc); + break; + case 6: + idx = ttfLookUpCMAP6(map, cc); + break; + case 8: + idx = ttfLookUpCMAP8(map, cc); + break; + case 10: + idx = ttfLookUpCMAP10(map, cc); + break; + case 12: + idx = ttfLookUpCMAP12(map, cc); + break; + case 13: + idx = ttfLookUpCMAP13(map, cc); + break; + case 14: + idx = ttfLookUpCMAP14(map, cc); + break; + default: + ttfError("Unrecognized CMAP format\n"); + return 0; + } return idx; } -SubTablePtr ttfSelectCMAP(CMAPPtr cmap, USHORT PlatformID, USHORT EncodingID) -{ - USHORT i; - - for (i=0;i<cmap->numberOfEncodings;i++) - { - if ((cmap->subTables+i)->PlatformID == PlatformID && - (cmap->subTables+i)->EncodingID == EncodingID) - return cmap->subTables+i; - } - return NULL; -} void ttfFreeCMAP(CMAPPtr cmap) { USHORT i; - for (i=0;i<cmap->numberOfEncodings;i++) - ttfFreeSubTable(cmap->subTables+i); + free(cmap->encoding); - free(cmap->subTables); - free(cmap); -} + for (i = 0; i < cmap->numberOfMaps; i++) + ttfFreeSubTable(cmap->subTable+i); + free(cmap->subTable); -/* actually, EncodingTable is a part of SubTable */ -static void ttfLoadEncodingTable(FILE *fp,SubTablePtr subTable,ULONG offset) -{ - xfseek(fp, offset, SEEK_SET, "ttfLoadEncodingTable"); - - subTable->PlatformID = ttfGetUSHORT(fp); - subTable->EncodingID = ttfGetUSHORT(fp); - subTable->offset = ttfGetULONG(fp); + free(cmap); } -/* should this one be static ? */ -static void ttfLoadSubTable(FILE *fp,SubTablePtr subTable,ULONG base) +static void ttfLoadSubTable(FILE *fp, SubTablePtr subTable, ULONG offset) { ULONG pos; USHORT format; @@ -198,239 +239,275 @@ static void ttfLoadSubTable(FILE *fp,SubTablePtr subTable,ULONG base) /* seek to the actuall position for this subtable * base: beginning of cmap * offset: offset field of each encoding table */ - pos = base + subTable->offset; - xfseek(fp, pos, SEEK_SET, "ttfLoadSubTable"); + pos = offset + subTable->offset; + xfseek(fp, pos, SEEK_SET, "ttfLoadEncoding"); - subTable->format = format = ttfGetUSHORT(fp); - subTable->length = ttfGetUSHORT(fp); - subTable->version = ttfGetUSHORT(fp); + format = ttfGetUSHORT(fp); - pos += 6;/* step over format independent data,USHORT*3 */ - switch(format) - { - case 0: - ttfLoadCMAP0(fp,subTable,pos); - break; - case 2: - ttfLoadCMAP2(fp,subTable,pos); - break; - case 4: - ttfLoadCMAP4(fp,subTable,pos); - break; - case 6: - ttfLoadCMAP6(fp,subTable,pos); - break; - default: - ttfError("Unrecognized CMAP format\n"); - } -} -static void ttfPrintSubTable(FILE* fp,SubTablePtr ptable) -{ - USHORT format = ptable->format; - - /* print encoding table */ - fprintf(fp, " PlatformID: %2d\n",ptable->PlatformID); - fprintf(fp,"\t\t EcodingID: %2d\n",ptable->EncodingID); - fprintf(fp,"\t\t 'cmap' Offset: 0x%08x\n",ptable->offset); + { + case 0: + ttfLoadCMAP0(fp, &subTable->map); + break; + case 2: + ttfLoadCMAP2(fp, &subTable->map); + break; + case 4: + ttfLoadCMAP4(fp, &subTable->map); + break; + case 6: + ttfLoadCMAP6(fp, &subTable->map); + break; + case 8: + ttfLoadCMAP8(fp, &subTable->map); + break; + case 10: + ttfLoadCMAP10(fp, &subTable->map); + break; + case 12: + ttfLoadCMAP12(fp, &subTable->map); + break; + case 13: + ttfLoadCMAP13(fp, &subTable->map); + break; + case 14: + ttfLoadCMAP14(fp, &subTable->map); + break; + default: + ttfError("Unrecognized CMAP format\n"); + } + + *subTable->map.format = format; +} +static void ttfPrintSubTable(FILE* fp, SubTablePtr subTable) +{ + USHORT format = *subTable->map.format; - /* print SubTable part */ - fprintf(fp,"\t\t Length: %6d\n",ptable->length); - fprintf(fp,"\t\t Version: %6d\n",ptable->version); - switch(format) - { - case 0: - fprintf(fp,"\t\t Format 0 - Byte encoding table\n"); - ttfPrintCMAP0(fp,ptable); - break; - case 2: - fprintf(fp,"\t\t Format 2 - High-byte mapping through table\n"); - ttfPrintCMAP2(fp,ptable); - break; - case 4: - fprintf(fp,"\t\t Format 4 - Segment mapping to delta values\n"); - ttfPrintCMAP4(fp,ptable); - break; - case 6: - fprintf(fp,"\t\t Format 6 - Trimmed table mapping\n"); - ttfPrintCMAP6(fp,ptable); - break; - default: - ttfError("Unrecognized CMAP format\n"); - } -} -static void ttfFreeSubTable(SubTablePtr ptable) -{ - USHORT format = ptable->format; + { + case 0: + ttfPrintCMAP0(fp, subTable->map); + break; + case 2: + ttfPrintCMAP2(fp, subTable->map); + break; + case 4: + ttfPrintCMAP4(fp, subTable->map); + break; + case 6: + ttfPrintCMAP6(fp, subTable->map); + break; + case 8: + ttfPrintCMAP8(fp, subTable->map); + break; + case 10: + ttfPrintCMAP10(fp, subTable->map); + break; + case 12: + ttfPrintCMAP12(fp, subTable->map); + break; + case 13: + ttfPrintCMAP13(fp, subTable->map); + break; + case 14: + ttfPrintCMAP14(fp, subTable->map); + break; + default: + ttfError("Unrecognized CMAP format\n"); + } +} +static void ttfFreeSubTable(SubTablePtr subTable) +{ + USHORT format = *subTable->map.format; switch(format) - { - case 0: - ttfFreeCMAP0(ptable); - break; - case 2: - ttfFreeCMAP2(ptable); - break; - case 4: - ttfFreeCMAP4(ptable); - break; - case 6: - ttfFreeCMAP6(ptable); - break; - } -} - -static void ttfLoadCMAP0(FILE *fp,SubTablePtr subTable,ULONG offset) + { + case 0: + ttfFreeCMAP0(subTable->map); + break; + case 2: + ttfFreeCMAP2(subTable->map); + break; + case 4: + ttfFreeCMAP4(subTable->map); + break; + case 6: + ttfFreeCMAP6(subTable->map); + break; + case 8: + ttfFreeCMAP8(subTable->map); + break; + case 10: + ttfFreeCMAP10(subTable->map); + break; + case 12: + ttfFreeCMAP12(subTable->map); + break; + case 13: + ttfFreeCMAP13(subTable->map); + break; + case 14: + ttfFreeCMAP14(subTable->map); + break; + } +} + +static void ttfLoadCMAP0(FILE *fp, MapPtr *map) { BYTE * array; - subTable->map.cmap0 = XCALLOC1 (CMAP0); - array = subTable->map.cmap0->glyphIndexArray; - - xfseek(fp, offset, SEEK_SET, "ttfLoadCMAP0"); + map->cmap0 = XCALLOC1 (CMAP0); + map->cmap0->length = ttfGetUSHORT(fp); + map->cmap0->version = ttfGetUSHORT(fp); + array = map->cmap0->glyphIndexArray; /* Attention: we get lots of bytes at once as a work around of the * usual ttfGet*, this cause byte sex trouble as will be seen - * in the fellowing procedures */ + * in the following procedures */ if (fread(array,sizeof(BYTE),256,fp) != 256) - ttfError("Error when getting glyphIndexArray\n"); + ttfError("Error when getting glyphIndexArray\n"); } -static void ttfPrintCMAP0(FILE *fp,SubTablePtr subTable) +static void ttfPrintCMAP0(FILE *fp, MapPtr map) { USHORT index; int i; + fprintf(fp, " Format 0 - Byte encoding table\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap0->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap0->version); for (i=0;i<256;i++) - { - index = ttfLookUpCMAP(subTable,i); - fprintf(fp,"\t\t Char %3d -> Index %4d\n",i,index); - } + { + index = ttfLookUpCMAP(map, i); + fprintf(fp,"\t\t Char %3d -> Index %4d\n",i,index); + } } -static USHORT ttfLookUpCMAP0(SubTablePtr subTable,USHORT cc) +static USHORT ttfLookUpCMAP0(MapPtr map, USHORT cc) { - return subTable->map.cmap0->glyphIndexArray[cc & 0x00ff]; + return map.cmap0->glyphIndexArray[cc & 0x00ff]; } -static void ttfFreeCMAP0(SubTablePtr subTable) +static void ttfFreeCMAP0(MapPtr map) { - free(subTable->map.cmap0); + free(map.cmap0); } -static void ttfLoadCMAP2(FILE *fp,SubTablePtr subTable,ULONG offset) +static void ttfLoadCMAP2(FILE *fp, MapPtr *map) { USHORT * array,i,n = 0; USHORT numGlyphId; SubHeaderPtr header; - xfseek(fp, offset, SEEK_SET, "ttfLoadCMAP2"); - - subTable->map.cmap2 = XCALLOC1 (CMAP2); - array = subTable->map.cmap2->subHeaderKeys; + map->cmap2 = XCALLOC1 (CMAP2); + map->cmap2->length = ttfGetUSHORT(fp); + map->cmap2->version = ttfGetUSHORT(fp); + array = map->cmap2->subHeaderKeys; ttfReadUSHORT (array, 256, fp); for (i=0;i<256;i++) - { - array[i] /= 8; - if (n< array[i]) - n = array[i]; /* find the max of subHeaderKeys */ - } + { + array[i] /= 8; + if (n< array[i]) + n = array[i]; /* find the max of subHeaderKeys */ + } n += 1; /* the number of subHeaders is one plus the max of subHeaderKeys */ - subTable->map.cmap2->subHeaders = header = XCALLOC (n, SubHeader); + map->cmap2->subHeaders = header = XCALLOC (n, SubHeader); for (i=0;i<n;i++) - { - (header+i)->firstCode = ttfGetUSHORT(fp); - (header+i)->entryCount = ttfGetUSHORT(fp); - (header+i)->idDelta = ttfGetSHORT(fp); - (header+i)->idRangeOffset = ttfGetUSHORT(fp); - - /* it makes things easier to let the offset starts from - * the beginning of glyphIndexArray */ - if ((header+i)->idRangeOffset != 0) - (header+i)->idRangeOffset -= (sizeof(USHORT) + - (n-i-1) * sizeof(SubHeader)) ; - } + { + (header+i)->firstCode = ttfGetUSHORT(fp); + (header+i)->entryCount = ttfGetUSHORT(fp); + (header+i)->idDelta = ttfGetSHORT(fp); + (header+i)->idRangeOffset = ttfGetUSHORT(fp); + + /* it makes things easier to let the offset starts from + * the beginning of glyphIndexArray */ + if ((header+i)->idRangeOffset != 0) + (header+i)->idRangeOffset -= (sizeof(USHORT) + + (n-i-1) * sizeof(SubHeader)) ; + } /* caculate the length of glyphIndexArray, this is ugly, there should be * a better way to get this information. */ numGlyphId = - subTable->length - (256 + 3) * sizeof(USHORT) - n * sizeof(SubHeader); + map->cmap2->length - (256 + 3) * sizeof(USHORT) - n * sizeof(SubHeader); numGlyphId /= sizeof(USHORT); - subTable->map.cmap2->glyphIndexArray = XCALLOC (numGlyphId, USHORT); + map->cmap2->glyphIndexArray = XCALLOC (numGlyphId, USHORT); for (i=0;i<numGlyphId;i++) - { - subTable->map.cmap2->glyphIndexArray[i] = ttfGetUSHORT(fp); - } + { + map->cmap2->glyphIndexArray[i] = ttfGetUSHORT(fp); + } } -static void ttfPrintCMAP2(FILE *fp,SubTablePtr subTable) +static void ttfPrintCMAP2(FILE *fp, MapPtr map) { USHORT i,j,numGlyphId; USHORT *array,n=0,index; SubHeaderPtr header; TwoBytes tb; - array = subTable->map.cmap2->subHeaderKeys; - header = subTable->map.cmap2->subHeaders; + fprintf(fp, " Format 2 - High-byte mapping through table\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap2->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap2->version); + array = map.cmap2->subHeaderKeys; + header = map.cmap2->subHeaders; for (i=0;i<256;i++) - { - /* find the number of subHeader */ - if (n< array[i]) - n = array[i]; - fprintf(fp,"\t\t subHeaderKeys[%d] = %d\n",i,array[i]); - } + { + /* find the number of subHeader */ + if (n< array[i]) + n = array[i]; + fprintf(fp,"\t\t subHeaderKeys[%d] = %d\n",i,array[i]); + } n += 1; /* the number of subHeaders is one plus the max of subHeaderKeys */ fprintf(fp,"\t\t Number of SubHeaders is %d\n",n); for (i=0;i<=n;i++) - { - fprintf(fp,"\t\t SubHeader[%d]\n",i); - fprintf(fp,"\t\t firstCode \t 0x%04x\n",(header+i)->firstCode); - fprintf(fp,"\t\t entryCount \t %d\n",(header+i)->entryCount); - fprintf(fp,"\t\t idDelta \t %d\n",(header+i)->idDelta); - fprintf(fp,"\t\t idRangeOffset \t 0x%04x\n\n", - (header+i)->idRangeOffset); - } + { + fprintf(fp,"\t\t SubHeader[%d]\n",i); + fprintf(fp,"\t\t firstCode \t 0x%04x\n",(header+i)->firstCode); + fprintf(fp,"\t\t entryCount \t %d\n",(header+i)->entryCount); + fprintf(fp,"\t\t idDelta \t %d\n",(header+i)->idDelta); + fprintf(fp,"\t\t idRangeOffset \t 0x%04x\n\n", + (header+i)->idRangeOffset); + } /* caculate the length of glyphIndexArray, this is ugly, there should be * a better way to get this information. */ numGlyphId = - subTable->length - (256 + 3) * sizeof(USHORT) - n * sizeof(SubHeader); + map.cmap2->length - (256 + 3) * sizeof(USHORT) - n * sizeof(SubHeader); numGlyphId /= sizeof(USHORT); fprintf(fp,"Number of glyphIndex: %d\n", numGlyphId); for (i=0;i<numGlyphId;i++) - { - fprintf(fp,"\t\t glyphIdArray[%d] = %4d\n",i, - subTable->map.cmap2->glyphIndexArray[i]); - } + { + fprintf(fp,"\t\t glyphIdArray[%d] = %4d\n",i, + map.cmap2->glyphIndexArray[i]); + } i = 0; fprintf(fp,"\t\t First Byte:\t %2x\n",i); tb.c[1] = i; for(j=0;j<=255;j++) - { - tb.c[0] = j; - index = ttfLookUpCMAP2(subTable,tb.u); - fprintf(fp,"\t\t Char %2x -> Index %d\n",j,index); - } + { + tb.c[0] = j; + index = ttfLookUpCMAP2(map, tb.u); + fprintf(fp,"\t\t Char %2x -> Index %d\n",j,index); + } for (i=128;i<=255;i++) - { - fprintf(fp,"\t\t First Byte:\t %2x\n",i); - tb.c[1] = i; - for(j=0;j<=255;j++) - { - tb.c[0] = j; - index = ttfLookUpCMAP2(subTable,tb.u); - fprintf(fp,"\t\t Char %2x -> Index %d\n",j,index); - } - } -} -static USHORT ttfLookUpCMAP2(SubTablePtr subTable,USHORT cc) + { + fprintf(fp,"\t\t First Byte:\t %2x\n",i); + tb.c[1] = i; + for(j=0;j<=255;j++) + { + tb.c[0] = j; + index = ttfLookUpCMAP2(map, tb.u); + fprintf(fp,"\t\t Char %2x -> Index %d\n",j,index); + } + } +} +static USHORT ttfLookUpCMAP2(MapPtr map, USHORT cc) { USHORT index,idx = 0; - USHORT *array = subTable->map.cmap2->subHeaderKeys; - SubHeaderPtr headers = subTable->map.cmap2->subHeaders; + USHORT *array = map.cmap2->subHeaderKeys; + SubHeaderPtr headers = map.cmap2->subHeaders; SHORT idDelta; USHORT firstCode, entryCount, idRangeOffset; TwoBytes tb; @@ -459,195 +536,431 @@ static USHORT ttfLookUpCMAP2(SubTablePtr subTable,USHORT cc) idRangeOffset = (headers+idx)->idRangeOffset / sizeof (USHORT); if (second >= firstCode && second < firstCode+entryCount) - { - /* use idRangeOffset to find where in the glyphIndexArray - * the correspinding index is */ - idRangeOffset += (second - firstCode); - index = subTable->map.cmap2->glyphIndexArray[idRangeOffset]; - if (index != 0) - /* if the character is not a missing character then - * add idDelta to it */ - index += idDelta; - } + { + /* use idRangeOffset to find where in the glyphIndexArray + * the correspinding index is */ + idRangeOffset += (second - firstCode); + index = map.cmap2->glyphIndexArray[idRangeOffset]; + if (index != 0) + /* if the character is not a missing character then + * add idDelta to it */ + index += idDelta; + } else - /* The second code is out ranged then return the - * missing glyph character */ - index = 0; - + /* The second code is out ranged then return the + * missing glyph character */ + index = 0; + return index; } -static void ttfFreeCMAP2(SubTablePtr subTable) +static void ttfFreeCMAP2(MapPtr map) { - free(subTable->map.cmap2->subHeaders); - free(subTable->map.cmap2->glyphIndexArray); - free(subTable->map.cmap2); + free(map.cmap2->subHeaders); + free(map.cmap2->glyphIndexArray); + free(map.cmap2); } -static void ttfLoadCMAP4(FILE *fp,SubTablePtr subTable,ULONG offset) +static void ttfLoadCMAP4(FILE *fp, MapPtr *map) { USHORT segCount; USHORT len; - xfseek(fp, offset, SEEK_SET, "ttfLoadCMAP4"); - - subTable->map.cmap4 = XCALLOC1 (CMAP4); + map->cmap4 = XCALLOC1 (CMAP4); + map->cmap4->length = ttfGetUSHORT(fp); + map->cmap4->version = ttfGetUSHORT(fp); - subTable->map.cmap4->segCountX2 = segCount = ttfGetUSHORT(fp); - subTable->map.cmap4->searchRange = ttfGetUSHORT(fp); - subTable->map.cmap4->entrySelector = ttfGetUSHORT(fp); - subTable->map.cmap4->rangeShift = ttfGetUSHORT(fp); + map->cmap4->segCountX2 = segCount = ttfGetUSHORT(fp); + map->cmap4->searchRange = ttfGetUSHORT(fp); + map->cmap4->entrySelector = ttfGetUSHORT(fp); + map->cmap4->rangeShift = ttfGetUSHORT(fp); segCount /= 2; - subTable->map.cmap4->endCount = ttfMakeUSHORT (segCount, fp); + map->cmap4->endCount = ttfMakeUSHORT (segCount, fp); - subTable->map.cmap4->reservedPad = ttfGetUSHORT(fp); + map->cmap4->reservedPad = ttfGetUSHORT(fp); - subTable->map.cmap4->startCount = ttfMakeUSHORT (segCount, fp); + map->cmap4->startCount = ttfMakeUSHORT (segCount, fp); - subTable->map.cmap4->idDelta = ttfMakeUSHORT (segCount, fp); + map->cmap4->idDelta = ttfMakeUSHORT (segCount, fp); - subTable->map.cmap4->idRangeOffset = ttfMakeUSHORT (segCount, fp); + map->cmap4->idRangeOffset = ttfMakeUSHORT (segCount, fp); /* caculate the length of glyphIndexArray, this is ugly, there should be * a better way to get this information. */ - len = subTable->length - 8*sizeof(USHORT) - 4*segCount*sizeof(USHORT); + len = map->cmap4->length - 8*sizeof(USHORT) - 4*segCount*sizeof(USHORT); len /= sizeof(USHORT); - subTable->map.cmap4->glyphIndexArray = ttfMakeUSHORT (len, fp); + map->cmap4->glyphIndexArray = ttfMakeUSHORT (len, fp); } -static void ttfPrintCMAP4(FILE *fp,SubTablePtr subTable) +static void ttfPrintCMAP4(FILE *fp, MapPtr map) { USHORT i; USHORT segCount,len; - segCount = subTable->map.cmap4->segCountX2/2; + fprintf(fp, " Format 4 - Segment mapping to delta values\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap4->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap4->version); + segCount = map.cmap4->segCountX2/2; fprintf(fp, "\t\t segCount:\t %d\n", segCount); - fprintf(fp, "\t\t searchRange:\t %d\n", subTable->map.cmap4->searchRange); - fprintf(fp, "\t\t entrySelector:\t %d\n", subTable->map.cmap4->entrySelector); - fprintf(fp, "\t\t rangeShift:\t %d\n", subTable->map.cmap4->rangeShift); + fprintf(fp, "\t\t searchRange:\t %d\n", map.cmap4->searchRange); + fprintf(fp, "\t\t entrySelector:\t %d\n", map.cmap4->entrySelector); + fprintf(fp, "\t\t rangeShift:\t %d\n", map.cmap4->rangeShift); for (i=0;i<segCount;i++) - { - fprintf(fp, "\t\t Seg %3d :", i); - fprintf(fp, " St = %04x,", subTable->map.cmap4->startCount[i]); - fprintf(fp, " En = %04x,", subTable->map.cmap4->endCount[i]); - /* should this filed be SHORT or USHORT ?? */ - fprintf(fp, " D = %6d," , - (subTable->map.cmap4->idDelta[i])); - fprintf(fp, " RO = %6d," , subTable->map.cmap4->idRangeOffset[i]); - - /* find the glyphIndex correpsonding to this segment */ - if (subTable->map.cmap4->idRangeOffset[i] != 0) - { - USHORT j; - j = subTable->map.cmap4->segCountX2/2 - i; - j = subTable->map.cmap4->idRangeOffset[i] - - j*sizeof(USHORT); - fprintf(fp, " gId# = %d\n", (int) (j/sizeof(USHORT))); - } - else - fprintf(fp, " gId# = N/A\n"); - } + { + fprintf(fp, "\t\t Seg %3d :", i); + fprintf(fp, " St = %04x,", map.cmap4->startCount[i]); + fprintf(fp, " En = %04x,", map.cmap4->endCount[i]); + /* should this filed be SHORT or USHORT ?? */ + fprintf(fp, " D = %6d," , + (map.cmap4->idDelta[i])); + fprintf(fp, " RO = %6d," , map.cmap4->idRangeOffset[i]); + + /* find the glyphIndex correpsonding to this segment */ + if (map.cmap4->idRangeOffset[i] != 0) + { + USHORT j; + j = map.cmap4->segCountX2/2 - i; + j = map.cmap4->idRangeOffset[i] - + j*sizeof(USHORT); + fprintf(fp, " gId# = %d\n", (int) (j/sizeof(USHORT))); + } + else + fprintf(fp, " gId# = N/A\n"); + } /* caculate the length of glyphIndexArray, this is ugly, there should be * a better way to get this information. */ - len = subTable->length - 8*sizeof(USHORT) - 4*segCount*sizeof(USHORT); + len = map.cmap4->length - 8*sizeof(USHORT) - 4*segCount*sizeof(USHORT); len /= sizeof(USHORT); fprintf(fp,"\t\t Number of glyphIndex %d\n",len); for (i=0;i<len;i++) - { - fprintf(fp,"\t\t glyphIdArray[%d] = %d\n",i, - subTable->map.cmap4->glyphIndexArray[i]); - } + { + fprintf(fp,"\t\t glyphIdArray[%d] = %d\n",i, + map.cmap4->glyphIndexArray[i]); + } for (i=0;i<segCount;i++) - { - int j,index; - fprintf(fp,"Segment %d:\n",i); - for (j=subTable->map.cmap4->startCount[i]; - j<=subTable->map.cmap4->endCount[i];j++) - { - index = ttfLookUpCMAP4(subTable,j); - fprintf(fp,"\t\tChar 0x%04x -> Index %d\n",j,index); - } - } -} -static USHORT ttfLookUpCMAP4(SubTablePtr subTable,USHORT cc) + { + int j,index; + fprintf(fp,"Segment %d:\n",i); + for (j=map.cmap4->startCount[i]; + j<=map.cmap4->endCount[i];j++) + { + index = ttfLookUpCMAP4(map, j); + fprintf(fp,"\t\tChar 0x%04x -> Index %d\n",j,index); + } + } +} +static USHORT ttfLookUpCMAP4(MapPtr map, USHORT cc) { USHORT i; - USHORT index=0, segCount = subTable->map.cmap4->segCountX2/2; + USHORT index=0, segCount = map.cmap4->segCountX2/2; for (i=0;i<segCount;i++) - { - if (cc <= subTable->map.cmap4->endCount[i] && - cc >= subTable->map.cmap4->startCount[i]) - { - USHORT j; - if (subTable->map.cmap4->idRangeOffset[i] != 0) - { - j = subTable->map.cmap4->idRangeOffset[i] - - (segCount - i)*sizeof(USHORT); - j = cc - subTable->map.cmap4->startCount[i] + j/2; - index = subTable->map.cmap4->glyphIndexArray[j]; - if (index != 0) - index += subTable->map.cmap4->idDelta[i]; - } - else - { - index = cc + subTable->map.cmap4->idDelta[i]; - } - break; - } - } + { + if (cc <= map.cmap4->endCount[i] && + cc >= map.cmap4->startCount[i]) + { + USHORT j; + if (map.cmap4->idRangeOffset[i] != 0) + { + j = map.cmap4->idRangeOffset[i] - + (segCount - i)*sizeof(USHORT); + j = cc - map.cmap4->startCount[i] + j/2; + index = map.cmap4->glyphIndexArray[j]; + if (index != 0) + index += map.cmap4->idDelta[i]; + } + else + { + index = cc + map.cmap4->idDelta[i]; + } + break; + } + } return index; } -static void ttfFreeCMAP4(SubTablePtr subTable) +static void ttfFreeCMAP4(MapPtr map) { - free(subTable->map.cmap4->endCount); - free(subTable->map.cmap4->startCount); - free(subTable->map.cmap4->idDelta); - free(subTable->map.cmap4->idRangeOffset); - free(subTable->map.cmap4->glyphIndexArray); - free(subTable->map.cmap4); + free(map.cmap4->endCount); + free(map.cmap4->startCount); + free(map.cmap4->idDelta); + free(map.cmap4->idRangeOffset); + free(map.cmap4->glyphIndexArray); + free(map.cmap4); } -static void ttfLoadCMAP6(FILE *fp,SubTablePtr subTable,ULONG offset) +static void ttfLoadCMAP6(FILE *fp, MapPtr *map) { USHORT len; - xfseek(fp, offset, SEEK_SET, "ttfLoadCMAP6"); - - subTable->map.cmap6 = XCALLOC1 (CMAP6); - subTable->map.cmap6->firstCode = ttfGetUSHORT(fp); - subTable->map.cmap6->entryCount = len = ttfGetUSHORT(fp); - subTable->map.cmap6->glyphIndexArray = ttfMakeUSHORT (len, fp); + map->cmap6 = XCALLOC1 (CMAP6); + map->cmap6->length = ttfGetUSHORT(fp); + map->cmap6->version = ttfGetUSHORT(fp); + map->cmap6->firstCode = ttfGetUSHORT(fp); + map->cmap6->entryCount = len = ttfGetUSHORT(fp); + map->cmap6->glyphIndexArray = ttfMakeUSHORT (len, fp); } -static void ttfPrintCMAP6(FILE *fp, SubTablePtr subTable) +static void ttfPrintCMAP6(FILE *fp, MapPtr map) { USHORT i; - fprintf(fp,"\t\t First Code: 0x%04x\n",subTable->map.cmap6->firstCode); - fprintf(fp,"\t\t Entry Count: %d\n",subTable->map.cmap6->entryCount); + + fprintf(fp, " Format 6 - Trimmed table mapping\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap6->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap6->version); + fprintf(fp,"\t\t First Code: 0x%04x\n", map.cmap6->firstCode); + fprintf(fp,"\t\t Entry Count: %d\n", map.cmap6->entryCount); - for (i=0;i<subTable->map.cmap6->entryCount;i++) - { - fprintf(fp,"\t\t glyphIdArray[%d] = %d\n",i, - subTable->map.cmap6->glyphIndexArray[i]); - } + for (i=0;i<map.cmap6->entryCount;i++) + { + fprintf(fp,"\t\t glyphIdArray[%d] = %d\n",i, + map.cmap6->glyphIndexArray[i]); + } } -static USHORT ttfLookUpCMAP6(SubTablePtr subTable,USHORT cc) +static USHORT ttfLookUpCMAP6(MapPtr map, USHORT cc) { USHORT index; - index = cc - subTable->map.cmap6->firstCode; - if (index < subTable->map.cmap6->entryCount) - return subTable->map.cmap6->glyphIndexArray[index]; + index = cc - map.cmap6->firstCode; + if (index < map.cmap6->entryCount) + return map.cmap6->glyphIndexArray[index]; + else + /* index out of range, return missing glyph */ + return 0; +} +static void ttfFreeCMAP6(MapPtr map) +{ + free(map.cmap6->glyphIndexArray); + free(map.cmap6); +} + +static void ttfLoadCMAP8(FILE *fp, MapPtr *map) +{ + int i; + + map->cmap8 = XCALLOC1 (CMAP8); + ttfGetUSHORT(fp); + map->cmap8->length = ttfGetULONG(fp); + map->cmap8->version = ttfGetULONG(fp); + if (fread(map->cmap8->is32, sizeof(BYTE), 8192, fp) != 8192) + ttfError("Error when getting is32\n"); + map->cmap8->nGroups = ttfGetULONG(fp); + map->cmap8->charGroup = XCALLOC (map->cmap8->nGroups, CharGroup); + for (i = 0; i < map->cmap8->nGroups; i++) { + map->cmap8->charGroup[i].startCharCode = ttfGetULONG(fp); + map->cmap8->charGroup[i].endCharCode = ttfGetULONG(fp); + map->cmap8->charGroup[i].startGlyphID = ttfGetULONG(fp); + } +} +static void ttfPrintCMAP8(FILE *fp, MapPtr map) +{ + int i; + + fprintf(fp, " Format 8 - Mixed 16-bit and 32-bit coverage\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap8->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap8->version); + fprintf(fp,"\t\t nGroups: %6d\n", map.cmap8->nGroups); + for (i = 0; i < 256; i++) { + int j; + + fprintf(fp, "\t is32 %2x", i); + for (j = 0; j < 32; j++) + fprintf(fp, j % 4 ? "%2x" : " %2x", map.cmap8->is32[i << 5 | j]); + fprintf(fp, "\n"); + } + for (i = 0; i < map.cmap8->nGroups; i++) + fprintf(fp, "\t\t Group %4d : startCharCode = %d, endCharCode = %d, startGlyphID = %d\n", i, + map.cmap8->charGroup[i].startCharCode, + map.cmap8->charGroup[i].endCharCode, + map.cmap8->charGroup[i].startGlyphID); +} +static USHORT ttfLookUpCMAP8(MapPtr map, ULONG cc) +{ + int i; + + for (i = 0; i < map.cmap8->nGroups; i++) + if (cc > map.cmap8->charGroup[i].endCharCode) + continue; + else if (cc < map.cmap8->charGroup[i].startCharCode) + break; + else + return map.cmap8->charGroup[i].startGlyphID + + (cc - map.cmap8->charGroup[i].startCharCode); + + /* index out of range, return missing glyph */ + return 0; +} +static void ttfFreeCMAP8(MapPtr map) +{ + free(map.cmap8->charGroup); + free(map.cmap8); +} + +static void ttfLoadCMAP10(FILE *fp, MapPtr *map) +{ + ULONG len; + + map->cmap10 = XCALLOC1 (CMAP10); + ttfGetUSHORT(fp); + map->cmap10->length = ttfGetULONG(fp); + map->cmap10->version = ttfGetULONG(fp); + map->cmap10->startCharCode = ttfGetULONG(fp); + map->cmap10->numChars = len = ttfGetULONG(fp); + map->cmap10->glyphs = ttfMakeUSHORT (len, fp); +} +static void ttfPrintCMAP10(FILE *fp, MapPtr map) +{ + int i; + + fprintf(fp, " Format 10 - Trimmed array\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap10->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap10->version); + fprintf(fp,"\t\t Start Char Code: 0x%04x\n", map.cmap10->startCharCode); + fprintf(fp,"\t\t Num Chars: %d\n", map.cmap10->numChars); + + for (i = 0; i < map.cmap10->numChars; i++) + { + fprintf(fp, "\t\t glyphs[%d] = %d\n", i, map.cmap10->glyphs[i]); + } +} +static USHORT ttfLookUpCMAP10(MapPtr map, ULONG cc) +{ + ULONG index; + + index = cc - map.cmap10->startCharCode; + if (index < map.cmap10->numChars) + return map.cmap10->glyphs[index]; else - /* index out of range, return missing glyph */ - return 0; + /* index out of range, return missing glyph */ + return 0; +} +static void ttfFreeCMAP10(MapPtr map) +{ + free(map.cmap10->glyphs); + free(map.cmap10); +} + +static void ttfLoadCMAP12(FILE *fp, MapPtr *map) +{ + int i; + + map->cmap12 = XCALLOC1 (CMAP12); + ttfGetUSHORT(fp); + map->cmap12->length = ttfGetULONG(fp); + map->cmap12->version = ttfGetULONG(fp); + map->cmap12->nGroups = ttfGetULONG(fp); + map->cmap12->charGroup = XCALLOC (map->cmap12->nGroups, CharGroup); + for (i = 0; i < map->cmap12->nGroups; i++) { + map->cmap12->charGroup[i].startCharCode = ttfGetULONG(fp); + map->cmap12->charGroup[i].endCharCode = ttfGetULONG(fp); + map->cmap12->charGroup[i].startGlyphID = ttfGetULONG(fp); + } +} +static void ttfPrintCMAP12(FILE *fp, MapPtr map) +{ + int i; + + fprintf(fp, " Format 12 - Segmented coverage\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap12->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap12->version); + fprintf(fp,"\t\t nGroups: %6d\n", map.cmap12->nGroups); + for (i = 0; i < map.cmap12->nGroups; i++) + fprintf(fp, "\t\t Group %4d : startCharCode = %d, endCharCode = %d, startGlyphID = %d\n", i, + map.cmap12->charGroup[i].startCharCode, + map.cmap12->charGroup[i].endCharCode, + map.cmap12->charGroup[i].startGlyphID); +} +static USHORT ttfLookUpCMAP12(MapPtr map, ULONG cc) +{ + int i; + + for (i = 0; i < map.cmap12->nGroups; i++) + if (cc > map.cmap12->charGroup[i].endCharCode) + continue; + else if (cc < map.cmap12->charGroup[i].startCharCode) + break; + else + return map.cmap12->charGroup[i].startGlyphID + + (cc - map.cmap12->charGroup[i].startCharCode); + + /* index out of range, return missing glyph */ + return 0; +} +static void ttfFreeCMAP12(MapPtr map) +{ + free(map.cmap12->charGroup); + free(map.cmap12); +} + +static void ttfLoadCMAP13(FILE *fp, MapPtr *map) +{ + int i; + + map->cmap13 = XCALLOC1 (CMAP13); + ttfGetUSHORT(fp); + map->cmap13->length = ttfGetULONG(fp); + map->cmap13->version = ttfGetULONG(fp); + map->cmap13->nGroups = ttfGetULONG(fp); + map->cmap13->charGroup = XCALLOC (map->cmap13->nGroups, CharGroup); + for (i = 0; i < map->cmap13->nGroups; i++) { + map->cmap13->charGroup[i].startCharCode = ttfGetULONG(fp); + map->cmap13->charGroup[i].endCharCode = ttfGetULONG(fp); + map->cmap13->charGroup[i].startGlyphID = ttfGetULONG(fp); + } +} +static void ttfPrintCMAP13(FILE *fp, MapPtr map) +{ + int i; + + fprintf(fp, " Format 13 - Many-to-one range mappings\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap13->length); + fprintf(fp,"\t\t Version: %6d\n", map.cmap13->version); + fprintf(fp,"\t\t nGroups: %6d\n", map.cmap13->nGroups); + for (i = 0; i < map.cmap13->nGroups; i++) + fprintf(fp, "\t\t Group %4d : startCharCode = %d, endCharCode = %d, glyphID = %d\n", i, + map.cmap13->charGroup[i].startCharCode, + map.cmap13->charGroup[i].endCharCode, + map.cmap13->charGroup[i].startGlyphID); +} +static USHORT ttfLookUpCMAP13(MapPtr map, ULONG cc) +{ + int i; + + for (i = 0; i < map.cmap13->nGroups; i++) + if (cc > map.cmap13->charGroup[i].endCharCode) + continue; + else if (cc < map.cmap13->charGroup[i].startCharCode) + break; + else + return map.cmap12->charGroup[i].startGlyphID; + + /* index out of range, return missing glyph */ + return 0; +} +static void ttfFreeCMAP13(MapPtr map) +{ + free(map.cmap13->charGroup); + free(map.cmap13); +} + +static void ttfLoadCMAP14(FILE *fp, MapPtr *map) +{ + map->cmap14 = XCALLOC1 (CMAP14); + map->cmap14->length = ttfGetULONG(fp); +} +static void ttfPrintCMAP14(FILE *fp, MapPtr map) +{ + fprintf(fp, " Format 14 - Unicode variation sequences\n"); + fprintf(fp,"\t\t Length: %6d\n", map.cmap14->length); + fprintf(fp,"\t\t *** NOT YET IMPLEMENTED ***\n"); +} +static USHORT ttfLookUpCMAP14(MapPtr map, ULONG cc) +{ + return 0; } -static void ttfFreeCMAP6(SubTablePtr subTable) +static void ttfFreeCMAP14(MapPtr map) { - free(subTable->map.cmap6->glyphIndexArray); - free(subTable->map.cmap6); + free(map.cmap14); } diff --git a/Build/source/texk/ttfdump/libttf/font.c b/Build/source/texk/ttfdump/libttf/font.c index 0ee6c25ec02..8b5e0d0a247 100644 --- a/Build/source/texk/ttfdump/libttf/font.c +++ b/Build/source/texk/ttfdump/libttf/font.c @@ -42,6 +42,7 @@ void ttfLoadFont(TTFontPtr font, ULONG offset) ttfLoadRequiredTables(font); ttfLoadOptionalTables(font); + ttfLoadOpenTypeTables(font); ttfInitInterpreter(font); @@ -55,6 +56,8 @@ void ttfFreeFont(TTFontPtr font) ttfFreeOptionalTables(font); + ttfFreeOpenTypeTables(font); + ttfFreeTableDir(font->dir); free(font->refcount); free(font); @@ -67,7 +70,6 @@ void ttfLoadRequiredTables(TTFontPtr font) ttfInitMAXP(font); ttfInitHEAD(font); - ttfInitLOCA(font); ttfInitGlyphCache(font); ttfInitGLYF(font); @@ -85,7 +87,6 @@ void ttfFreeRequiredTables(TTFontPtr font) ttfFreeNAME(font->name); ttfCleanUpGlyphCache(font); - ttfFreeLOCA(font->loca); ttfFreeHEAD(font->head); ttfFreeMAXP(font->maxp); @@ -103,6 +104,7 @@ void ttfLoadOptionalTables(TTFontPtr font) ttfInitGASP(font); ttfInitHDMX(font); ttfInitKERN(font); + ttfInitLOCA(font); ttfInitPREP(font); ttfInitLTSH(font); ttfInitPCLT(font); @@ -117,6 +119,7 @@ void ttfFreeOptionalTables(TTFontPtr font) ttfFreeGASP(font->gasp); ttfFreeHDMX(font->hdmx); ttfFreeKERN(font->kern); + ttfFreeLOCA(font->loca); ttfFreePREP(font->prep); ttfFreeLTSH(font->ltsh); ttfFreePCLT(font->pclt); @@ -125,6 +128,17 @@ void ttfFreeOptionalTables(TTFontPtr font) ttfFreeVMTX(font->vmtx); } +void ttfLoadOpenTypeTables(TTFontPtr font) +{ + ttfInitGPOS(font); + ttfInitGSUB(font); +} +void ttfFreeOpenTypeTables(TTFontPtr font) +{ + ttfFreeGPOS(font->gpos); + ttfFreeGSUB(font->gsub); +} + #if 0 /* Not used */ /* make a clone of the origional font diff --git a/Build/source/texk/ttfdump/libttf/glyf.c b/Build/source/texk/ttfdump/libttf/glyf.c index 9804d1bb126..ca922d0e07f 100644 --- a/Build/source/texk/ttfdump/libttf/glyf.c +++ b/Build/source/texk/ttfdump/libttf/glyf.c @@ -54,8 +54,8 @@ void ttfLoadGLYF(FILE *fp, GLYFPtr glyf, ULONG offset) } void ttfPrintGLYF(FILE *fp, GLYFPtr glyf) { - fprintf(fp,"\t numberOfContours:\t %d %s\n", glyf->numberOfContours, - glyf->numberOfContours == -1 ? "(Composite)": ""); + fprintf(fp,"\t numberOfContours:\t %d%s\n", glyf->numberOfContours, + glyf->numberOfContours == -1 ? " (Composite)": ""); fprintf(fp,"\t xMin:\t\t\t %d\n", glyf->xMin); fprintf(fp,"\t yMin:\t\t\t %d\n", glyf->yMin); fprintf(fp,"\t xMax:\t\t\t %d\n", glyf->xMax); @@ -404,7 +404,7 @@ GLYFPtr ttfLoadGlyphCode(TTFont *font,USHORT cc) { USHORT index; - index = ttfLookUpCMAP(font->encoding,cc); + index = ttfLookUpCMAP(font->encoding->map,cc); return ttfLoadGlyphIndex(font,index); } diff --git a/Build/source/texk/ttfdump/libttf/gpos.c b/Build/source/texk/ttfdump/libttf/gpos.c new file mode 100644 index 00000000000..9d040298099 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/gpos.c @@ -0,0 +1,971 @@ +/* gpos.c -- Glyph Positioning Table + */ +#include <stdio.h> +#include <stdlib.h> +#include "config.h" +#include "ttf.h" +#include "ttfutil.h" + +static USHORT getValueFormat (FILE *fp) +{ + USHORT valueFormat = ttfGetUSHORT (fp); + + if (valueFormat & ValueFormat_Reserved) + ttfError ("Unrecognized GPOS valueFormat\n"); + + return valueFormat; +} + +static ValueRecordPtr +gposMakeValueRecord (USHORT valueFormat, FILE *fp, ULONG offset) +{ + int i; + ValueRecordPtr value; + + if (valueFormat == 0) + return NULL; + + value = XCALLOC1 (ValueRecord); + for (i = 0; i < 4; i++) + if (valueFormat & (ValueFormat_XPlacement << i)) + value->valDesign[i] = ttfGetSHORT (fp); + for (i = 0; i < 4; i++) + if (valueFormat & (ValueFormat_XPlaDevice << i)) + ttfGetUSHORT (fp); + + return value; +} + +static const char *txtDesign[4] = { + "XPlacement", + "YPlacement", + "XAdvance", + "YAdvance" +}; + +static void +gposPrintValueRecord (FILE *fp, const char *str, USHORT valueFormat, ValueRecordPtr value) +{ + const char *s = ":"; + int i; + + for (i = 0; i < 4; i++) + if (valueFormat & (ValueFormat_XPlacement << i)) { + fprintf (fp, "%s %s = %d\n", s, txtDesign[i], value->valDesign[i]); + s = str; + } + if (valueFormat & ValueFormat_AllDevice) + fprintf (fp, "\t\t *** Device Table NOT YET IMPLEMENTED ***\n"); +} + +static void freeValueRecord (ValueRecordPtr value) +{ + if (value) { + int i; + + for (i = 0; i < 4; i++) + if (value->valDevice[i]) + free (value->valDevice[i]); + free (value); + } +} + +static AnchorPtr gposMakeAnchor (FILE *fp, ULONG offset) +{ + AnchorPtr anchor; + USHORT anchorFormat; + USHORT xOffset, yOffset; + + xfseek (fp, offset, SEEK_SET, "gposMakeAnchor"); + + anchorFormat = ttfGetUSHORT (fp); + switch (anchorFormat) + { + case 1: + anchor.anchor1 = XCALLOC1 (Anchor1); + break; + case 2: + anchor.anchor2 = XCALLOC1 (Anchor2); + break; + case 3: + anchor.anchor3 = XCALLOC1 (Anchor3); + break; + default: + ttfError ("Unrecognized GPOS anchorFormat\n"); + } + anchor.anchor1->anchorFormat = anchorFormat; + anchor.anchor1->xCoordinate = ttfGetSHORT (fp); + anchor.anchor1->yCoordinate = ttfGetSHORT (fp); + + switch (anchorFormat) + { + case 2: + anchor.anchor2->anchorPoint = ttfGetUSHORT (fp); + break; + case 3: + xOffset = ttfGetUSHORT (fp); + yOffset = ttfGetUSHORT (fp); + if (xOffset) + anchor.anchor3->xDevice = otfMakeDevice (fp, offset + xOffset); + if (yOffset) + anchor.anchor3->yDevice = otfMakeDevice (fp, offset + yOffset); + break; + } + + return anchor; +} + +static void +gposPrintAnchor (FILE *fp, const char *str, AnchorPtr anchor) +{ + fprintf (fp, "anchorFormat = %d, xCoordinate = %d, yCoordinate = %d\n", + anchor.anchor1->anchorFormat, anchor.anchor1->xCoordinate, anchor.anchor1->yCoordinate); + + switch (anchor.anchor1->anchorFormat) + { + case 2: + fprintf (fp, "%sanchorPoint = %d\n", str, anchor.anchor2->anchorPoint); + break; + case 3: + if (anchor.anchor3->xDevice) { + fprintf (fp, "%sxDevice: ", str); + otfPrintDevice (fp, anchor.anchor3->xDevice); + } + if (anchor.anchor3->yDevice) { + fprintf (fp, "%syDevice: ", str); + otfPrintDevice (fp, anchor.anchor3->yDevice); + } + break; + } +} + +static void freeAnchor (AnchorPtr anchor) +{ + if (anchor.anchor3) { + if (anchor.anchor3->anchorFormat == 3) { + if (anchor.anchor3->xDevice) + free (anchor.anchor3->xDevice); + if (anchor.anchor3->yDevice) + free (anchor.anchor3->yDevice); + } + free (anchor.anchor3); + } +} + +static MarkRecordPtr +gposMakeMarkArray (FILE *fp, USHORT *markCount, ULONG offset) +{ + int i; + MarkRecordPtr markArray; + USHORT *aOffset; + + xfseek (fp, offset, SEEK_SET, "gposMakeMarkArray"); + + *markCount = ttfGetUSHORT (fp); + markArray = XCALLOC (*markCount, MarkRecord); + aOffset = XCALLOC (*markCount, USHORT); + for (i = 0; i < *markCount; i++) { + markArray[i].class = ttfGetUSHORT (fp); + aOffset[i] = ttfGetUSHORT (fp); + } + for (i = 0; i < *markCount; i++) + markArray[i].markAnchor = gposMakeAnchor (fp, offset + aOffset[i]); + free (aOffset); + + return markArray; +} + +static void +gposPrintMarkArray (FILE *fp, USHORT markCount, MarkRecordPtr markArray) +{ + int i; + + for (i = 0; i < markCount; i++) { + fprintf (fp, "\t %2d. class: %d - ", i, markArray[i].class); + gposPrintAnchor (fp, "\t\t ", markArray[i].markAnchor); + } +} + +/* Used for both pos41->baseArray and pos61->mark2Array. */ +static AnchorPtr * +gposMakeBaseArray (FILE *fp, USHORT *baseCount, USHORT classCount, ULONG offset) +{ + int i; + AnchorPtr *baseArray; + USHORT *aOffset; + + xfseek (fp, offset, SEEK_SET, "gposMakeBaseArray"); + + *baseCount = ttfGetUSHORT (fp); + aOffset = ttfMakeUSHORT (*baseCount * classCount, fp); + baseArray = XCALLOC (*baseCount * classCount, AnchorPtr); + for (i = 0; i < *baseCount * classCount; i++) + if (aOffset[i]) + baseArray[i] = gposMakeAnchor (fp, offset + aOffset[i]); + free (aOffset); + + return baseArray; +} + +static Pos11Ptr makeGPOS11 (FILE *fp, ULONG offset) +{ + USHORT cOffset; + Pos11Ptr pos = XCALLOC1 (Pos11); + + cOffset = ttfGetUSHORT (fp); + pos->valueFormat = getValueFormat (fp); + pos->value = gposMakeValueRecord (pos->valueFormat, fp, offset); + pos->coverage = otfMakeCoverage (fp, offset + cOffset); + + return pos; +} + +static void printGPOS11 (FILE *fp, Pos11Ptr pos) +{ + fprintf (fp, " - Single Adjustment Value\n\t "); + otfPrintCoverage (fp, pos->coverage); + fprintf (fp, "\t valueFormat: 0x%04x\n", pos->valueFormat); + if (pos->valueFormat) { + fprintf (fp, "\t value"); + gposPrintValueRecord (fp, "\t\t", pos->valueFormat, pos->value); + } +} + +static void freeGPOS11 (Pos11Ptr pos) +{ + freeValueRecord (pos->value); + otfFreeCoverage (pos->coverage); +} + +static Pos12Ptr makeGPOS12 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + Pos12Ptr pos = XCALLOC1 (Pos12); + + cOffset = ttfGetUSHORT (fp); + pos->valueFormat = getValueFormat (fp); + pos->valueCount = ttfGetUSHORT (fp); + pos->value = XCALLOC (pos->valueCount, ValueRecordPtr); + for (i = 0; i < pos->valueCount; i++) + pos->value[i] = gposMakeValueRecord (pos->valueFormat, fp, offset); + pos->coverage = otfMakeCoverage (fp, offset + cOffset); + + return pos; +} + +static void printGPOS12 (FILE *fp, Pos12Ptr pos) +{ + int i; + + fprintf (fp, " - Single Adjustment List\n\t "); + otfPrintCoverage (fp, pos->coverage); + fprintf (fp, "\t valueFormat: 0x%04x, valueCount: %d\n", pos->valueFormat, pos->valueCount); + for (i = 0; i < pos->valueCount; i++) { + fprintf (fp, "\t %2d. value", i); + gposPrintValueRecord (fp, "\t\t ", pos->valueFormat, pos->value[i]); + } +} + +static void freeGPOS12 (Pos12Ptr pos) +{ + int i; + + for (i = 0; i < pos->valueCount; i++) + freeValueRecord (pos->value[i]); + free (pos->value); + otfFreeCoverage (pos->coverage); +} + +static void gposLoadPairSet (Pos21Ptr pos, int i, FILE *fp, ULONG offset, USHORT poff) +{ + int j; + PairSetPtr pairSet = &pos->pairSet[i]; + + xfseek (fp, offset + poff, SEEK_SET, "gposLoadPairSet"); + + pairSet->pairValueCount = ttfGetUSHORT (fp); + pairSet->pairValue = XCALLOC (pairSet->pairValueCount, PairValueRecord); + for (j = 0; j < pairSet->pairValueCount; j++) { + pairSet->pairValue[j].secondGlyph = ttfGetUSHORT (fp); + pairSet->pairValue[j].value1 = gposMakeValueRecord (pos->valueFormat1, fp, offset); + pairSet->pairValue[j].value2 = gposMakeValueRecord (pos->valueFormat2, fp, offset); + } +} + +static Pos21Ptr makeGPOS21 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *pOffset; + Pos21Ptr pos = XCALLOC1 (Pos21); + + cOffset = ttfGetUSHORT (fp); + pos->valueFormat1 = getValueFormat (fp); + pos->valueFormat2 = getValueFormat (fp); + pos->pairSetCount = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (pos->pairSetCount, fp); + pos->coverage = otfMakeCoverage (fp, offset + cOffset); + pos->pairSet = XCALLOC (pos->pairSetCount, PairSet); + for (i = 0; i < pos->pairSetCount; i++) + gposLoadPairSet (pos, i, fp, offset, pOffset[i]); + free (pOffset); + + return pos; +} + +static void printGPOS21 (FILE *fp, Pos21Ptr pos) +{ + int i; + + fprintf (fp, " - Pair Adjustment List\n\t "); + otfPrintCoverage (fp, pos->coverage); + fprintf (fp, "\t valueFormat1: 0x%04x, valueFormat2: 0x%04x, pairSetCount: %d\n", + pos->valueFormat1, pos->valueFormat2, pos->pairSetCount); + for (i = 0; i < pos->pairSetCount; i++) { + int j; + fprintf (fp, "\t %2d. pairValueCount: %d\n", i, pos->pairSet[i].pairValueCount); + for (j = 0; j < pos->pairSet[i].pairValueCount; j++) { + fprintf (fp, "\t %2d. secondGlyph: %d\n", j, + pos->pairSet[i].pairValue[j].secondGlyph); + if (pos->valueFormat1) { + fprintf (fp, "\t\t value1"); + gposPrintValueRecord (fp, "\t\t\t ", pos->valueFormat1, + pos->pairSet[i].pairValue[j].value1); + } + if (pos->valueFormat2) { + fprintf (fp, "\t\t value2"); + gposPrintValueRecord (fp, "\t\t\t ", pos->valueFormat2, + pos->pairSet[i].pairValue[j].value2); + } + } + } +} + +static void freeGPOS21 (Pos21Ptr pos) +{ + int i; + + for (i = 0; i < pos->pairSetCount; i++) { + int j; + for (j = 0; j < pos->pairSet[i].pairValueCount; j++) { + freeValueRecord (pos->pairSet[i].pairValue[j].value1); + freeValueRecord (pos->pairSet[i].pairValue[j].value2); + } + free (pos->pairSet[i].pairValue); + } + free (pos->pairSet); + otfFreeCoverage (pos->coverage); +} + +static Pos22Ptr makeGPOS22 (FILE *fp, ULONG offset) +{ + int num = 0, i; + USHORT cOffset, cOffset1, cOffset2; + Pos22Ptr pos = XCALLOC1 (Pos22); + + cOffset = ttfGetUSHORT (fp); + pos->valueFormat1 = getValueFormat (fp); + pos->valueFormat2 = getValueFormat (fp); + cOffset1 = ttfGetUSHORT (fp); + cOffset2 = ttfGetUSHORT (fp); + pos->class1Count = ttfGetUSHORT (fp); + pos->class2Count = ttfGetUSHORT (fp); + pos->values = XCALLOC (2 * pos->class1Count * pos->class2Count, ValueRecordPtr); + for (i = 0; i < pos->class1Count; i++) { + int j; + + for (j = 0; j < pos->class2Count; j++) { + pos->values[num++] = gposMakeValueRecord (pos->valueFormat1, fp, offset); + pos->values[num++] = gposMakeValueRecord (pos->valueFormat2, fp, offset); + } + } + pos->coverage = otfMakeCoverage (fp, offset + cOffset); + pos->classDef1 = otfMakeClassDef (fp, offset + cOffset1); + pos->classDef2 = otfMakeClassDef (fp, offset + cOffset2); + + return pos; +} + +static void printGPOS22 (FILE *fp, Pos22Ptr pos) +{ + int num = 0, i; + + fprintf (fp, " - Pair Adjustment Class\n\t "); + otfPrintCoverage (fp, pos->coverage); + fprintf (fp, "\t valueFormat1: 0x%04x, valueFormat2: 0x%04x\n", + pos->valueFormat1, pos->valueFormat2); + fprintf (fp, "\t ClassDef1 - "); + otfPrintClassDef (fp, pos->classDef1); + fprintf (fp, "\t ClassDef2 - "); + otfPrintClassDef (fp, pos->classDef2); + fprintf (fp, "\t class1Count: %d, class2Count: %d\n", + pos->class1Count, pos->class2Count); + for (i = 0; i < pos->class1Count; i++) { + int j; + const char *s = ""; + + fprintf (fp, "\t %2d.", i); + for (j = 0; j < pos->class2Count; j++) { + fprintf (fp, "%s %2d.", s, j); + s = "\t "; + + if (pos->valueFormat1) { + fprintf (fp, " value1"); + gposPrintValueRecord (fp, "\t\t\t ", pos->valueFormat1, + pos->values[num]); + } + num++; + if (pos->valueFormat2) { + fprintf (fp, " value2"); + gposPrintValueRecord (fp, "\t\t\t ", pos->valueFormat2, + pos->values[num]); + } + num++; + } + } +} + +static void freeGPOS22 (Pos22Ptr pos) +{ + int i; + + for (i = 0; i < 2 * pos->class1Count * pos->class2Count; i++) + freeValueRecord (pos->values[i]); + free (pos->values); + otfFreeCoverage (pos->coverage); + otfFreeClassDef (pos->classDef1); + otfFreeClassDef (pos->classDef2); +} + +static Pos31Ptr makeGPOS31 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *eOffset; + Pos31Ptr pos = XCALLOC1 (Pos31); + + cOffset = ttfGetUSHORT (fp); + pos->entryExitCount = ttfGetUSHORT (fp); + eOffset = ttfMakeUSHORT (2 * pos->entryExitCount, fp); + pos->coverage = otfMakeCoverage (fp, offset + cOffset); + pos->entryExit = XCALLOC (2 * pos->entryExitCount, AnchorPtr); + for (i = 0; i < 2 * pos->entryExitCount; i++) + if (eOffset[i]) + pos->entryExit[i] = gposMakeAnchor (fp, offset + eOffset[i]); + free (eOffset); + + return pos; +} + +static void printGPOS31 (FILE *fp, Pos31Ptr pos) +{ + int i, num = 0; + fprintf (fp, " - Cursive Attachment\n\t "); + otfPrintCoverage (fp, pos->coverage); + fprintf (fp, "\t entryExitCount: %d\n", pos->entryExitCount); + for (i = 0; i < pos->entryExitCount; i++) { + int j; + const char *s = ""; + + fprintf (fp, "\t %2d. ", i); + for (j = 0; j < 2; j++) { + if (pos->entryExit[num].anchor1) { + fprintf (fp, "%s%sAnchor - ", s, j ? "exit" : "entry"); + gposPrintAnchor (fp, "\t\t ", pos->entryExit[num]); + s = "\t "; + } + num++; + } + } +} + +static void freeGPOS31 (Pos31Ptr pos) +{ + int i; + + for (i = 0; i < 2 * pos->entryExitCount; i++) + freeAnchor (pos->entryExit[i]); + free (pos->entryExit); + otfFreeCoverage (pos->coverage); +} + +static Pos41Ptr makeGPOS41 (FILE *fp, ULONG offset) +{ + USHORT mcOffset, bcOffset, maOffset, baOffset; + Pos41Ptr pos = XCALLOC1 (Pos41); + + mcOffset = ttfGetUSHORT (fp); + bcOffset = ttfGetUSHORT (fp); + pos->classCount = ttfGetUSHORT (fp); + maOffset = ttfGetUSHORT (fp); + baOffset = ttfGetUSHORT (fp); + pos->markCoverage = otfMakeCoverage (fp, offset + mcOffset); + pos->baseCoverage = otfMakeCoverage (fp, offset + bcOffset); + pos->markArray = gposMakeMarkArray (fp, &pos->markCount, offset + maOffset); + pos->baseArray = gposMakeBaseArray (fp, &pos->baseCount, pos->classCount, offset + baOffset); + + return pos; +} + +static void printGPOS41 (FILE *fp, Pos41Ptr pos) +{ + int i, num = 0; + + fprintf (fp, " - Mark To Base Attachment\n\t mark"); + otfPrintCoverage (fp, pos->markCoverage); + fprintf (fp, "\t markArray - markCount: %d\n", pos->markCount); + gposPrintMarkArray (fp, pos->markCount, pos->markArray); + fprintf (fp, "\t base"); + otfPrintCoverage (fp, pos->baseCoverage); + fprintf (fp, "\t baseArray - baseCount: %d, classCount: %d\n", + pos->baseCount, pos->classCount); + for (i = 0; i < pos->baseCount; i++) { + int j; + const char *s = ""; + + fprintf (fp, "\t %2d. ", i); + for (j = 0; j < pos->classCount; j++) { + if (pos->baseArray[num].anchor1) { + fprintf (fp, "%s%2d. ", s, j); + gposPrintAnchor (fp, "\t\t ", pos->baseArray[num]); + s = "\t "; + } + num++; + } + } +} + +static void freeGPOS41 (Pos41Ptr pos) +{ + int i; + + for (i = 0; i < pos->markCount; i++) + freeAnchor (pos->markArray[i].markAnchor); + free (pos->markArray); + for (i = 0; i < pos->baseCount * pos->classCount; i++) + freeAnchor (pos->baseArray[i]); + free (pos->baseArray); + otfFreeCoverage (pos->markCoverage); + otfFreeCoverage (pos->baseCoverage); +} + +static void +gposLoadLigatureArray (LigatureAttachPtr ligatureArray, USHORT classCount, FILE *fp, ULONG offset) +{ + int i; + USHORT *aOffset; + + xfseek (fp, offset, SEEK_SET, "gposLoadLigatureArray"); + + ligatureArray->componentCount = ttfGetUSHORT (fp); + aOffset = ttfMakeUSHORT (ligatureArray->componentCount * classCount, fp); + ligatureArray->componentRecord = XCALLOC (ligatureArray->componentCount * classCount, AnchorPtr); + for (i = 0; i < ligatureArray->componentCount * classCount; i++) + if (aOffset[i]) + ligatureArray->componentRecord[i] = gposMakeAnchor (fp, offset + aOffset[i]); + free (aOffset); +} + +static LigatureAttachPtr +gposMakeLigatureArray (FILE *fp, USHORT *ligatureCount, USHORT classCount, ULONG offset) +{ + int i; + LigatureAttachPtr ligatureArray; + USHORT *aOffset; + + xfseek (fp, offset, SEEK_SET, "gposMakeLigatureArray"); + + *ligatureCount = ttfGetUSHORT (fp); + aOffset = ttfMakeUSHORT (*ligatureCount, fp); + ligatureArray = XCALLOC (*ligatureCount, LigatureAttach); + for (i = 0; i < *ligatureCount; i++) + gposLoadLigatureArray (&ligatureArray[i], classCount, fp, offset + aOffset[i]); + free (aOffset); + + return ligatureArray; +} + +static Pos51Ptr makeGPOS51 (FILE *fp, ULONG offset) +{ + USHORT mcOffset, lcOffset, maOffset, laOffset; + Pos51Ptr pos = XCALLOC1 (Pos51); + + mcOffset = ttfGetUSHORT (fp); + lcOffset = ttfGetUSHORT (fp); + pos->classCount = ttfGetUSHORT (fp); + maOffset = ttfGetUSHORT (fp); + laOffset = ttfGetUSHORT (fp); + pos->markCoverage = otfMakeCoverage (fp, offset + mcOffset); + pos->ligatureCoverage = otfMakeCoverage (fp, offset + lcOffset); + pos->markArray = gposMakeMarkArray (fp, &pos->markCount, offset + maOffset); + pos->ligatureArray = gposMakeLigatureArray (fp, &pos->ligatureCount, pos->classCount, offset + laOffset); + + return pos; +} + +static void printGPOS51 (FILE *fp, Pos51Ptr pos) +{ + int i; + + fprintf (fp, " - Mark To Ligature Attachment\n\t mark"); + otfPrintCoverage (fp, pos->markCoverage); + fprintf (fp, "\t markArray - markCount: %d\n", pos->markCount); + gposPrintMarkArray (fp, pos->markCount, pos->markArray); + fprintf (fp, "\t ligature"); + otfPrintCoverage (fp, pos->ligatureCoverage); + fprintf (fp, "\t ligatureArray - ligatureCount: %d\n", pos->ligatureCount); + for (i = 0; i < pos->ligatureCount; i++) { + int j, num = 0; + + fprintf (fp, "\t %2d. componentCount: %d, classCount: %d\n", i, + pos->ligatureArray[i].componentCount, pos->classCount); + for (j = 0; j < pos->ligatureArray[i].componentCount; j++) { + int k; + const char *s = ""; + + fprintf (fp, "\t %2d. ", j); + for (k = 0; k < pos->classCount; k++) { + if (pos->ligatureArray[i].componentRecord[num].anchor1) { + fprintf (fp, "%s%2d. ", s, k); + gposPrintAnchor (fp, "\t\t ", pos->ligatureArray[i].componentRecord[num]); + s = "\t\t "; + } + num++; + } + } + } +} + +static void freeGPOS51 (Pos51Ptr pos) +{ + int i; + + for (i = 0; i < pos->markCount; i++) + freeAnchor (pos->markArray[i].markAnchor); + free (pos->markArray); + for (i = 0; i < pos->ligatureCount; i++) { + int j; + + for (j = 0; j < pos->ligatureArray[i].componentCount * pos->classCount; j++) + freeAnchor (pos->ligatureArray[i].componentRecord[j]); + } + free (pos->ligatureArray); + otfFreeCoverage (pos->markCoverage); + otfFreeCoverage (pos->ligatureCoverage); +} + +static Pos61Ptr makeGPOS61 (FILE *fp, ULONG offset) +{ + USHORT c1Offset, c2Offset, a1Offset, a2Offset; + Pos61Ptr pos = XCALLOC1 (Pos61); + + c1Offset = ttfGetUSHORT (fp); + c2Offset = ttfGetUSHORT (fp); + pos->classCount = ttfGetUSHORT (fp); + a1Offset = ttfGetUSHORT (fp); + a2Offset = ttfGetUSHORT (fp); + pos->mark1Coverage = otfMakeCoverage (fp, offset + c1Offset); + pos->mark2Coverage = otfMakeCoverage (fp, offset + c2Offset); + pos->mark1Array = gposMakeMarkArray (fp, &pos->mark1Count, offset + a1Offset); + pos->mark2Array = gposMakeBaseArray (fp, &pos->mark2Count, pos->classCount, offset + a2Offset); + + return pos; +} + +static void printGPOS61 (FILE *fp, Pos61Ptr pos) +{ + int i, num = 0; + + fprintf (fp, " - Mark To Mark Attachment\n\t mark1"); + otfPrintCoverage (fp, pos->mark1Coverage); + fprintf (fp, "\t mark1Array - mark1Count: %d\n", pos->mark1Count); + gposPrintMarkArray (fp, pos->mark1Count, pos->mark1Array); + fprintf (fp, "\t mark2"); + otfPrintCoverage (fp, pos->mark2Coverage); + fprintf (fp, "\t mark2Array - mark2Count: %d, classCount: %d\n", + pos->mark2Count, pos->classCount); + for (i = 0; i < pos->mark2Count; i++) { + int j; + const char *s = ""; + + fprintf (fp, "\t %2d. ", i); + for (j = 0; j < pos->classCount; j++) { + if (pos->mark2Array[num].anchor1) { + fprintf (fp, "%s%2d. ", s, j); + gposPrintAnchor (fp, "\t\t ", pos->mark2Array[num]); + s = "\t "; + } + num++; + } + } +} + +static void freeGPOS61 (Pos61Ptr pos) +{ + int i; + + for (i = 0; i < pos->mark1Count; i++) + freeAnchor (pos->mark1Array[i].markAnchor); + free (pos->mark1Array); + for (i = 0; i < pos->mark2Count * pos->classCount; i++) + freeAnchor (pos->mark2Array[i]); + free (pos->mark2Array); + otfFreeCoverage (pos->mark1Coverage); + otfFreeCoverage (pos->mark2Coverage); +} + +#define makeGPOS71 makeOTFCtx1 +#define printGPOS71 printOTFCtx1 +#define freeGPOS71 freeOTFCtx1 + +#define makeGPOS72 makeOTFCtx2 +#define printGPOS72 printOTFCtx2 +#define freeGPOS72 freeOTFCtx2 + +#define makeGPOS73 makeOTFCtx3 +#define printGPOS73 printOTFCtx3 +#define freeGPOS73 freeOTFCtx3 + +#define makeGPOS81 makeOTFChn1 +#define printGPOS81 printOTFChn1 +#define freeGPOS81 freeOTFChn1 + +#define makeGPOS82 makeOTFChn2 +#define printGPOS82 printOTFChn2 +#define freeGPOS82 freeOTFChn2 + +#define makeGPOS83 makeOTFChn3 +#define printGPOS83 printOTFChn3 +#define freeGPOS83 freeOTFChn3 + +static LookupPtr makeGPOSLookup (FILE *fp, USHORT lookupType, ULONG offset) +{ + LookupPtr lookup; + USHORT lookupFormat; + +again: + if (lookupType == 0 || lookupType > PosLookup_Max) + ttfError ("Unrecognized GPOS lookupType\n"); + + xfseek (fp, offset, SEEK_SET, "makeGPOSLookup"); + + lookupFormat = ttfGetUSHORT (fp); + if (lookupFormat & 0xfff0) + lookupFormat = 0x000f; + + switch (lookupType << 4 | lookupFormat) + { + case 0x011: + lookup.pos.pos11 = makeGPOS11 (fp, offset); + break; + case 0x012: + lookup.pos.pos12 = makeGPOS12 (fp, offset); + break; + case 0x021: + lookup.pos.pos21 = makeGPOS21 (fp, offset); + break; + case 0x022: + lookup.pos.pos22 = makeGPOS22 (fp, offset); + break; + case 0x031: + lookup.pos.pos31 = makeGPOS31 (fp, offset); + break; + case 0x041: + lookup.pos.pos41 = makeGPOS41 (fp, offset); + break; + case 0x051: + lookup.pos.pos51 = makeGPOS51 (fp, offset); + break; + case 0x061: + lookup.pos.pos61 = makeGPOS61 (fp, offset); + break; + case 0x071: + lookup.pos.pos71 = makeGPOS71 (fp, offset); + break; + case 0x072: + lookup.pos.pos72 = makeGPOS72 (fp, offset); + break; + case 0x073: + lookup.pos.pos73 = makeGPOS73 (fp, offset); + break; + case 0x081: + lookup.pos.pos81 = makeGPOS81 (fp, offset); + break; + case 0x082: + lookup.pos.pos82 = makeGPOS82 (fp, offset); + break; + case 0x083: + lookup.pos.pos83 = makeGPOS83 (fp, offset); + break; + case 0x091: + lookupType = ttfGetUSHORT (fp); + if (lookupType == 9) + ttfError ("Invalid GPOS extensionLookupType\n"); + offset += ttfGetULONG (fp); + goto again; + default: + ttfError ("Unrecognized GPOS lookupFormat\n"); + } + + lookup.otf->lookupType = lookupType; + lookup.otf->lookupFormat = lookupFormat; + + return lookup; +} + +static void printGPOSLookup (FILE *fp, LookupPtr lookup) +{ + switch (lookup.otf->lookupType << 4 | lookup.otf->lookupFormat) + { + case 0x011: + printGPOS11 (fp, lookup.pos.pos11); + break; + case 0x012: + printGPOS12 (fp, lookup.pos.pos12); + break; + case 0x021: + printGPOS21 (fp, lookup.pos.pos21); + break; + case 0x022: + printGPOS22 (fp, lookup.pos.pos22); + break; + case 0x031: + printGPOS31 (fp, lookup.pos.pos31); + break; + case 0x041: + printGPOS41 (fp, lookup.pos.pos41); + break; + case 0x051: + printGPOS51 (fp, lookup.pos.pos51); + break; + case 0x061: + printGPOS61 (fp, lookup.pos.pos61); + break; + case 0x071: + printGPOS71 (fp, lookup.pos.pos71); + break; + case 0x072: + printGPOS72 (fp, lookup.pos.pos72); + break; + case 0x073: + printGPOS73 (fp, lookup.pos.pos73); + break; + case 0x081: + printGPOS81 (fp, lookup.pos.pos81); + break; + case 0x082: + printGPOS82 (fp, lookup.pos.pos82); + break; + case 0x083: + printGPOS83 (fp, lookup.pos.pos83); + break; + default: + ttfError ("Internal error: printGPOSLookup\n"); + } +} + +static void freeGPOSLookup (LookupPtr lookup) +{ + switch (lookup.otf->lookupType << 4 | lookup.otf->lookupFormat) + { + case 0x011: + freeGPOS11 (lookup.pos.pos11); + break; + case 0x012: + freeGPOS12 (lookup.pos.pos12); + break; + case 0x021: + freeGPOS21 (lookup.pos.pos21); + break; + case 0x022: + freeGPOS22 (lookup.pos.pos22); + break; + case 0x031: + freeGPOS31 (lookup.pos.pos31); + break; + case 0x041: + freeGPOS41 (lookup.pos.pos41); + break; + case 0x051: + freeGPOS51 (lookup.pos.pos51); + break; + case 0x061: + freeGPOS61 (lookup.pos.pos61); + break; + case 0x071: + freeGPOS71 (lookup.pos.pos71); + break; + case 0x072: + freeGPOS72 (lookup.pos.pos72); + break; + case 0x073: + freeGPOS73 (lookup.pos.pos73); + break; + case 0x081: + freeGPOS81 (lookup.pos.pos81); + break; + case 0x082: + freeGPOS82 (lookup.pos.pos82); + break; + case 0x083: + freeGPOS83 (lookup.pos.pos83); + break; + default: + ttfError ("Internal error: freeGPOSLookup\n"); + } +} + +static void ttfLoadGPOS (FILE *fp, GPOSPtr gpos, ULONG offset) +{ + USHORT sOffset, fOffset, lOffset; + + xfseek (fp, offset, SEEK_SET, "ttfLoadGPOS"); + + gpos->version = ttfGetFixed (fp); + sOffset = ttfGetUSHORT (fp); + fOffset = ttfGetUSHORT (fp); + lOffset = ttfGetUSHORT (fp); + + gpos->scriptList = otfMakeScriptList (fp, offset + sOffset); + gpos->featureList = otfMakeFeatureList (fp, offset + fOffset); + gpos->lookupList = otfMakeLookupList (fp, offset + lOffset, &makeGPOSLookup); +} + +void ttfInitGPOS (TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('G', 'P', 'O', 'S'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir (tag, font)) != NULL) + { + font->gpos = XCALLOC1 (GPOS); + ttfLoadGPOS (font->fp, font->gpos, ptd->offset); + } +} + +void ttfPrintGPOS (FILE *fp, GPOSPtr gpos) +{ + int b[2]; + + FixedSplit (gpos->version, b); + + fprintf (fp, "'GPOS' Table - Glyph Positioning Data\n"); + fprintf (fp, "-------------------------------------\n"); + fprintf (fp, "\t 'GPOS' Version:\t %d.%d\n",b[1],b[0]); + + otfPrintScriptList (fp, gpos->scriptList); + otfPrintFeatureList (fp, gpos->featureList); + otfPrintLookupList (fp, gpos->lookupList, &printGPOSLookup); +} + +void ttfFreeGPOS (GPOSPtr gpos) +{ + if (gpos != NULL) + { + otfFreeScriptList (gpos->scriptList); + otfFreeFeatureList (gpos->featureList); + otfFreeLookupList (gpos->lookupList, &freeGPOSLookup); + free (gpos); + } +} diff --git a/Build/source/texk/ttfdump/libttf/gsub.c b/Build/source/texk/ttfdump/libttf/gsub.c new file mode 100644 index 00000000000..a0c8549bfc2 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/gsub.c @@ -0,0 +1,553 @@ +/* gsub.c -- Glyph Substitution Table + */ +#include <stdio.h> +#include <stdlib.h> +#include "config.h" +#include "ttf.h" +#include "ttfutil.h" + +static Sub11Ptr makeGSUB11 (FILE *fp, ULONG offset) +{ + USHORT cOffset; + Sub11Ptr sub = XCALLOC1 (Sub11); + + cOffset = ttfGetUSHORT (fp); + sub->deltaGlyphID = ttfGetUSHORT (fp); + sub->coverage = otfMakeCoverage (fp, offset + cOffset); + + return sub; +} + +static void printGSUB11 (FILE *fp, Sub11Ptr sub) +{ + fprintf (fp, " - Single Substitution Delta\n\t "); + otfPrintCoverage (fp, sub->coverage); + fprintf (fp, "\t deltaGlyphID: %d\n", sub->deltaGlyphID); +} + +static void freeGSUB11 (Sub11Ptr sub) +{ + otfFreeCoverage (sub->coverage); +} + +static Sub12Ptr makeGSUB12 (FILE *fp, ULONG offset) +{ + USHORT cOffset; + Sub12Ptr sub = XCALLOC1 (Sub12); + + cOffset = ttfGetUSHORT (fp); + sub->glyphCount = ttfGetUSHORT (fp); + sub->substitute = ttfMakeUSHORT (sub->glyphCount, fp); + sub->coverage = otfMakeCoverage (fp, offset + cOffset); + + return sub; +} + +static void printGSUB12 (FILE *fp, Sub12Ptr sub) +{ + int i; + + fprintf (fp, " - Single Substitution List\n\t "); + otfPrintCoverage (fp, sub->coverage); + fprintf (fp, "\t glyphCount: %d\n\t\t substitute: %d", + sub->glyphCount, sub->substitute[0]); + for (i = 1; i < sub->glyphCount; i++) + fprintf (fp, i % 8 ? ", %d" : ",\n\t\t\t %d", sub->substitute[i]); + fprintf (fp, "\n"); +} + +static void freeGSUB12 (Sub12Ptr sub) +{ + otfFreeCoverage (sub->coverage); + free (sub->substitute); +} + +static void gsubLoadSequence (SequencePtr sequence, FILE *fp, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "gsubLoadSequence"); + + sequence->glyphCount = ttfGetUSHORT (fp); + sequence->substitute = ttfMakeUSHORT (sequence->glyphCount, fp); +} + +static Sub21Ptr makeGSUB21 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *sOffset; + Sub21Ptr sub = XCALLOC1 (Sub21); + + cOffset = ttfGetUSHORT (fp); + sub->sequenceCount = ttfGetUSHORT (fp); + sOffset = ttfMakeUSHORT (sub->sequenceCount, fp); + sub->coverage = otfMakeCoverage (fp, offset + cOffset); + sub->sequence = XCALLOC (sub->sequenceCount, Sequence); + for (i = 0; i < sub->sequenceCount; i++) + gsubLoadSequence (&sub->sequence[i], fp, offset + sOffset[i]); + free (sOffset); + + return sub; +} + +static void printGSUB21 (FILE *fp, Sub21Ptr sub) +{ + int i; + + fprintf (fp, " - Multiple Substitution\n\t "); + otfPrintCoverage (fp, sub->coverage); + fprintf (fp, "\t sequenceCount: %d\n", sub->sequenceCount); + for (i = 0; i < sub->sequenceCount; i++) { + int j; + + fprintf (fp, "\t %2d. glyphCount: %d - ", i, sub->sequence[i].glyphCount); + for (j = 0; j < sub->sequence[i].glyphCount; j++) + fprintf (fp, j == 0 ? "- %d" : ", %d", sub->sequence[i].substitute[j]); + fprintf (fp, "\n"); + } +} + +static void freeGSUB21 (Sub21Ptr sub) +{ + int i; + + otfFreeCoverage (sub->coverage); + for (i = 0; i < sub->sequenceCount; i++) + free (sub->sequence[i].substitute); + free (sub->sequence); +} + +static void gsubLoadAlternateSet (AlternateSetPtr alternateSet, FILE *fp, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "gsubLoadAlternateSet"); + + alternateSet->glyphCount = ttfGetUSHORT (fp); + alternateSet->alternate = ttfMakeUSHORT (alternateSet->glyphCount, fp); +} + +static Sub31Ptr makeGSUB31 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *aOffset; + Sub31Ptr sub = XCALLOC1 (Sub31); + + cOffset = ttfGetUSHORT (fp); + sub->alternateSetCount = ttfGetUSHORT (fp); + aOffset = ttfMakeUSHORT (sub->alternateSetCount, fp); + sub->coverage = otfMakeCoverage (fp, offset + cOffset); + sub->alternateSet = XCALLOC (sub->alternateSetCount, AlternateSet); + for (i = 0; i < sub->alternateSetCount; i++) + gsubLoadAlternateSet (&sub->alternateSet[i], fp, offset + aOffset[i]); + free (aOffset); + + return sub; +} + +static void printGSUB31 (FILE *fp, Sub31Ptr sub) +{ + int i; + + fprintf (fp, " - Alternate Substitution\n\t "); + otfPrintCoverage (fp, sub->coverage); + fprintf (fp, "\t alternateSetCount: %d\n", sub->alternateSetCount); + for (i = 0; i < sub->alternateSetCount; i++) { + int j; + + fprintf (fp, "\t %2d. glyphCount: %d ", i, sub->alternateSet[i].glyphCount); + for (j = 0; j < sub->alternateSet[i].glyphCount; j++) + fprintf (fp, j == 0 ? "- %d" : ", %d", sub->alternateSet[i].alternate[j]); + fprintf (fp, "\n"); + } +} + +static void freeGSUB31 (Sub31Ptr sub) +{ + int i; + + otfFreeCoverage (sub->coverage); + for (i = 0; i < sub->alternateSetCount; i++) + free (sub->alternateSet[i].alternate); + free (sub->alternateSet); +} + +static void gsubLoadLigature (LigaturePtr ligature, FILE *fp, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "gsubLoadLigature"); + + ligature->ligGlyph = ttfGetUSHORT (fp); + ligature->compCount = ttfGetUSHORT (fp); + ligature->component = ttfMakeUSHORT (ligature->compCount - 1, fp); +} + +static void gsubLoadLigatureSet (LigatureSetPtr ligatureSet, FILE *fp, ULONG offset) +{ + int i; + USHORT *lOffset; + + xfseek (fp, offset, SEEK_SET, "gsubLoadLigatureSet"); + + ligatureSet->ligatureCount = ttfGetUSHORT (fp); + lOffset = ttfMakeUSHORT (ligatureSet->ligatureCount, fp); + ligatureSet->ligature = XCALLOC (ligatureSet->ligatureCount, Ligature); + for (i = 0; i < ligatureSet->ligatureCount; i++) + gsubLoadLigature (&ligatureSet->ligature[i], fp, offset + lOffset[i]); + free (lOffset); +} + +static Sub41Ptr makeGSUB41 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *lOffset; + Sub41Ptr sub = XCALLOC1 (Sub41); + + cOffset = ttfGetUSHORT (fp); + sub->ligSetCount = ttfGetUSHORT (fp); + lOffset = ttfMakeUSHORT (sub->ligSetCount, fp); + sub->coverage = otfMakeCoverage (fp, offset + cOffset); + sub->ligatureSet = XCALLOC (sub->ligSetCount, LigatureSet); + for (i = 0; i < sub->ligSetCount; i++) + gsubLoadLigatureSet (&sub->ligatureSet[i], fp, offset + lOffset[i]); + free (lOffset); + + return sub; +} + +static void printGSUB41 (FILE *fp, Sub41Ptr sub) +{ + int i; + + fprintf (fp, " - Ligature Substitution\n\t "); + otfPrintCoverage (fp, sub->coverage); + fprintf (fp, "\t ligSetCount: %d\n", sub->ligSetCount); + for (i = 0; i < sub->ligSetCount; i++) { + int j; + + fprintf (fp, "\t %2d. ligatureCount: %d\n", i, sub->ligatureSet[i].ligatureCount); + for (j = 0; j < sub->ligatureSet[i].ligatureCount; j++) { + int k; + + fprintf (fp, "\t %2d. ligGlyph: %d, compCount: %d ", j, + sub->ligatureSet[i].ligature[j].ligGlyph, + sub->ligatureSet[i].ligature[j].compCount); + for (k = 0; k < sub->ligatureSet[i].ligature[j].compCount - 1; k++) + fprintf (fp, k == 0 ? "- %d" : ", %d", sub->ligatureSet[i].ligature[j].component[k]); + fprintf (fp, "\n"); + } + } +} + +static void freeGSUB41 (Sub41Ptr sub) +{ + int i; + + otfFreeCoverage (sub->coverage); + for (i = 0; i < sub->ligSetCount; i++) { + int j; + + for (j = 0; j < sub->ligatureSet[i].ligatureCount; j++) + free (sub->ligatureSet[i].ligature[j].component); + free (sub->ligatureSet[i].ligature); + } + free (sub->ligatureSet); +} + +#define makeGSUB51 makeOTFCtx1 +#define printGSUB51 printOTFCtx1 +#define freeGSUB51 freeOTFCtx1 + +#define makeGSUB52 makeOTFCtx2 +#define printGSUB52 printOTFCtx2 +#define freeGSUB52 freeOTFCtx2 + +#define makeGSUB53 makeOTFCtx3 +#define printGSUB53 printOTFCtx3 +#define freeGSUB53 freeOTFCtx3 + +#define makeGSUB61 makeOTFChn1 +#define printGSUB61 printOTFChn1 +#define freeGSUB61 freeOTFChn1 + +#define makeGSUB62 makeOTFChn2 +#define printGSUB62 printOTFChn2 +#define freeGSUB62 freeOTFChn2 + +#define makeGSUB63 makeOTFChn3 +#define printGSUB63 printOTFChn3 +#define freeGSUB63 freeOTFChn3 + +static Sub81Ptr makeGSUB81 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *bOffset, *lOffset; + Sub81Ptr sub = XCALLOC1 (Sub81); + + cOffset = ttfGetUSHORT (fp); + sub->backtrackGlyphCount = ttfGetUSHORT (fp); + bOffset = ttfMakeUSHORT (sub->backtrackGlyphCount, fp); + sub->lookaheadGlyphCount = ttfGetUSHORT (fp); + lOffset = ttfMakeUSHORT (sub->lookaheadGlyphCount, fp); + sub->glyphCount = ttfGetUSHORT (fp); + sub->substitute = ttfMakeUSHORT (sub->glyphCount, fp); + sub->coverage = otfMakeCoverage (fp, offset + cOffset); + sub->backtrack = XCALLOC (sub->backtrackGlyphCount, CoveragePtr); + for (i = 0; i < sub->backtrackGlyphCount; i++) + sub->backtrack[i] = otfMakeCoverage (fp, offset + bOffset[i]); + free (bOffset); + sub->lookahead = XCALLOC (sub->lookaheadGlyphCount, CoveragePtr); + for (i = 0; i < sub->lookaheadGlyphCount; i++) + sub->lookahead[i] = otfMakeCoverage (fp, offset + lOffset[i]); + free (lOffset); + + return sub; +} + +static void printGSUB81 (FILE *fp, Sub81Ptr sub) +{ + int i; + + fprintf (fp, " - Reverse Chaining Context Single Substitution\n\t "); + otfPrintCoverage (fp, sub->coverage); + fprintf (fp, "\t backtrackGlyphCount: %d\n", sub->backtrackGlyphCount); + for (i = 0; i < sub->backtrackGlyphCount; i++) { + fprintf (fp, "\t %2d. backtrack", i); + otfPrintCoverage (fp, sub->backtrack[i]); + } + fprintf (fp, "\t lookaheadGlyphCount: %d\n", sub->lookaheadGlyphCount); + for (i = 0; i < sub->lookaheadGlyphCount; i++) { + fprintf (fp, "\t %2d. lookahead", i); + otfPrintCoverage (fp, sub->lookahead[i]); + } + fprintf (fp, "\t glyphCount: %d\n\t substitute - %d", + sub->glyphCount, sub->substitute[0]); + for (i = 1; i < sub->glyphCount; i++) + fprintf (fp, i % 8 ? ",\n\t\t %d" : ", %d", sub->substitute[i]); +} + +static void freeGSUB81 (Sub81Ptr sub) +{ + int i; + + otfFreeCoverage (sub->coverage); + for (i = 0; i < sub->backtrackGlyphCount; i++) + otfFreeCoverage (sub->backtrack[i]); + free (sub->backtrack); + for (i = 0; i < sub->lookaheadGlyphCount; i++) + otfFreeCoverage (sub->lookahead[i]); + free (sub->lookahead); + free (sub->substitute); +} + +static LookupPtr makeGSUBLookup (FILE *fp, USHORT lookupType, ULONG offset) +{ + LookupPtr lookup; + USHORT lookupFormat; + +again: + if (lookupType == 0 || lookupType > SubLookup_Max) + ttfError ("Unrecognized GSUB lookupType\n"); + + xfseek (fp, offset, SEEK_SET, "makeGSUBLookup"); + + lookupFormat = ttfGetUSHORT (fp); + if (lookupFormat & 0xfff0) + lookupFormat = 0x000f; + + switch (lookupType << 4 | lookupFormat) + { + case 0x011: + lookup.sub.sub11 = makeGSUB11 (fp, offset); + break; + case 0x012: + lookup.sub.sub12 = makeGSUB12 (fp, offset); + break; + case 0x021: + lookup.sub.sub21 = makeGSUB21 (fp, offset); + break; + case 0x031: + lookup.sub.sub31 = makeGSUB31 (fp, offset); + break; + case 0x041: + lookup.sub.sub41 = makeGSUB41 (fp, offset); + break; + case 0x051: + lookup.sub.sub51 = makeGSUB51 (fp, offset); + break; + case 0x052: + lookup.sub.sub52 = makeGSUB52 (fp, offset); + break; + case 0x053: + lookup.sub.sub53 = makeGSUB53 (fp, offset); + break; + case 0x061: + lookup.sub.sub61 = makeGSUB61 (fp, offset); + break; + case 0x062: + lookup.sub.sub62 = makeGSUB62 (fp, offset); + break; + case 0x063: + lookup.sub.sub63 = makeGSUB63 (fp, offset); + break; + case 0x081: + lookup.sub.sub81 = makeGSUB81 (fp, offset); + break; + case 0x071: + lookupType = ttfGetUSHORT (fp); + if (lookupType == 7) + ttfError ("Invalid GSUB extensionLookupType\n"); + offset += ttfGetULONG (fp); + goto again; + default: + ttfError ("Unrecognized GSUB lookupFormat\n"); + } + + lookup.otf->lookupType = lookupType; + lookup.otf->lookupFormat = lookupFormat; + + return lookup; +} + +static void printGSUBLookup (FILE *fp, LookupPtr lookup) +{ + switch (lookup.otf->lookupType << 4 | lookup.otf->lookupFormat) + { + case 0x011: + printGSUB11 (fp, lookup.sub.sub11); + break; + case 0x012: + printGSUB12 (fp, lookup.sub.sub12); + break; + case 0x021: + printGSUB21 (fp, lookup.sub.sub21); + break; + case 0x031: + printGSUB31 (fp, lookup.sub.sub31); + break; + case 0x041: + printGSUB41 (fp, lookup.sub.sub41); + break; + case 0x051: + printGSUB51 (fp, lookup.sub.sub51); + break; + case 0x052: + printGSUB52 (fp, lookup.sub.sub52); + break; + case 0x053: + printGSUB53 (fp, lookup.sub.sub53); + break; + case 0x061: + printGSUB61 (fp, lookup.sub.sub61); + break; + case 0x062: + printGSUB62 (fp, lookup.sub.sub62); + break; + case 0x063: + printGSUB63 (fp, lookup.sub.sub63); + break; + case 0x081: + printGSUB81 (fp, lookup.sub.sub81); + break; + default: + ttfError ("Internal error: printGSUBLookup\n"); + } +} + +static void freeGSUBLookup (LookupPtr lookup) +{ + switch (lookup.otf->lookupType << 4 | lookup.otf->lookupFormat) + { + case 0x011: + freeGSUB11 (lookup.sub.sub11); + break; + case 0x012: + freeGSUB12 (lookup.sub.sub12); + break; + case 0x021: + freeGSUB21 (lookup.sub.sub21); + break; + case 0x031: + freeGSUB31 (lookup.sub.sub31); + break; + case 0x041: + freeGSUB41 (lookup.sub.sub41); + break; + case 0x051: + freeGSUB51 (lookup.sub.sub51); + break; + case 0x052: + freeGSUB52 (lookup.sub.sub52); + break; + case 0x053: + freeGSUB53 (lookup.sub.sub53); + break; + case 0x061: + freeGSUB61 (lookup.sub.sub61); + break; + case 0x062: + freeGSUB62 (lookup.sub.sub62); + break; + case 0x063: + freeGSUB63 (lookup.sub.sub63); + break; + case 0x081: + freeGSUB81 (lookup.sub.sub81); + break; + default: + ttfError ("Internal error: freeGSUBLookup\n"); + } +} + +static void ttfLoadGSUB (FILE *fp, GSUBPtr gsub, ULONG offset) +{ + USHORT sOffset, fOffset, lOffset; + + xfseek (fp, offset, SEEK_SET, "ttfLoadGSUB"); + + gsub->version = ttfGetFixed (fp); + sOffset = ttfGetUSHORT (fp); + fOffset = ttfGetUSHORT (fp); + lOffset = ttfGetUSHORT (fp); + + gsub->scriptList = otfMakeScriptList (fp, offset + sOffset); + gsub->featureList = otfMakeFeatureList (fp, offset + fOffset); + gsub->lookupList = otfMakeLookupList (fp, offset + lOffset, &makeGSUBLookup); +} + +void ttfInitGSUB (TTFontPtr font) +{ + ULONG tag = FT_MAKE_TAG ('G', 'S', 'U', 'B'); + TableDirPtr ptd; + + if ((ptd = ttfLookUpTableDir (tag, font)) != NULL) + { + font->gsub = XCALLOC1 (GSUB); + ttfLoadGSUB (font->fp, font->gsub, ptd->offset); + } +} + +void ttfPrintGSUB (FILE *fp, GSUBPtr gsub) +{ + int b[2]; + + FixedSplit (gsub->version, b); + + fprintf (fp, "'GSUB' Table - Glyph Substitution Data\n"); + fprintf (fp, "--------------------------------------\n"); + fprintf (fp, "\t 'GSUB' Version:\t %d.%d\n",b[1],b[0]); + + otfPrintScriptList (fp, gsub->scriptList); + otfPrintFeatureList (fp, gsub->featureList); + otfPrintLookupList (fp, gsub->lookupList, &printGSUBLookup); +} + +void ttfFreeGSUB (GSUBPtr gsub) +{ + if (gsub != NULL) + { + otfFreeScriptList (gsub->scriptList); + otfFreeFeatureList (gsub->featureList); + otfFreeLookupList (gsub->lookupList, &freeGSUBLookup); + free (gsub); + } +} diff --git a/Build/source/texk/ttfdump/libttf/head.c b/Build/source/texk/ttfdump/libttf/head.c index ec4b33bcbaa..eec89cc9b2c 100644 --- a/Build/source/texk/ttfdump/libttf/head.c +++ b/Build/source/texk/ttfdump/libttf/head.c @@ -34,10 +34,8 @@ static void ttfLoadHEAD(FILE *fp,HEADPtr head,ULONG offset) head->flags = ttfGetUSHORT(fp); head->unitsPerEm = ttfGetUSHORT(fp); - if (fread(head->created,sizeof(char),8,fp) != 8) - ttfError("Error when getting HEAD created\n"); - if (fread(head->modified,sizeof(char),8,fp) != 8) - ttfError("Error when getting HEAD modified\n"); + ttfReadULONG (head->created, 2, fp); + ttfReadULONG (head->modified, 2, fp); head->xMin = ttfGetFWord(fp); head->yMin = ttfGetFWord(fp); @@ -61,16 +59,16 @@ void ttfPrintHEAD(FILE *fp,HEADPtr head) fprintf(fp,"'head' Table - Font Header\n"); fprintf(fp,"--------------------------\n"); - fprintf(fp,"\t 'head' version:\t %2d.%2d\n",b1[1],b1[0]); - fprintf(fp,"\t fontReversion:\t\t %2d.%2d\n",b2[1],b2[0]); + fprintf(fp,"\t 'head' version:\t %d.%d\n",b1[1],b1[0]); + fprintf(fp,"\t fontReversion:\t\t %d.%d\n",b2[1],b2[0]); fprintf(fp,"\t checkSumAdjustment:\t 0x%08x\n",head->checkSumAdj); fprintf(fp,"\t magicNumber:\t\t 0x%08x\n",head->magicNumber); fprintf(fp,"\t flags:\t\t\t 0x%04x\n",head->flags); fprintf(fp,"\t unitsPerEm:\t\t %d\n",head->unitsPerEm); /* don't know how to compute */ - fprintf(fp,"\t created:\n"); - fprintf(fp,"\t modified:\n"); + fprintf(fp,"\t created:\t\t 0x%08x%08x\n", head->created[0], head->created[1]); + fprintf(fp,"\t modified:\t\t 0x%08x%08x\n", head->modified[0], head->modified[1]); fprintf(fp,"\t xMin:\t\t\t %d\n",head->xMin); fprintf(fp,"\t yMin:\t\t\t %d\n",head->yMin); diff --git a/Build/source/texk/ttfdump/libttf/hhea.c b/Build/source/texk/ttfdump/libttf/hhea.c index 9b056dde6ab..3ec85c827d4 100644 --- a/Build/source/texk/ttfdump/libttf/hhea.c +++ b/Build/source/texk/ttfdump/libttf/hhea.c @@ -53,7 +53,7 @@ void ttfPrintHHEA(FILE *fp,HHEAPtr hhea) fprintf(fp,"'hhea' Table - Horizontal Header\n"); fprintf(fp,"--------------------------\n"); - fprintf(fp,"\t 'hhea' version:\t %2d.%2d\n",b[1],b[0]); + fprintf(fp,"\t 'hhea' version:\t %d.%d\n",b[1],b[0]); fprintf(fp,"\t yAscender:\t\t %d\n",hhea->Ascender); fprintf(fp,"\t yDescender:\t\t %d\n",hhea->Descender); fprintf(fp,"\t yLineGap:\t\t %d\n",hhea->LineGap); diff --git a/Build/source/texk/ttfdump/libttf/loca.c b/Build/source/texk/ttfdump/libttf/loca.c index 44ec5e05fcc..5342fbf20c3 100644 --- a/Build/source/texk/ttfdump/libttf/loca.c +++ b/Build/source/texk/ttfdump/libttf/loca.c @@ -59,20 +59,26 @@ void ttfPrintLOCA(FILE *fp,LOCAPtr loca) { USHORT i; - fprintf(fp,"'loca' Table - Index to Location\n"); - fprintf(fp,"--------------------------------\n"); - for (i=0;i<loca->numGlyphs;i++) - { - fprintf(fp,"\t Idx %6d -> GlyphOffset 0x%08x\n",i, - (loca->offset)[i]); - } - fprintf (fp,"\t Ended at 0x%08x\n",(loca->offset)[loca->numGlyphs]); + if (loca) + { + fprintf(fp,"'loca' Table - Index to Location\n"); + fprintf(fp,"--------------------------------\n"); + for (i=0;i<loca->numGlyphs;i++) + { + fprintf(fp,"\t Idx %6d -> GlyphOffset 0x%08x\n",i, + (loca->offset)[i]); + } + fprintf (fp,"\t Ended at 0x%08x\n",(loca->offset)[loca->numGlyphs]); + } } void ttfFreeLOCA(LOCAPtr loca) { - free (loca->offset); - free (loca); + if (loca) + { + free (loca->offset); + free (loca); + } } ULONG ttfLookUpGlyfLOCA(LOCAPtr loca,USHORT idx) diff --git a/Build/source/texk/ttfdump/libttf/maxp.c b/Build/source/texk/ttfdump/libttf/maxp.c index cefa38a4c0d..1b36fb2690b 100644 --- a/Build/source/texk/ttfdump/libttf/maxp.c +++ b/Build/source/texk/ttfdump/libttf/maxp.c @@ -49,7 +49,7 @@ void ttfPrintMAXP(FILE *fp,MAXPPtr maxp) fprintf(fp,"'maxp' Table - Maximum Profile\n"); fprintf(fp,"------------------------------\n"); - fprintf(fp,"\t 'maxp' version:\t %2d.%2d\n",b[1],b[0]); + fprintf(fp,"\t 'maxp' version:\t %d.%d\n",b[1],b[0]); fprintf(fp,"\t numGlyphs:\t\t %d\n",maxp->numGlyphs); fprintf(fp,"\t maxPoints:\t\t %d\n",maxp->maxPoints); fprintf(fp,"\t maxContours:\t\t %d\n",maxp->maxContours); diff --git a/Build/source/texk/ttfdump/libttf/otfcommon.c b/Build/source/texk/ttfdump/libttf/otfcommon.c new file mode 100644 index 00000000000..8102aae6ab5 --- /dev/null +++ b/Build/source/texk/ttfdump/libttf/otfcommon.c @@ -0,0 +1,1074 @@ +/* otfcommon.c -- OpenType Common Table Formats + */ +#include <stdio.h> +#include <stdlib.h> +#include "config.h" +#include "ttf.h" +#include "ttfutil.h" + +static LangSysPtr +otfMakeLangSys (FILE *fp, ULONG offset) +{ + LangSysPtr langSys = XCALLOC1 (LangSys); + USHORT lookupOrder; + + xfseek (fp, offset, SEEK_SET, "otfMakeLangSys"); + + if ((lookupOrder = ttfGetUSHORT (fp)) != 0) + ttfError ("Non-zero lookupOrder\n"); + langSys->reqFeatureIndex = ttfGetUSHORT (fp); + langSys->featureCount = ttfGetUSHORT (fp); + langSys->featureIndex = ttfMakeUSHORT (langSys->featureCount, fp); + + return langSys; +} + +static void +otfLoadScriptRecord (FILE *fp, ScriptRecordPtr scriptRecord, ULONG offset) +{ + int i; + USHORT dOffset; + USHORT *lOffset; + + xfseek (fp, offset, SEEK_SET, "otfLoadScriptRecord"); + + dOffset = ttfGetUSHORT (fp); + + scriptRecord->langSysCount = ttfGetUSHORT (fp); + if (scriptRecord->langSysCount) { + scriptRecord->langSysRecord = XCALLOC (scriptRecord->langSysCount, LangSysRecord); + lOffset = XTALLOC (scriptRecord->langSysCount, USHORT); + + for (i = 0; i < scriptRecord->langSysCount; i++) { + scriptRecord->langSysRecord[i].tag = ttfGetULONG (fp); + lOffset[i] = ttfGetUSHORT (fp); + } + + for (i = 0; i < scriptRecord->langSysCount; i++) + scriptRecord->langSysRecord[i].langSys = otfMakeLangSys (fp, offset + lOffset[i]); + + free (lOffset); + } + + if (dOffset) + scriptRecord->defaultLangSys = otfMakeLangSys (fp, offset + dOffset); +} + +ScriptListPtr +otfMakeScriptList (FILE *fp, ULONG offset) +{ + int i; + USHORT *sOffset; + ScriptListPtr scriptList = XCALLOC1 (ScriptList); + + xfseek (fp, offset, SEEK_SET, "otfMakeScriptList"); + + scriptList->scriptCount = ttfGetUSHORT (fp); + scriptList->scriptRecord = XCALLOC (scriptList->scriptCount, ScriptRecord); + sOffset = XTALLOC (scriptList->scriptCount, USHORT); + + for (i = 0; i < scriptList->scriptCount; i++) { + scriptList->scriptRecord[i].tag = ttfGetULONG (fp); + sOffset[i] = ttfGetUSHORT (fp); + } + + for (i = 0; i < scriptList->scriptCount; i++) + otfLoadScriptRecord (fp, &scriptList->scriptRecord[i], offset + sOffset[i]); + + free (sOffset); + + return scriptList; +} + +static void +otfPrintLangSys (FILE *fp, LangSysPtr langSys) +{ + int i; + + fprintf (fp, " lang - featureCount: %d\n", langSys->featureCount); + if (langSys->reqFeatureIndex != 0xffff) + fprintf (fp, "\t\t reqFeatureIndex: %d\n", langSys->reqFeatureIndex); + if (langSys->featureCount) { + fprintf (fp, "\t\t featureIndex: %d", langSys->featureIndex[0]); + for (i = 1; i < langSys->featureCount; i++) + fprintf (fp, i % 8 ? ", %d" : ",\n\t\t\t\t%d", + langSys->featureIndex[i]); + fprintf (fp, "\n"); + } +} + +static void +otfPrintScriptRecord (FILE *fp, ScriptRecordPtr scriptRecord) +{ + int i; + + fprintf (fp, "'%s' script - langSysCount: %d\n", + TagToStr (scriptRecord->tag), scriptRecord->langSysCount); + if (scriptRecord->defaultLangSys) { + fprintf (fp, "\t default"); + otfPrintLangSys (fp, scriptRecord->defaultLangSys); + } + for (i = 0; i < scriptRecord->langSysCount; i++) { + fprintf (fp, " %2d. '%s'", i, + TagToStr (scriptRecord->langSysRecord[i].tag)); + otfPrintLangSys (fp, scriptRecord->langSysRecord[i].langSys); + } +} + +void +otfPrintScriptList (FILE *fp, ScriptListPtr scriptList) +{ + int i; + + fprintf (fp, " scriptCount: %d\n", scriptList->scriptCount); + + for (i = 0; i < scriptList->scriptCount; i++) { + fprintf (fp, " %2d. ", i); + otfPrintScriptRecord (fp, &scriptList->scriptRecord[i]); + } + fprintf (fp, "\n"); +} + +static void +otfFreeLangSys (LangSysPtr langSys) +{ + free (langSys->featureIndex); + free (langSys); +} + +static void +otfFreeScriptRecord (ScriptRecordPtr scriptRecord) +{ + int i; + + if (scriptRecord->defaultLangSys) + otfFreeLangSys (scriptRecord->defaultLangSys); + for (i = 0; i < scriptRecord->langSysCount; i++) + otfFreeLangSys (scriptRecord->langSysRecord[i].langSys); + free (scriptRecord->langSysRecord); +} + +void +otfFreeScriptList (ScriptListPtr scriptList) +{ + int i; + + for (i = 0; i < scriptList->scriptCount; i++) + otfFreeScriptRecord (&scriptList->scriptRecord[i]); + free (scriptList->scriptRecord); + free (scriptList); +} + +static void +otfLoadFeatureRecord (FILE *fp, FeatureRecordPtr featureRecord, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "otfLoadFeatureRecord"); + + featureRecord->featureParams = ttfGetUSHORT (fp); + featureRecord->lookupCount = ttfGetUSHORT (fp); + featureRecord->lookupListIndex = ttfMakeUSHORT (featureRecord->lookupCount, fp); +} + +FeatureListPtr +otfMakeFeatureList (FILE *fp, ULONG offset) +{ + int i; + USHORT *fOffset; + FeatureListPtr featureList = XCALLOC1 (FeatureList); + + xfseek (fp, offset, SEEK_SET, "otfMakeFeatureList"); + + featureList->featureCount = ttfGetUSHORT (fp); + if (featureList->featureCount) { + featureList->featureRecord = XCALLOC (featureList->featureCount, FeatureRecord); + fOffset = XTALLOC (featureList->featureCount, USHORT); + + for (i = 0; i < featureList->featureCount; i++) { + featureList->featureRecord[i].tag = ttfGetULONG (fp); + fOffset[i] = ttfGetUSHORT (fp); + } + + for (i = 0; i < featureList->featureCount; i++) + otfLoadFeatureRecord (fp, &featureList->featureRecord[i], offset + fOffset[i]); + + free (fOffset); + } + + return featureList; +} + +static void +otfPrintFeatureRecord (FILE *fp, FeatureRecordPtr featureRecord) +{ + int i; + + fprintf (fp, "'%s' feature - lookupCount: %d\n", + TagToStr (featureRecord->tag), featureRecord->lookupCount); + fprintf (fp, "\t\tlookupListIndex: %d", featureRecord->lookupListIndex[0]); + for (i = 1; i < featureRecord->lookupCount; i++) + fprintf (fp, i % 8 ? ", %d" : ",\n\t\t\t\t %d", + featureRecord->lookupListIndex[i]); + fprintf (fp, "\n"); + if (featureRecord->featureParams) + fprintf (fp, "\t\tfeatureParams Offset: 0x%04x\n", featureRecord->featureParams); +} + +void +otfPrintFeatureList (FILE *fp, FeatureListPtr featureList) +{ + int i; + + fprintf (fp, " featureCount: %d\n", featureList->featureCount); + + for (i = 0; i < featureList->featureCount; i++) { + fprintf (fp, " %2d. ", i); + otfPrintFeatureRecord (fp, &featureList->featureRecord[i]); + } + fprintf (fp, "\n"); +} + +void +otfFreeFeatureList (FeatureListPtr featureList) +{ + int i; + + if (featureList->featureCount) { + for (i = 0; i < featureList->featureCount; i++) + free (featureList->featureRecord[i].lookupListIndex); + free (featureList->featureRecord); + } + free (featureList); +} + +static void +otfLoadLookupRecord (FILE *fp, LookupRecordPtr lookupRecord, ULONG offset, MakeLookupFunc makeLookup) +{ + int i; + USHORT lookupType; + USHORT *lOffset; + + xfseek (fp, offset, SEEK_SET, "otfLoadLookupRecord"); + + lookupType = ttfGetUSHORT (fp); + lookupRecord->lookupFlag = ttfGetUSHORT (fp); + lookupRecord->subTableCount = ttfGetUSHORT (fp); + lookupRecord->lookup = XCALLOC (lookupRecord->subTableCount, LookupPtr); + lOffset = ttfMakeUSHORT (lookupRecord->subTableCount, fp); + if (lookupRecord->lookupFlag & lookupFlag_UseMarkFilteringSet) + lookupRecord->markFilteringSet = ttfGetUSHORT (fp); + for (i = 0; i < lookupRecord->subTableCount; i++) + lookupRecord->lookup[i] = (*makeLookup) (fp, lookupType, offset + lOffset[i]); + free (lOffset); +} + +LookupListPtr +otfMakeLookupList (FILE *fp, ULONG offset, MakeLookupFunc makeLookup) +{ + int i; + USHORT *lOffset; + LookupListPtr lookupList = XCALLOC1 (LookupList); + + xfseek (fp, offset, SEEK_SET, "otfMakeLookupList"); + + lookupList->lookupCount = ttfGetUSHORT (fp); + if (lookupList->lookupCount) { + lookupList->lookupRecord = XCALLOC (lookupList->lookupCount, LookupRecord); + lOffset = ttfMakeUSHORT (lookupList->lookupCount, fp); + + for (i = 0; i < lookupList->lookupCount; i++) + otfLoadLookupRecord (fp, &lookupList->lookupRecord[i], offset + lOffset[i], makeLookup); + + free (lOffset); + } + + return lookupList; +} + +void +otfPrintLookupList (FILE *fp, LookupListPtr lookupList, PrintLookupFunc printLookup) +{ + int i; + + fprintf (fp, " lookupCount: %d\n", lookupList->lookupCount); + + for (i = 0; i < lookupList->lookupCount; i++) { + int j; + + fprintf (fp, " %2d. lookupType: %d, lookupFlag: 0x%04x", i, + lookupList->lookupRecord[i].lookup[0].otf->lookupType, + lookupList->lookupRecord[i].lookupFlag); + if (lookupList->lookupRecord[i].lookupFlag & lookupFlag_UseMarkFilteringSet) + fprintf (fp, ", markFilteringSet: %d", lookupList->lookupRecord[i].markFilteringSet); + fprintf (fp, "\n\tsubTableCount:\t%d\n", lookupList->lookupRecord[i].subTableCount); + for (j = 0; j < lookupList->lookupRecord[i].subTableCount; j++) { + fprintf (fp, " %2d. lookupFormat: %d", j, + lookupList->lookupRecord[i].lookup[j].otf->lookupFormat); + (*printLookup) (fp, lookupList->lookupRecord[i].lookup[j]); + } + } + fprintf (fp, "\n"); +} + +void +otfFreeLookupList (LookupListPtr lookupList, FreeLookupFunc freeLookup) +{ + int i; + + if (lookupList->lookupCount) { + for (i = 0; i < lookupList->lookupCount; i++) { + int j; + + for (j = 0; j < lookupList->lookupRecord[i].subTableCount; j++) { + (*freeLookup) (lookupList->lookupRecord[i].lookup[j]); + free (lookupList->lookupRecord[i].lookup[j].otf); + } + free (lookupList->lookupRecord[i].lookup); + } + free (lookupList->lookupRecord); + } + free (lookupList); +} + +CoveragePtr +otfMakeCoverage (FILE *fp, ULONG offset) +{ + CoveragePtr coverage; + int i; + USHORT format; + + xfseek (fp, offset, SEEK_SET, "otfMakeCoverage"); + + format = ttfGetUSHORT (fp); + switch (format) + { + case 1: + coverage.coverage1 = XCALLOC1 (Coverage1); + coverage.coverage1->glyphCount = ttfGetUSHORT (fp); + coverage.coverage1->glyphArray = ttfMakeUSHORT (coverage.coverage1->glyphCount, fp); + break; + case 2: + coverage.coverage2 = XCALLOC1 (Coverage2); + coverage.coverage2->rangeCount = ttfGetUSHORT (fp); + coverage.coverage2->rangeRecord = XTALLOC (coverage.coverage2->rangeCount, RangeRecord); + for (i = 0; i < coverage.coverage2->rangeCount; i++) { + coverage.coverage2->rangeRecord[i].start = ttfGetUSHORT (fp); + coverage.coverage2->rangeRecord[i].end = ttfGetUSHORT (fp); + coverage.coverage2->rangeRecord[i].startCoverageIndex = ttfGetUSHORT (fp); + } + break; + default: + ttfError ("Unrecognized coverageFormat\n"); + } + + *coverage.format = format; + return coverage; +} + +void +otfPrintCoverage (FILE *fp, CoveragePtr coverage) +{ + int i; + + fprintf (fp, "Coverage - "); + switch (*coverage.format) + { + case 1: + fprintf (fp, "glyphCount: %d\n\t\t glyphArray: %d", + coverage.coverage1->glyphCount, coverage.coverage1->glyphArray[0]); + for (i = 1; i < coverage.coverage1->glyphCount; i++) + fprintf (fp, i % 8 ? ", %d" : ",\n\t\t\t %d", + coverage.coverage1->glyphArray[i]); + fprintf (fp, "\n"); + break; + case 2: + fprintf (fp, "rangeCount: %d\n", coverage.coverage2->rangeCount); + for (i = 0; i < coverage.coverage2->rangeCount; i++) { + fprintf (fp, "\t %2d. start: %d, end: %d, startCoverageIndex: %d\n", i, + coverage.coverage2->rangeRecord[i].start, + coverage.coverage2->rangeRecord[i].end, + coverage.coverage2->rangeRecord[i].startCoverageIndex); + } + break; + default: + ttfError ("Internal error: otfPrintCoverage\n"); + } +} + +void +otfFreeCoverage (CoveragePtr coverage) +{ + switch (*coverage.format) + { + case 1: + free (coverage.coverage1->glyphArray); + break; + case 2: + free (coverage.coverage2->rangeRecord); + break; + default: + ttfError ("Internal error: otfFreeCoverage\n"); + } + free (coverage.format); +} + +ClassDefPtr +otfMakeClassDef (FILE *fp, ULONG offset) +{ + ClassDefPtr classDef; + int i; + USHORT format; + + xfseek (fp, offset, SEEK_SET, "otfMakeClassDef"); + + format = ttfGetUSHORT (fp); + switch (format) + { + case 1: + classDef.classDef1 = XCALLOC1 (ClassDef1); + classDef.classDef1->startGlyph = ttfGetUSHORT (fp); + classDef.classDef1->glyphCount = ttfGetUSHORT (fp); + classDef.classDef1->classValueArray = ttfMakeUSHORT (classDef.classDef1->glyphCount, fp); + break; + case 2: + classDef.classDef2 = XCALLOC1 (ClassDef2); + classDef.classDef2->classRangeCount = ttfGetUSHORT (fp); + classDef.classDef2->classRangeRecord = XTALLOC (classDef.classDef2->classRangeCount, ClassRangeRecord); + for (i = 0; i < classDef.classDef2->classRangeCount; i++) { + classDef.classDef2->classRangeRecord[i].start = ttfGetUSHORT (fp); + classDef.classDef2->classRangeRecord[i].end = ttfGetUSHORT (fp); + classDef.classDef2->classRangeRecord[i].classValue = ttfGetUSHORT (fp); + } + break; + default: + ttfError ("Unrecognized classDefFormat\n"); + } + + *classDef.format = format; + return classDef; +} + +void +otfPrintClassDef (FILE *fp, ClassDefPtr classDef) +{ + int i; + + switch (*classDef.format) + { + case 1: + fprintf (fp, "startGlyph: %d, glyphCount: %d\n\t\tclassValueArray ", + classDef.classDef1->startGlyph, classDef.classDef1->glyphCount); + for (i = 0; i < classDef.classDef1->glyphCount; i++) + fprintf (fp, i == 0 ? "- %d" : i % 8 ? ", %d" : ",\n\t\t\t\t %d", + classDef.classDef1->classValueArray[i]); + fprintf (fp, "\n"); + break; + case 2: + fprintf (fp, "classRangeCount: %d\n", classDef.classDef2->classRangeCount); + for (i = 0; i < classDef.classDef2->classRangeCount; i++) + fprintf (fp, "\t\t%2d. start: %d, end: %d, classValue: %d\n", i, + classDef.classDef2->classRangeRecord[i].start, + classDef.classDef2->classRangeRecord[i].end, + classDef.classDef2->classRangeRecord[i].classValue); + break; + default: + ttfError ("Internal error: otfPrintClassDef\n"); + } +} + +void +otfFreeClassDef (ClassDefPtr classDef) +{ + switch (*classDef.format) + { + case 1: + free (classDef.classDef1->classValueArray); + break; + case 2: + free (classDef.classDef2->classRangeRecord); + break; + default: + ttfError ("Internal error: otfFreeClassDef\n"); + } + free (classDef.format); +} + +DevicePtr +otfMakeDevice (FILE *fp, ULONG offset) +{ + size_t num; + DevicePtr device; + USHORT startSize, endSize, deltaFormat; + + xfseek (fp, offset, SEEK_SET, "otfMakeDevice"); + + startSize = ttfGetUSHORT (fp); + endSize = ttfGetUSHORT (fp); + deltaFormat = ttfGetUSHORT (fp); + if (deltaFormat < 1 || deltaFormat > 3) + ttfError ("Unrecognized deltaFormat\n"); + num = (endSize - startSize) >> (4 - deltaFormat); + device = (DevicePtr) xcalloc (1, sizeof (Device) + num * sizeof (USHORT)); + device->startSize = startSize; + device->endSize = endSize; + device->deltaFormat = deltaFormat; + ttfReadUSHORT (device->deltaValue, num + 1, fp); + + return device; +} + +void +otfPrintDevice (FILE *fp, DevicePtr device) +{ + int i; + size_t num = (device->endSize - device->startSize) >> (4 - device->deltaFormat); + + fprintf (fp, "startSize = %d, endSize = %d, deltaFormat = %d, deltaValue = 0x", + device->startSize, device->endSize, device->deltaFormat); + for (i = 0; i < num; i++) + fprintf (fp, "%04x", device->deltaValue[i]); + fprintf (fp, "%04x\n", device->deltaValue[num]); +} + +static OtfLookupRecordPtr +makeOtfLookupRecord (USHORT otfCount, FILE *fp) +{ + int i; + OtfLookupRecordPtr otf = XCALLOC (otfCount, OtfLookupRecord); + + for (i = 0; i < otfCount; i++) { + otf[i].sequenceIndex = ttfGetUSHORT (fp); + otf[i].lookupListIndex = ttfGetUSHORT (fp); + } + return otf; +} + +static void +printOtfLookupRecord (FILE * fp, const char *str, USHORT otfCount, OtfLookupRecordPtr otf) +{ + int i; + + fprintf (fp, "\t%sotfCount: %d\n", str, otfCount); + for (i = 0; i < otfCount; i++) + fprintf (fp, "\t%s%2d. sequenceIndex: %d, lookupListIndex: %d\n", + str, i, otf[i].sequenceIndex, otf[i].lookupListIndex); +} + +static void loadOtfRule (OtfRulePtr otfRule, FILE *fp, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "loadOtfRule"); + + otfRule->glyphCount = ttfGetUSHORT (fp); + otfRule->otfCount = ttfGetUSHORT (fp); + otfRule->input = ttfMakeUSHORT (otfRule->glyphCount - 1, fp); + otfRule->otf = makeOtfLookupRecord (otfRule->otfCount, fp); +} + +static void loadOtfRuleSet (OtfRuleSetPtr otfRuleSet, FILE *fp, ULONG offset) +{ + int i; + USHORT *pOffset; + + xfseek (fp, offset, SEEK_SET, "loadOtfRuleSet"); + + otfRuleSet->otfRuleCount = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (otfRuleSet->otfRuleCount, fp); + otfRuleSet->otfRule = XCALLOC (otfRuleSet->otfRuleCount, OtfRule); + for (i = 0; i < otfRuleSet->otfRuleCount; i++) + loadOtfRule (&otfRuleSet->otfRule[i], fp, offset + pOffset[i]); + free (pOffset); +} + +OtfCtx1Ptr makeOTFCtx1 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *pOffset; + OtfCtx1Ptr otf = XCALLOC1 (OtfCtx1); + + cOffset = ttfGetUSHORT (fp); + otf->otfRuleSetCount = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (otf->otfRuleSetCount, fp); + otf->otfRuleSet = XCALLOC (otf->otfRuleSetCount, OtfRuleSet); + otf->coverage = otfMakeCoverage (fp, offset + cOffset); + for (i = 0; i < otf->otfRuleSetCount; i++) + loadOtfRuleSet (&otf->otfRuleSet[i], fp, offset + pOffset[i]); + free (pOffset); + + return otf; +} + +void printOTFCtx1 (FILE *fp, OtfCtx1Ptr otf) +{ + int i; + + fprintf (fp, " - Context Simple\n\t "); + otfPrintCoverage (fp, otf->coverage); + fprintf (fp, "\t otfRuleSetCount: %d\n", otf->otfRuleSetCount); + for (i = 0; i < otf->otfRuleSetCount; i++) { + int j; + + fprintf (fp, "\t %2d. otfRuleCount: %d\n", i, otf->otfRuleSet[i].otfRuleCount); + for (j = 0; j < otf->otfRuleSet[i].otfRuleCount; j++) { + int k; + + fprintf (fp, "\t %2d. glyphtCount: %d ", j, + otf->otfRuleSet[i].otfRule[j].glyphCount); + for (k = 0; k < otf->otfRuleSet[i].otfRule[j].glyphCount - 1; k++) + fprintf (fp, k == 0 ? "- %d" : ", %d", otf->otfRuleSet[i].otfRule[j].input[k]); + fprintf (fp, "\n"); + printOtfLookupRecord (fp, " ", + otf->otfRuleSet[i].otfRule[j].otfCount, + otf->otfRuleSet[i].otfRule[j].otf); + } + } +} + +void freeOTFCtx1 (OtfCtx1Ptr otf) +{ + int i; + + otfFreeCoverage (otf->coverage); + for (i = 0; i < otf->otfRuleSetCount; i++) { + int j; + + for (j = 0; j < otf->otfRuleSet[i].otfRuleCount; j++) { + free (otf->otfRuleSet[i].otfRule[j].input); + free (otf->otfRuleSet[i].otfRule[j].otf); + } + free (otf->otfRuleSet[i].otfRule); + } + free (otf->otfRuleSet); +} + +static void loadOtfClassRule (OtfClassRulePtr otfClassRule, FILE *fp, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "loadOtfClassRule"); + + otfClassRule->glyphCount = ttfGetUSHORT (fp); + otfClassRule->otfCount = ttfGetUSHORT (fp); + otfClassRule->class = ttfMakeUSHORT (otfClassRule->glyphCount - 1, fp); + otfClassRule->otf = makeOtfLookupRecord (otfClassRule->otfCount, fp); +} + +static void loadOtfClassSet (OtfClassSetPtr otfClassSet, FILE *fp, ULONG offset) +{ + int i; + USHORT *pOffset; + + xfseek (fp, offset, SEEK_SET, "loadOtfClassSet"); + + otfClassSet->otfClassRuleCnt = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (otfClassSet->otfClassRuleCnt, fp); + otfClassSet->otfClassRule = XCALLOC (otfClassSet->otfClassRuleCnt, OtfClassRule); + for (i = 0; i < otfClassSet->otfClassRuleCnt; i++) + loadOtfClassRule (&otfClassSet->otfClassRule[i], fp, offset + pOffset[i]); + free (pOffset); +} + +OtfCtx2Ptr makeOTFCtx2 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT clOffset; + USHORT *pOffset; + OtfCtx2Ptr otf = XCALLOC1 (OtfCtx2); + + cOffset = ttfGetUSHORT (fp); + clOffset = ttfGetUSHORT (fp); + otf->otfClassSetCnt = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (otf->otfClassSetCnt, fp); + otf->otfClassSet = XCALLOC (otf->otfClassSetCnt, OtfClassSet); + otf->coverage = otfMakeCoverage (fp, offset + cOffset); + otf->classDef = otfMakeClassDef (fp, offset + clOffset); + for (i = 0; i < otf->otfClassSetCnt; i++) + if (pOffset[i]) + loadOtfClassSet (&otf->otfClassSet[i], fp, offset + pOffset[i]); + free (pOffset); + + return otf; +} + +void printOTFCtx2 (FILE *fp, OtfCtx2Ptr otf) +{ + int i; + + fprintf (fp, " - Context Class-based\n\t "); + otfPrintCoverage (fp, otf->coverage); + fprintf (fp, "\t ClassDef - "); + otfPrintClassDef (fp, otf->classDef); + fprintf (fp, "\t otfClassSetCnt: %d\n", otf->otfClassSetCnt); + for (i = 0; i < otf->otfClassSetCnt; i++) { + int j; + + fprintf (fp, "\t %2d. otfClassRuleCnt: %d\n", i, otf->otfClassSet[i].otfClassRuleCnt); + for (j = 0; j < otf->otfClassSet[i].otfClassRuleCnt; j++) { + int k; + + fprintf (fp, "\t %2d. glyphtCount: %d ", j, + otf->otfClassSet[i].otfClassRule[j].glyphCount); + for (k = 0; k < otf->otfClassSet[i].otfClassRule[j].glyphCount - 1; k++) + fprintf (fp, k == 0 ? "- %d" : ", %d", otf->otfClassSet[i].otfClassRule[j].class[k]); + fprintf (fp, "\n"); + printOtfLookupRecord (fp, " ", + otf->otfClassSet[i].otfClassRule[j].otfCount, + otf->otfClassSet[i].otfClassRule[j].otf); + } + } +} + +void freeOTFCtx2 (OtfCtx2Ptr otf) +{ + int i; + + otfFreeCoverage (otf->coverage); + otfFreeClassDef (otf->classDef); + for (i = 0; i < otf->otfClassSetCnt; i++) { + int j; + + for (j = 0; j < otf->otfClassSet[i].otfClassRuleCnt; j++) { + free (otf->otfClassSet[i].otfClassRule[j].class); + free (otf->otfClassSet[i].otfClassRule[j].otf); + } + free (otf->otfClassSet[i].otfClassRule); + } + free (otf->otfClassSet); +} + +OtfCtx3Ptr makeOTFCtx3 (FILE *fp, ULONG offset) +{ + int i; + USHORT *gOffset; + OtfCtx3Ptr otf = XCALLOC1 (OtfCtx3); + + otf->glyphCount = ttfGetUSHORT (fp); + otf->otfCount = ttfGetUSHORT (fp); + gOffset = ttfMakeUSHORT (otf->glyphCount, fp); + otf->otf = makeOtfLookupRecord (otf->otfCount, fp); + otf->glyphs = XCALLOC (otf->glyphCount, CoveragePtr); + for (i = 0; i < otf->glyphCount; i++) + otf->glyphs[i] = otfMakeCoverage (fp, offset + gOffset[i]); + free (gOffset); + + return otf; +} + +void printOTFCtx3 (FILE *fp, OtfCtx3Ptr otf) +{ + int i; + + fprintf (fp, " - Context Coverage-based\n"); + fprintf (fp, "\t glyphCount: %d\n", otf->glyphCount); + for (i = 0; i < otf->glyphCount; i++) { + fprintf (fp, "\t %2d. ", i); + otfPrintCoverage (fp, otf->glyphs[i]); + } + printOtfLookupRecord (fp, " ", otf->otfCount, otf->otf); +} + +void freeOTFCtx3 (OtfCtx3Ptr otf) +{ + int i; + + for (i = 0; i < otf->glyphCount; i++) + otfFreeCoverage (otf->glyphs[i]); + free (otf->glyphs); + free (otf->otf); +} + +static void +loadChainOtfRule (ChainOtfRulePtr chainOtfRule, FILE *fp, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "loadChainOtfRule"); + + chainOtfRule->backtrackGlyphCount = ttfGetUSHORT (fp); + chainOtfRule->backtrack = ttfMakeUSHORT (chainOtfRule->backtrackGlyphCount, fp); + chainOtfRule->inputGlyphCount = ttfGetUSHORT (fp); + chainOtfRule->input = ttfMakeUSHORT (chainOtfRule->inputGlyphCount - 1, fp); + chainOtfRule->lookaheadGlyphCount = ttfGetUSHORT (fp); + chainOtfRule->lookahead = ttfMakeUSHORT (chainOtfRule->lookaheadGlyphCount, fp); + chainOtfRule->otfCount = ttfGetUSHORT (fp); + chainOtfRule->otf = makeOtfLookupRecord (chainOtfRule->otfCount, fp); +} + +static void +loadChainOtfRuleSet (ChainOtfRuleSetPtr chainOtfRuleSet, FILE *fp, ULONG offset) +{ + int i; + USHORT *pOffset; + + xfseek (fp, offset, SEEK_SET, "loadChainOtfRuleSet"); + + chainOtfRuleSet->chainOtfRuleCount = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (chainOtfRuleSet->chainOtfRuleCount, fp); + chainOtfRuleSet->chainOtfRule = XCALLOC (chainOtfRuleSet->chainOtfRuleCount, ChainOtfRule); + for (i = 0; i < chainOtfRuleSet->chainOtfRuleCount; i++) + loadChainOtfRule (&chainOtfRuleSet->chainOtfRule[i], fp, offset + pOffset[i]); + free (pOffset); +} + +OtfChn1Ptr makeOTFChn1 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT *pOffset; + OtfChn1Ptr otf = XCALLOC1 (OtfChn1); + + cOffset = ttfGetUSHORT (fp); + otf->chainOtfRuleSetCount = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (otf->chainOtfRuleSetCount, fp); + otf->coverage = otfMakeCoverage (fp, offset + cOffset); + otf->chainOtfRuleSet = XCALLOC (otf->chainOtfRuleSetCount, ChainOtfRuleSet); + for (i = 0; i < otf->chainOtfRuleSetCount; i++) + loadChainOtfRuleSet (&otf->chainOtfRuleSet[i], fp, offset + pOffset[i]); + free (pOffset); + + return otf; +} + +void printOTFChn1 (FILE *fp, OtfChn1Ptr otf) +{ + int i; + + fprintf (fp, " - Chained Context Simple\n\t "); + otfPrintCoverage (fp, otf->coverage); + fprintf (fp, "\t chainOtfRuleSetCount: %d\n", otf->chainOtfRuleSetCount); + for (i = 0; i < otf->chainOtfRuleSetCount; i++) { + int j; + + fprintf (fp, "\t %2d. chainOtfRuleCount: %d\n", i, + otf->chainOtfRuleSet[i].chainOtfRuleCount); + for (j = 0; j < otf->chainOtfRuleSet[i].chainOtfRuleCount; j++) { + int k; + + fprintf (fp, "\t %2d. backtrackGlyphCount: %d ", j, + otf->chainOtfRuleSet[i].chainOtfRule[j].backtrackGlyphCount); + for (k = 0; k < otf->chainOtfRuleSet[i].chainOtfRule[j].backtrackGlyphCount; k++) + fprintf (fp, k == 0 ? "- %d" : ", %d", otf->chainOtfRuleSet[i].chainOtfRule[j].backtrack[k]); + fprintf (fp, "\n\t\tinputGlyphCount: %d ", + otf->chainOtfRuleSet[i].chainOtfRule[j].inputGlyphCount); + for (k = 0; k < otf->chainOtfRuleSet[i].chainOtfRule[j].inputGlyphCount; k++) + fprintf (fp, k == 0 ? "- %d" : ", %d", otf->chainOtfRuleSet[i].chainOtfRule[j].input[k]); + fprintf (fp, "\n\t\tlookaheadGlyphCount: %d ", + otf->chainOtfRuleSet[i].chainOtfRule[j].lookaheadGlyphCount); + for (k = 0; k < otf->chainOtfRuleSet[i].chainOtfRule[j].lookaheadGlyphCount; k++) + fprintf (fp, k == 0 ? "- %d" : ", %d", otf->chainOtfRuleSet[i].chainOtfRule[j].lookahead[k]); + fprintf (fp, "\n"); + printOtfLookupRecord (fp, " ", + otf->chainOtfRuleSet[i].chainOtfRule[j].otfCount, + otf->chainOtfRuleSet[i].chainOtfRule[j].otf); + } + } +} + +void freeOTFChn1 (OtfChn1Ptr otf) +{ + int i; + + otfFreeCoverage (otf->coverage); + for (i = 0; i < otf->chainOtfRuleSetCount; i++) { + int j; + + for (j = 0; j < otf->chainOtfRuleSet[i].chainOtfRuleCount; j++) { + free (otf->chainOtfRuleSet[i].chainOtfRule[j].backtrack); + free (otf->chainOtfRuleSet[i].chainOtfRule[j].input); + free (otf->chainOtfRuleSet[i].chainOtfRule[j].lookahead); + free (otf->chainOtfRuleSet[i].chainOtfRule[j].otf); + } + free (otf->chainOtfRuleSet[i].chainOtfRule); + } + free (otf->chainOtfRuleSet); +} + +static void +loadChainOtfClassRule (ChainOtfClassRulePtr chainOtfClassRule, FILE *fp, ULONG offset) +{ + xfseek (fp, offset, SEEK_SET, "loadChainOtfClassRule"); + + chainOtfClassRule->backtrackGlyphCount = ttfGetUSHORT (fp); + chainOtfClassRule->backtrack = ttfMakeUSHORT (chainOtfClassRule->backtrackGlyphCount, fp); + chainOtfClassRule->inputGlyphCount = ttfGetUSHORT (fp); + chainOtfClassRule->input = ttfMakeUSHORT (chainOtfClassRule->inputGlyphCount - 1, fp); + chainOtfClassRule->lookaheadGlyphCount = ttfGetUSHORT (fp); + chainOtfClassRule->lookahead = ttfMakeUSHORT (chainOtfClassRule->lookaheadGlyphCount, fp); + chainOtfClassRule->otfCount = ttfGetUSHORT (fp); + chainOtfClassRule->otf = makeOtfLookupRecord (chainOtfClassRule->otfCount, fp); +} + +static void +loadChainOtfClassSet (ChainOtfClassSetPtr chainOtfClassSet, FILE *fp, ULONG offset) +{ + int i; + USHORT *pOffset; + + xfseek (fp, offset, SEEK_SET, "loadChainOtfClassSet"); + + chainOtfClassSet->chainOtfClassRuleCnt = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (chainOtfClassSet->chainOtfClassRuleCnt, fp); + chainOtfClassSet->chainOtfClassRule = XCALLOC (chainOtfClassSet->chainOtfClassRuleCnt, ChainOtfClassRule); + for (i = 0; i < chainOtfClassSet->chainOtfClassRuleCnt; i++) + loadChainOtfClassRule (&chainOtfClassSet->chainOtfClassRule[i], fp, offset + pOffset[i]); + free (pOffset); +} + +OtfChn2Ptr makeOTFChn2 (FILE *fp, ULONG offset) +{ + int i; + USHORT cOffset; + USHORT bOffset, iOffset, lOffset; + USHORT *pOffset; + OtfChn2Ptr otf = XCALLOC1 (OtfChn2); + + cOffset = ttfGetUSHORT (fp); + bOffset = ttfGetUSHORT (fp); + iOffset = ttfGetUSHORT (fp); + lOffset = ttfGetUSHORT (fp); + otf->chainOtfClassSetCnt = ttfGetUSHORT (fp); + pOffset = ttfMakeUSHORT (otf->chainOtfClassSetCnt, fp); + otf->coverage = otfMakeCoverage (fp, offset + cOffset); + otf->backtrackClassDef = otfMakeClassDef (fp, offset + bOffset); + otf->inputClassDef = otfMakeClassDef (fp, offset + iOffset); + otf->lookaheadClassDef = otfMakeClassDef (fp, offset + lOffset); + otf->chainOtfClassSet = XCALLOC (otf->chainOtfClassSetCnt, ChainOtfClassSet); + for (i = 0; i < otf->chainOtfClassSetCnt; i++) + if (pOffset[i]) + loadChainOtfClassSet (&otf->chainOtfClassSet[i], fp, offset + pOffset[i]); + free (pOffset); + + return otf; +} + +void printOTFChn2 (FILE *fp, OtfChn2Ptr otf) +{ + int i; + + fprintf (fp, " - Chained Context Class-based\n\t "); + otfPrintCoverage (fp, otf->coverage); + fprintf (fp, "\t backtrackClassDef - "); + otfPrintClassDef (fp, otf->backtrackClassDef); + fprintf (fp, "\t inputClassDef - "); + otfPrintClassDef (fp, otf->inputClassDef); + fprintf (fp, "\t lookaheadClassDef - "); + otfPrintClassDef (fp, otf->lookaheadClassDef); + fprintf (fp, "\t chainOtfClassSetCnt: %d\n", otf->chainOtfClassSetCnt); + for (i = 0; i < otf->chainOtfClassSetCnt; i++) { + int j; + + fprintf (fp, "\t %2d. chainOtfClassRuleCnt: %d\n", i, + otf->chainOtfClassSet[i].chainOtfClassRuleCnt); + for (j = 0; j < otf->chainOtfClassSet[i].chainOtfClassRuleCnt; j++) { + int k; + + fprintf (fp, "\t %2d. backtrackGlyphCount: %2d ", j, + otf->chainOtfClassSet[i].chainOtfClassRule[j].backtrackGlyphCount); + for (k = 0; k < otf->chainOtfClassSet[i].chainOtfClassRule[j].backtrackGlyphCount; k++) + fprintf (fp, k == 0 ? "- %d" : k % 8 ? ", %d" : ",\n\t\t\t\t\t %d", + otf->chainOtfClassSet[i].chainOtfClassRule[j].backtrack[k]); + fprintf (fp, "\n\t\tinputGlyphCount: %2d ", + otf->chainOtfClassSet[i].chainOtfClassRule[j].inputGlyphCount); + for (k = 0; k < otf->chainOtfClassSet[i].chainOtfClassRule[j].inputGlyphCount; k++) + fprintf (fp, k == 0 ? "- %d" : k % 8 ? ", %d" : ",\n\t\t\t\t %d", + otf->chainOtfClassSet[i].chainOtfClassRule[j].input[k]); + fprintf (fp, "\n\t\tlookaheadGlyphCount: %2d ", + otf->chainOtfClassSet[i].chainOtfClassRule[j].lookaheadGlyphCount); + for (k = 0; k < otf->chainOtfClassSet[i].chainOtfClassRule[j].lookaheadGlyphCount; k++) + fprintf (fp, k == 0 ? "- %d" : k % 8 ? ", %d" : ",\n\t\t\t\t\t %d", + otf->chainOtfClassSet[i].chainOtfClassRule[j].lookahead[k]); + fprintf (fp, "\n"); + printOtfLookupRecord (fp, " ", + otf->chainOtfClassSet[i].chainOtfClassRule[j].otfCount, + otf->chainOtfClassSet[i].chainOtfClassRule[j].otf); + } + } +} + +void freeOTFChn2 (OtfChn2Ptr otf) +{ + int i; + + otfFreeCoverage (otf->coverage); + otfFreeClassDef (otf->backtrackClassDef); + otfFreeClassDef (otf->inputClassDef); + otfFreeClassDef (otf->lookaheadClassDef); + for (i = 0; i < otf->chainOtfClassSetCnt; i++) { + int j; + + for (j = 0; j < otf->chainOtfClassSet[i].chainOtfClassRuleCnt; j++) { + free (otf->chainOtfClassSet[i].chainOtfClassRule[j].backtrack); + free (otf->chainOtfClassSet[i].chainOtfClassRule[j].input); + free (otf->chainOtfClassSet[i].chainOtfClassRule[j].lookahead); + free (otf->chainOtfClassSet[i].chainOtfClassRule[j].otf); + } + free (otf->chainOtfClassSet[i].chainOtfClassRule); + } + free (otf->chainOtfClassSet); +} + +OtfChn3Ptr makeOTFChn3 (FILE *fp, ULONG offset) +{ + int i; + USHORT *bOffset, *iOffset, *lOffset; + OtfChn3Ptr otf = XCALLOC1 (OtfChn3); + + otf->backtrackGlyphCount = ttfGetUSHORT (fp); + bOffset = ttfMakeUSHORT (otf->backtrackGlyphCount, fp); + otf->inputGlyphCount = ttfGetUSHORT (fp); + iOffset = ttfMakeUSHORT (otf->inputGlyphCount, fp); + otf->lookaheadGlyphCount = ttfGetUSHORT (fp); + lOffset = ttfMakeUSHORT (otf->lookaheadGlyphCount, fp); + otf->otfCount = ttfGetUSHORT (fp); + otf->otf = makeOtfLookupRecord (otf->otfCount, fp); + otf->backtrack = XCALLOC (otf->backtrackGlyphCount, CoveragePtr); + for (i = 0; i < otf->backtrackGlyphCount; i++) + otf->backtrack[i] = otfMakeCoverage (fp, offset + bOffset[i]); + free (bOffset); + otf->input = XCALLOC (otf->inputGlyphCount, CoveragePtr); + for (i = 0; i < otf->inputGlyphCount; i++) + otf->input[i] = otfMakeCoverage (fp, offset + iOffset[i]); + free (iOffset); + otf->lookahead = XCALLOC (otf->lookaheadGlyphCount, CoveragePtr); + for (i = 0; i < otf->lookaheadGlyphCount; i++) + otf->lookahead[i] = otfMakeCoverage (fp, offset + lOffset[i]); + free (lOffset); + + return otf; +} + +void printOTFChn3 (FILE *fp, OtfChn3Ptr otf) +{ + int i; + + fprintf (fp, " - Chained Context Coverage-based\n"); + fprintf (fp, "\t backtrackGlyphCount: %d\n", otf->backtrackGlyphCount); + for (i = 0; i < otf->backtrackGlyphCount; i++) { + fprintf (fp, "\t %2d. backtrack", i); + otfPrintCoverage (fp, otf->backtrack[i]); + } + fprintf (fp, "\t inputGlyphCount: %d\n", otf->inputGlyphCount); + for (i = 0; i < otf->inputGlyphCount; i++) { + fprintf (fp, "\t %2d. input", i); + otfPrintCoverage (fp, otf->input[i]); + } + fprintf (fp, "\t lookaheadGlyphCount: %d\n", otf->lookaheadGlyphCount); + for (i = 0; i < otf->lookaheadGlyphCount; i++) { + fprintf (fp, "\t %2d. lookahead", i); + otfPrintCoverage (fp, otf->lookahead[i]); + } + printOtfLookupRecord (fp, " ", otf->otfCount, otf->otf); +} + +void freeOTFChn3 (OtfChn3Ptr otf) +{ + int i; + + for (i = 0; i < otf->backtrackGlyphCount; i++) + otfFreeCoverage (otf->backtrack[i]); + free (otf->backtrack); + for (i = 0; i < otf->inputGlyphCount; i++) + otfFreeCoverage (otf->input[i]); + free (otf->input); + for (i = 0; i < otf->lookaheadGlyphCount; i++) + otfFreeCoverage (otf->lookahead[i]); + free (otf->lookahead); + free (otf->otf); +} + diff --git a/Build/source/texk/ttfdump/libttf/ttfutil.c b/Build/source/texk/ttfdump/libttf/ttfutil.c index 96a1bd3eb53..a31478002a5 100644 --- a/Build/source/texk/ttfdump/libttf/ttfutil.c +++ b/Build/source/texk/ttfdump/libttf/ttfutil.c @@ -32,12 +32,22 @@ void ttfError(const char * msg) } /* Functions copied or adapted from kpathsea. */ +long +xftell (FILE *fp, const char *funcname) +{ + long where = ftell (fp); + + if (where < 0) + FATAL_PERROR(funcname); + + return where; +} + void xfseek (FILE *f, long offset, int wherefrom, const char *funcname) { - if (fseek (f, offset, wherefrom) < 0) { + if (fseek (f, offset, wherefrom) < 0) FATAL_PERROR(funcname); - } } void * @@ -55,7 +65,7 @@ xmalloc (size_t size) } void * -xcalloc (size_t nelem, size_t elsize) +xcalloc (size_t nelem, size_t elsize) { void *new_mem = (void*)calloc(nelem ? nelem : 1, elsize ? elsize : 1); diff --git a/Build/source/texk/ttfdump/src/ttfdump.c b/Build/source/texk/ttfdump/src/ttfdump.c index d603483dc28..0726b3b0e5f 100644 --- a/Build/source/texk/ttfdump/src/ttfdump.c +++ b/Build/source/texk/ttfdump/src/ttfdump.c @@ -52,6 +52,9 @@ static void print_vdmx(FILE *out); static void print_vhea(FILE *out); static void print_vmtx(FILE *out); +static void print_gpos(FILE *out); +static void print_gsub(FILE *out); + static void usage (void); @@ -157,6 +160,9 @@ main(int argc, char *argv[]) print_offset(dp_file); print_dir(dp_file); + if (font->loca == NULL) + glyphnum = NO_GLYF; + if (tablename == NULL) { /* no table specified */ @@ -236,6 +242,10 @@ print_table(FILE *out, char *tablename) print_vhea(out); if (!strcmp(tablename, "vmtx")) print_vmtx(out); + if (!strcmp(tablename, "GPOS")) + print_gpos(out); + if (!strcmp(tablename, "GSUB")) + print_gsub(out); } @@ -262,6 +272,10 @@ print_all_tables(FILE *dp_file) print_vdmx(dp_file); print_vhea(dp_file); print_vmtx(dp_file); + + /* Additional OpenType Tables */ + print_gpos(dp_file); + print_gsub(dp_file); } @@ -270,7 +284,6 @@ print_ttc(TTCHeaderPtr ttc, FILE *out) { int i, b[2]; - FixedSplit(ttc->version, b); fprintf(out, "TrueType Collection Header\n"); @@ -295,9 +308,17 @@ print_prologue(FILE *out) static void print_offset(FILE *out) { + int b[2]; + + FixedSplit(font->version, b); + fprintf(out, "Offset Table\n"); fprintf(out, "------------\n"); - fprintf(out, "\t sfnt version:\n"); + fprintf(out, "\t sfnt version: "); + if (b[1] & 0xff00) + fprintf(out, "'%s'\n", TagToStr (font->version)); + else + fprintf(out, "\t\t %d.%d\n", b[1], b[0]); fprintf(out, "\t number of tables: %d\n", font->numTables); } @@ -505,6 +526,22 @@ print_vmtx(FILE *out) static void +print_gpos(FILE *out) +{ + if (font->gpos != NULL) + ttfPrintGPOS(out, font->gpos); +} + + +static void +print_gsub(FILE *out) +{ + if (font->gsub != NULL) + ttfPrintGSUB(out, font->gsub); +} + + +static void usage(void) { fprintf(stderr, "Usage: ttfdump ttfname dumpname [options]\n"); diff --git a/Build/source/texk/ttfdump/tests/ttfdump.glyf b/Build/source/texk/ttfdump/tests/ttfdump.glyf index be977900774..b2754800ff4 100644 --- a/Build/source/texk/ttfdump/tests/ttfdump.glyf +++ b/Build/source/texk/ttfdump/tests/ttfdump.glyf @@ -1,29 +1,29 @@ True Type Font File Dumper: v 0.5.5 -Copyright 1996-1998 ollie@ms1.hinet.net +Copyright 1996-1998 ollie@ms1.hinet.net Dumping File:FonetikaDaniaIwonaeRegular.ttf -Offset Table ------------- - sfnt version: +Offset Table +------------ + sfnt version: 1.0 number of tables: 14 - 0. 'GPOS' - checksum = 0xd7f8e75c, offset = 0x00001cd0, len = 80 - 1. 'GSUB' - checksum = 0x6c91748f, offset = 0x00001cb0, len = 32 - 2. 'OS/2' - checksum = 0x55d6fec3, offset = 0x00000168, len = 86 - 3. 'cmap' - checksum = 0x987c2758, offset = 0x0000028c, len = 482 - 4. 'cvt ' - checksum = 0x00210279, offset = 0x00000470, len = 4 - 5. 'gasp' - checksum = 0xffff0003, offset = 0x00001ca8, len = 8 - 6. 'glyf' - checksum = 0xd071d50c, offset = 0x000004dc, len = 4946 - 7. 'head' - checksum = 0xe43df9fb, offset = 0x000000ec, len = 54 - 8. 'hhea' - checksum = 0x05e9014f, offset = 0x00000124, len = 36 - 9. 'hmtx' - checksum = 0x4ca30981, offset = 0x000001c0, len = 202 - 10. 'loca' - checksum = 0x6c437107, offset = 0x00000474, len = 104 - 11. 'maxp' - checksum = 0x0079007b, offset = 0x00000148, len = 32 - 12. 'name' - checksum = 0x31984665, offset = 0x00001830, len = 1002 - 13. 'post' - checksum = 0x0aef76ec, offset = 0x00001c1c, len = 140 + 0. 'GPOS' - checksum = 0xd7f8e75c, offset = 0x00001cd0, len = 80 + 1. 'GSUB' - checksum = 0x6c91748f, offset = 0x00001cb0, len = 32 + 2. 'OS/2' - checksum = 0x55d6fec3, offset = 0x00000168, len = 86 + 3. 'cmap' - checksum = 0x987c2758, offset = 0x0000028c, len = 482 + 4. 'cvt ' - checksum = 0x00210279, offset = 0x00000470, len = 4 + 5. 'gasp' - checksum = 0xffff0003, offset = 0x00001ca8, len = 8 + 6. 'glyf' - checksum = 0xd071d50c, offset = 0x000004dc, len = 4946 + 7. 'head' - checksum = 0xe43df9fb, offset = 0x000000ec, len = 54 + 8. 'hhea' - checksum = 0x05e9014f, offset = 0x00000124, len = 36 + 9. 'hmtx' - checksum = 0x4ca30981, offset = 0x000001c0, len = 202 + 10. 'loca' - checksum = 0x6c437107, offset = 0x00000474, len = 104 + 11. 'maxp' - checksum = 0x0079007b, offset = 0x00000148, len = 32 + 12. 'name' - checksum = 0x31984665, offset = 0x00001830, len = 1002 + 13. 'post' - checksum = 0x0aef76ec, offset = 0x00001c1c, len = 140 Glyph 1. - numberOfContours: 2 + numberOfContours: 2 xMin: 33 yMin: 0 xMax: 366 @@ -38,14 +38,14 @@ Glyph 1. Flags ----- - 0: YDual XDual X-Short On - 1: XDual On - 2: YDual On - 3: XDual On - 4: YDual Y-Short On - 5: YDual On - 6: XDual On - 7: YDual On + 0: YDual XDual X-Short On + 1: XDual On + 2: YDual On + 3: XDual On + 4: YDual Y-Short On + 5: YDual On + 6: XDual On + 7: YDual On Coordinates ----------- diff --git a/Build/source/texk/ttfdump/tests/ttfdump.gpos b/Build/source/texk/ttfdump/tests/ttfdump.gpos new file mode 100644 index 00000000000..9a07bda4a02 --- /dev/null +++ b/Build/source/texk/ttfdump/tests/ttfdump.gpos @@ -0,0 +1,47 @@ +True Type Font File Dumper: v 0.5.5 +Copyright 1996-1998 ollie@ms1.hinet.net +Dumping File:FonetikaDaniaIwonaeRegular.ttf + + +Offset Table +------------ + sfnt version: 1.0 + number of tables: 14 + 0. 'GPOS' - checksum = 0xd7f8e75c, offset = 0x00001cd0, len = 80 + 1. 'GSUB' - checksum = 0x6c91748f, offset = 0x00001cb0, len = 32 + 2. 'OS/2' - checksum = 0x55d6fec3, offset = 0x00000168, len = 86 + 3. 'cmap' - checksum = 0x987c2758, offset = 0x0000028c, len = 482 + 4. 'cvt ' - checksum = 0x00210279, offset = 0x00000470, len = 4 + 5. 'gasp' - checksum = 0xffff0003, offset = 0x00001ca8, len = 8 + 6. 'glyf' - checksum = 0xd071d50c, offset = 0x000004dc, len = 4946 + 7. 'head' - checksum = 0xe43df9fb, offset = 0x000000ec, len = 54 + 8. 'hhea' - checksum = 0x05e9014f, offset = 0x00000124, len = 36 + 9. 'hmtx' - checksum = 0x4ca30981, offset = 0x000001c0, len = 202 + 10. 'loca' - checksum = 0x6c437107, offset = 0x00000474, len = 104 + 11. 'maxp' - checksum = 0x0079007b, offset = 0x00000148, len = 32 + 12. 'name' - checksum = 0x31984665, offset = 0x00001830, len = 1002 + 13. 'post' - checksum = 0x0aef76ec, offset = 0x00001c1c, len = 140 + +'GPOS' Table - Glyph Positioning Data +------------------------------------- + 'GPOS' Version: 1.0 + scriptCount: 1 + 0. 'latn' script - langSysCount: 0 + default lang - featureCount: 1 + featureIndex: 0 + + featureCount: 1 + 0. 'kern' feature - lookupCount: 1 + lookupListIndex: 0 + + lookupCount: 1 + 0. lookupType: 2, lookupFlag: 0x0000 + subTableCount: 1 + 0. lookupFormat: 1 - Pair Adjustment List + Coverage - glyphCount: 1 + glyphArray: 34 + valueFormat1: 0x0004, valueFormat2: 0x0000, pairSetCount: 1 + 0. pairValueCount: 1 + 0. secondGlyph: 14 + value1: XAdvance = -33 + diff --git a/Build/source/texk/ttfdump/tests/ttfdump.gsub b/Build/source/texk/ttfdump/tests/ttfdump.gsub new file mode 100644 index 00000000000..574556947f6 --- /dev/null +++ b/Build/source/texk/ttfdump/tests/ttfdump.gsub @@ -0,0 +1,35 @@ +True Type Font File Dumper: v 0.5.5 +Copyright 1996-1998 ollie@ms1.hinet.net +Dumping File:FonetikaDaniaIwonaeRegular.ttf + + +Offset Table +------------ + sfnt version: 1.0 + number of tables: 14 + 0. 'GPOS' - checksum = 0xd7f8e75c, offset = 0x00001cd0, len = 80 + 1. 'GSUB' - checksum = 0x6c91748f, offset = 0x00001cb0, len = 32 + 2. 'OS/2' - checksum = 0x55d6fec3, offset = 0x00000168, len = 86 + 3. 'cmap' - checksum = 0x987c2758, offset = 0x0000028c, len = 482 + 4. 'cvt ' - checksum = 0x00210279, offset = 0x00000470, len = 4 + 5. 'gasp' - checksum = 0xffff0003, offset = 0x00001ca8, len = 8 + 6. 'glyf' - checksum = 0xd071d50c, offset = 0x000004dc, len = 4946 + 7. 'head' - checksum = 0xe43df9fb, offset = 0x000000ec, len = 54 + 8. 'hhea' - checksum = 0x05e9014f, offset = 0x00000124, len = 36 + 9. 'hmtx' - checksum = 0x4ca30981, offset = 0x000001c0, len = 202 + 10. 'loca' - checksum = 0x6c437107, offset = 0x00000474, len = 104 + 11. 'maxp' - checksum = 0x0079007b, offset = 0x00000148, len = 32 + 12. 'name' - checksum = 0x31984665, offset = 0x00001830, len = 1002 + 13. 'post' - checksum = 0x0aef76ec, offset = 0x00001c1c, len = 140 + +'GSUB' Table - Glyph Substitution Data +-------------------------------------- + 'GSUB' Version: 1.0 + scriptCount: 1 + 0. 'latn' script - langSysCount: 0 + default lang - featureCount: 0 + + featureCount: 0 + + lookupCount: 0 + diff --git a/Build/source/texk/ttfdump/tests/ttfdump.head b/Build/source/texk/ttfdump/tests/ttfdump.head index 4e626afd6f1..d960f69b4c2 100644 --- a/Build/source/texk/ttfdump/tests/ttfdump.head +++ b/Build/source/texk/ttfdump/tests/ttfdump.head @@ -1,37 +1,37 @@ True Type Font File Dumper: v 0.5.5 -Copyright 1996-1998 ollie@ms1.hinet.net +Copyright 1996-1998 ollie@ms1.hinet.net Dumping File:FonetikaDaniaIwonaeRegular.ttf -Offset Table ------------- - sfnt version: +Offset Table +------------ + sfnt version: 1.0 number of tables: 14 - 0. 'GPOS' - checksum = 0xd7f8e75c, offset = 0x00001cd0, len = 80 - 1. 'GSUB' - checksum = 0x6c91748f, offset = 0x00001cb0, len = 32 - 2. 'OS/2' - checksum = 0x55d6fec3, offset = 0x00000168, len = 86 - 3. 'cmap' - checksum = 0x987c2758, offset = 0x0000028c, len = 482 - 4. 'cvt ' - checksum = 0x00210279, offset = 0x00000470, len = 4 - 5. 'gasp' - checksum = 0xffff0003, offset = 0x00001ca8, len = 8 - 6. 'glyf' - checksum = 0xd071d50c, offset = 0x000004dc, len = 4946 - 7. 'head' - checksum = 0xe43df9fb, offset = 0x000000ec, len = 54 - 8. 'hhea' - checksum = 0x05e9014f, offset = 0x00000124, len = 36 - 9. 'hmtx' - checksum = 0x4ca30981, offset = 0x000001c0, len = 202 - 10. 'loca' - checksum = 0x6c437107, offset = 0x00000474, len = 104 - 11. 'maxp' - checksum = 0x0079007b, offset = 0x00000148, len = 32 - 12. 'name' - checksum = 0x31984665, offset = 0x00001830, len = 1002 - 13. 'post' - checksum = 0x0aef76ec, offset = 0x00001c1c, len = 140 + 0. 'GPOS' - checksum = 0xd7f8e75c, offset = 0x00001cd0, len = 80 + 1. 'GSUB' - checksum = 0x6c91748f, offset = 0x00001cb0, len = 32 + 2. 'OS/2' - checksum = 0x55d6fec3, offset = 0x00000168, len = 86 + 3. 'cmap' - checksum = 0x987c2758, offset = 0x0000028c, len = 482 + 4. 'cvt ' - checksum = 0x00210279, offset = 0x00000470, len = 4 + 5. 'gasp' - checksum = 0xffff0003, offset = 0x00001ca8, len = 8 + 6. 'glyf' - checksum = 0xd071d50c, offset = 0x000004dc, len = 4946 + 7. 'head' - checksum = 0xe43df9fb, offset = 0x000000ec, len = 54 + 8. 'hhea' - checksum = 0x05e9014f, offset = 0x00000124, len = 36 + 9. 'hmtx' - checksum = 0x4ca30981, offset = 0x000001c0, len = 202 + 10. 'loca' - checksum = 0x6c437107, offset = 0x00000474, len = 104 + 11. 'maxp' - checksum = 0x0079007b, offset = 0x00000148, len = 32 + 12. 'name' - checksum = 0x31984665, offset = 0x00001830, len = 1002 + 13. 'post' - checksum = 0x0aef76ec, offset = 0x00001c1c, len = 140 'head' Table - Font Header -------------------------- - 'head' version: 1. 0 - fontReversion: 1. 0 + 'head' version: 1.0 + fontReversion: 1.0 checkSumAdjustment: 0x851d4906 magicNumber: 0x5f0f3cf5 flags: 0x000b unitsPerEm: 1000 - created: - modified: + created: 0x00000000c1405b91 + modified: 0x00000000c1405b91 xMin: -63 yMin: -250 xMax: 733 diff --git a/Build/source/texk/ttfdump/tests/ttfdump.test b/Build/source/texk/ttfdump/tests/ttfdump.test index deddc589804..0196bea97a1 100755 --- a/Build/source/texk/ttfdump/tests/ttfdump.test +++ b/Build/source/texk/ttfdump/tests/ttfdump.test @@ -3,12 +3,32 @@ # Copyright (C) 2011 Peter Breitenlohner <tex-live@tug.org> # You may freely use, modify and/or distribute this file. -rm -rf FonetikaDaniaIwonaeRegular.ttf ttfdump.glyf ttfdump.head +failed= + +rm -rf FonetikaDaniaIwonaeRegular.ttf ttftest.* cp $srcdir/tests/FonetikaDaniaIwonaeRegular.ttf . -./ttfdump -t head -o ttfdump.head FonetikaDaniaIwonaeRegular.ttf || exit 1 -diff -b $srcdir/tests/ttfdump.head ttfdump.head || exit 1 +./ttfdump -t glyf -g 1 -o ttftest.glyf FonetikaDaniaIwonaeRegular.ttf \ + && diff -b $srcdir/tests/ttfdump.glyf ttftest.glyf \ + && echo "ttfdump.glyf tests OK" \ + || failed="$failed ttfdump.glyf" + +./ttfdump -t GPOS -o ttftest.gpos FonetikaDaniaIwonaeRegular.ttf \ + && diff -b $srcdir/tests/ttfdump.gpos ttftest.gpos \ + && echo "ttfdump.gpos tests OK" \ + || failed="$failed ttfdump.gpos" + +./ttfdump -t GSUB -o ttftest.gsub FonetikaDaniaIwonaeRegular.ttf \ + && diff -b $srcdir/tests/ttfdump.gsub ttftest.gsub \ + && echo "ttfdump.gsub tests OK" \ + || failed="$failed ttfdump.gsub" + +./ttfdump -t head -o ttftest.head FonetikaDaniaIwonaeRegular.ttf \ + && diff -b $srcdir/tests/ttfdump.head ttftest.head \ + && echo "ttfdump.head tests OK" \ + || failed="$failed ttfdump.head" -./ttfdump -t glyf -g 1 -o ttfdump.glyf FonetikaDaniaIwonaeRegular.ttf || exit 1 -diff -b $srcdir/tests/ttfdump.glyf ttfdump.glyf || exit 1 +test -z "$failed" && exit 0 +echo "failed tests:$failed" +exit 1 |