summaryrefslogtreecommitdiff
path: root/Build/source/texk/dvipdfm-x/xsrc/tt_gsub.c
diff options
context:
space:
mode:
Diffstat (limited to 'Build/source/texk/dvipdfm-x/xsrc/tt_gsub.c')
-rw-r--r--Build/source/texk/dvipdfm-x/xsrc/tt_gsub.c1666
1 files changed, 0 insertions, 1666 deletions
diff --git a/Build/source/texk/dvipdfm-x/xsrc/tt_gsub.c b/Build/source/texk/dvipdfm-x/xsrc/tt_gsub.c
deleted file mode 100644
index ea31da94e3e..00000000000
--- a/Build/source/texk/dvipdfm-x/xsrc/tt_gsub.c
+++ /dev/null
@@ -1,1666 +0,0 @@
-/*
-
- This is dvipdfmx, an eXtended version of dvipdfm by Mark A. Wicks.
-
- Copyright (C) 2002-2012 by Jin-Hwan Cho and Shunsaku Hirata,
- the dvipdfmx project team.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
-*/
-
-/*
- * TrueType GSUB support: (incomplete)
- */
-
-#include "system.h"
-
-#include "error.h"
-#include "mem.h"
-#include "mfileio.h"
-
-#include "sfnt.h"
-
-#include "otl_opt.h"
-#include "tt_gsub.h"
-
-#define VERBOSE_LEVEL_MIN 0
-static int verbose = 0;
-void
-otl_gsub_set_verbose (void)
-{
- verbose++;
-}
-
-typedef USHORT Offset;
-typedef USHORT GlyphID;
-
-/* OpenType Common Layout Table */
-/* Records */
-struct clt_record
-{
- char tag[5]; /* 4-byte identifier */
- Offset offset;
-};
-
-/* Ranges */
-/* RangeRecord */
-struct clt_range
-{
- GlyphID Start; /* First GlyphID in the range */
- GlyphID End; /* Last GlyphID in the range */
- USHORT StartCoverageIndex; /* Converage Index of first GID */
-};
-
-static long
-clt_read_record (struct clt_record *rec, sfnt *sfont)
-{
- int i;
-
- ASSERT(rec && sfont);
-
- for (i = 0; i < 4; i++) {
- rec->tag[i] = sfnt_get_char(sfont);
- }
- rec->tag[4] = '\0';
- rec->offset = sfnt_get_ushort(sfont);
-
- return 6;
-}
-
-static long
-clt_read_range (struct clt_range *rec, sfnt *sfont)
-{
- ASSERT(rec && sfont);
-
- rec->Start = sfnt_get_ushort(sfont);
- rec->End = sfnt_get_ushort(sfont);
- rec->StartCoverageIndex = sfnt_get_ushort(sfont);
-
- return 6;
-}
-
-/*
- List structure:
- ScriptRecord (records), FeatureRecord (records), Lookup (offsets)
-*/
-
-struct clt_record_list
-{
- USHORT count;
- struct clt_record *record;
-};
-
-/* offset and index list, Offset is USHORT */
-struct clt_number_list
-{
- USHORT count;
- USHORT *value;
-};
-
-static long
-clt_read_record_list (struct clt_record_list *list, sfnt *sfont)
-{
- long len, i;
-
- ASSERT(list && sfont);
-
- list->count = sfnt_get_ushort(sfont);
- len = 2;
-
- if (list->count == 0)
- list->record = NULL;
- else {
- list->record = NEW(list->count, struct clt_record);
- for (i = 0; i < list->count; i++) {
- len += clt_read_record(&(list->record[i]), sfont);
- }
- }
-
- return len;
-}
-
-static void
-clt_release_record_list (struct clt_record_list *list)
-{
- if (list) {
- if (list->record)
- RELEASE(list->record);
- list->record = NULL;
- list->count = 0;
- }
-}
-
-static long
-clt_read_number_list (struct clt_number_list *list, sfnt *sfont)
-{
- long i;
-
- ASSERT(list && sfont);
-
- list->count = sfnt_get_ushort(sfont);
-
- if (list->count == 0)
- list->value = NULL;
- else {
- list->value = NEW(list->count, USHORT);
- for (i = 0; i < list->count; i++) {
- list->value[i] = sfnt_get_ushort(sfont);
- }
- }
-
- return (2 + 2 * list->count);
-}
-
-static void
-clt_release_number_list (struct clt_number_list *list)
-{
- if (list) {
- if (list->value)
- RELEASE(list->value);
- list->value = NULL;
- list->count = 0;
- }
-}
-
-/*
- * Tables
- */
-
-
-/* Coverage Table: format 1 and format 2 */
-struct clt_coverage
-{
- USHORT format; /* Format identifier: 1 (list), 2 (range) */
- USHORT count; /* Glyphs/Range Count */
- GlyphID *list; /* Array of GlyphIDs - in numerical order */
- struct clt_range *range; /* Array of glyph ranges
- * - ordered by Start GlyphID
- */
-};
-
-/* GSUB - The Glyph Substitution Table */
-struct otl_gsub_header
-{
- Fixed version; /* 0x00010000 */
- Offset ScriptList; /* offset */
- Offset FeatureList; /* offset */
- Offset LookupList; /* offset */
-};
-
-/* Single Substitution Format 1 */
-struct otl_gsub_single1
-{
- SHORT DeltaGlyphID; /* Add to original GlyphID to get
- * substitute GlyphID */
- struct clt_coverage coverage; /* Coverage table */
-};
-
-/* Single Substitution Format 2 */
-struct otl_gsub_single2
-{
- USHORT GlyphCount; /* Number of GlyphIDs in the Substitute array */
- GlyphID *Substitute; /* Array of substitute GlyphIDs
- * - ordered by Coverage Index */
- struct clt_coverage coverage; /* Coverage table */
-};
-
-/* Alternate Subsutitution Format 1 */
-struct otl_gsub_altset
-{
- USHORT GlyphCount; /* Number of GlyphIDs in the Alternate array */
- GlyphID *Alternate; /* Array of alternate GlyphIDs
- * - in arbitrary order
- */
-};
-
-struct otl_gsub_alternate1
-{
- USHORT AlternateSetCount;
- struct otl_gsub_altset *AlternateSet;
-
- struct clt_coverage coverage;
-};
-
-/* Faithfull */
-struct otl_gsub_ligtab
-{
- GlyphID LigGlyph; /* GlyphID of ligature glyph */
- USHORT CompCount;
- GlyphID *Component; /* CompCount - 1 elements
- * First component excluded.
- * Ordered in writing direction...
- */
-};
-
-struct otl_gsub_ligset
-{
- USHORT LigatureCount;
- struct otl_gsub_ligtab *Ligature;
-};
-
-struct otl_gsub_ligature1
-{
- USHORT LigSetCount;
- struct otl_gsub_ligset *LigatureSet;
-
- struct clt_coverage coverage;
-};
-
-/* GSUB subtable (single) */
-struct otl_gsub_subtab
-{
- USHORT LookupType; /* FIXME */
-
- USHORT SubstFormat;
- union {
- struct otl_gsub_single1 *single1;
- struct otl_gsub_single2 *single2;
- struct otl_gsub_alternate1 *alternate1;
- struct otl_gsub_ligature1 *ligature1;
- } table;
-};
-
-/* Script Table */
-struct clt_script_table
-{
- Offset DefaultLangSys;
- struct clt_record_list LangSysRecord;
-};
-
-static long
-clt_read_script_table (struct clt_script_table *tab, sfnt *sfont)
-{
- long len;
-
- ASSERT(tab && sfont);
-
- tab->DefaultLangSys = sfnt_get_ushort(sfont);
- len = 2;
- len += clt_read_record_list(&tab->LangSysRecord, sfont);
-
- return len;
-}
-
-static void
-clt_release_script_table (struct clt_script_table *tab)
-{
- if (tab)
- clt_release_record_list(&tab->LangSysRecord);
-}
-
-/* LangSys Table */
-struct clt_langsys_table
-{
- Offset LookupOrder; /* reserved */
- USHORT ReqFeatureIndex;
- struct clt_number_list FeatureIndex; /* Array of indices into the
- * FeatureList in arbitary order.
- */
-};
-
-static long
-clt_read_langsys_table (struct clt_langsys_table *tab, sfnt *sfont)
-{
- long len;
-
- ASSERT(tab && sfont);
-
- tab->LookupOrder = sfnt_get_ushort(sfont);
- tab->ReqFeatureIndex = sfnt_get_ushort(sfont);
- len = 4;
- len += clt_read_number_list(&tab->FeatureIndex, sfont);
-
- return len;
-}
-
-static void
-clt_release_langsys_table (struct clt_langsys_table *tab)
-{
- if (tab)
- clt_release_number_list(&tab->FeatureIndex);
-}
-
-
-/* Feature Table */
-struct clt_feature_table
-{
- Offset FeatureParams;
- struct clt_number_list LookupListIndex; /* LookupListIndex List */
-};
-
-static long
-clt_read_feature_table (struct clt_feature_table *tab, sfnt *sfont)
-{
- long len;
-
- ASSERT(tab && sfont);
-
- tab->FeatureParams = sfnt_get_ushort(sfont);
- len = 2;
- len += clt_read_number_list(&tab->LookupListIndex, sfont);
-
- return len;
-}
-
-static void
-clt_release_feature_table (struct clt_feature_table *tab)
-{
- if (tab)
- clt_release_number_list(&tab->LookupListIndex);
-}
-
-/* Lookup Table:
- * Currently, only single substitution is supported.
- * LookupFlag is ignored.
- */
-struct clt_lookup_table
-{
- USHORT LookupType; /* Different enumerations for GSUB and GPOS */
- USHORT LookupFlag; /* Lookup qualifiers */
- struct clt_number_list SubTableList; /* offset */
- /* offset is from beginning of Lookup table */
-};
-
-static long
-clt_read_lookup_table (struct clt_lookup_table *tab, sfnt *sfont)
-{
- long len;
-
- ASSERT(tab && sfont);
-
- tab->LookupType = sfnt_get_ushort(sfont);
- tab->LookupFlag = sfnt_get_ushort(sfont);
- len = 4;
- len += clt_read_number_list(&tab->SubTableList, sfont);
-
- return len;
-}
-
-static void
-clt_release_lookup_table (struct clt_lookup_table *tab)
-{
- if (tab)
- clt_release_number_list(&tab->SubTableList);
-}
-
-static long
-clt_read_coverage (struct clt_coverage *cov, sfnt *sfont)
-{
- long len, i;
-
- ASSERT(cov && sfont);
-
- cov->format = sfnt_get_ushort(sfont);
- cov->count = sfnt_get_ushort(sfont);
- len = 4;
-
- switch (cov->format) {
- case 1: /* list */
- if (cov->count == 0)
- cov->list = NULL;
- else {
- cov->list = NEW(cov->count, USHORT);
- for (i = 0; i < cov->count; i++) {
- cov->list[i] = sfnt_get_ushort(sfont);
- }
- }
- cov->range = NULL;
- len += 2 * cov->count;
- break;
- case 2: /* range */
- if (cov->count == 0)
- cov->range = NULL;
- else {
- cov->range = NEW(cov->count, struct clt_range);
- for (i = 0; i < cov->count; i++) {
- len += clt_read_range(&(cov->range[i]), sfont);
- }
- }
- cov->list = NULL;
- break;
- default:
- ERROR("Unknown coverage format");
- }
-
- return len;
-}
-
-static void
-clt_release_coverage (struct clt_coverage *cov)
-{
- if (cov) {
- switch (cov->format) {
- case 1: /* list */
- if (cov->list)
- RELEASE(cov->list);
- cov->list = NULL;
- break;
- case 2: /* range */
- if (cov->range)
- RELEASE(cov->range);
- cov->range = NULL;
- break;
- default:
- ERROR("Unknown coverage format");
- }
- }
- cov->count = 0;
-}
-
-/* returns -1 if not found */
-static long
-clt_lookup_coverage (struct clt_coverage *cov, USHORT gid)
-{
- long i;
-
- ASSERT(cov);
-
- switch (cov->format) {
- case 1: /* list */
- for (i = 0; i < cov->count; i++) {
- if (cov->list[i] > gid) {
- break;
- } else if (cov->list[i] == gid) {
- return i; /* found */
- }
- }
- break;
- case 2: /* range */
- for (i = 0; i < cov->count; i++) {
- if (gid < cov->range[i].Start) {
- break;
- } else if (gid <= cov->range[i].End) { /* found */
- return (cov->range[i].StartCoverageIndex +
- gid - cov->range[i].Start);
- }
- }
- break;
- default:
- ERROR("Unknown coverage format");
- }
-
- return -1; /* not found */
-}
-
-static long
-otl_gsub_read_single (struct otl_gsub_subtab *subtab, sfnt *sfont)
-{
- long len;
- ULONG offset; /* not Offset which is USHORT */
- Offset cov_offset; /* subtable offset, offset to Coverage table */
-
- ASSERT(subtab && sfont);
-
-#ifdef XETEX
- offset = sfont->loc;
-#else
- offset = tell_position(sfont->stream);
-#endif
-
- subtab->LookupType = OTL_GSUB_TYPE_SINGLE;
- subtab->SubstFormat = sfnt_get_ushort(sfont);
- len = 2;
-
- if (subtab->SubstFormat == 1) {
- struct otl_gsub_single1 *data;
-
- subtab->table.single1 = data = NEW(1, struct otl_gsub_single1);
- cov_offset = sfnt_get_ushort(sfont);
- data->DeltaGlyphID = sfnt_get_short(sfont);
- len += 4;
-
- sfnt_seek_set(sfont, offset + cov_offset);
- len += clt_read_coverage(&data->coverage, sfont);
-
- } else if (subtab->SubstFormat == 2) {
- struct otl_gsub_single2 *data;
- USHORT count;
-
- subtab->table.single2 = data = NEW(1, struct otl_gsub_single2);
- cov_offset = sfnt_get_ushort(sfont);
- data->GlyphCount = sfnt_get_ushort(sfont);
- len += 4;
-
- if (data->GlyphCount == 0)
- data->Substitute = NULL;
- else {
- data->Substitute = NEW(data->GlyphCount, GlyphID);
- for (count = 0; count < data->GlyphCount; count++) {
- data->Substitute[count] = sfnt_get_ushort(sfont);
- }
- len += 2 * data->GlyphCount;
- }
-
- sfnt_seek_set(sfont, offset + cov_offset);
- len += clt_read_coverage(&data->coverage, sfont);
-
- } else {
- ERROR("unexpected SubstFormat");
- }
- /* not implemented yet */
-
- return len;
-}
-
-static long
-otl_gsub_read_alternate (struct otl_gsub_subtab *subtab, sfnt *sfont)
-{
- long len;
- USHORT i, j;
- ULONG offset; /* not Offset which is USHORT */
- Offset cov_offset; /* subtable offset, offset to Coverage table */
- struct clt_number_list altset_offsets;
- struct otl_gsub_alternate1 *data;
-
- ASSERT(subtab && sfont);
-
-#ifdef XETEX
- offset = sfont->loc;
-#else
- offset = tell_position(sfont->stream);
-#endif
-
- subtab->LookupType = OTL_GSUB_TYPE_ALTERNATE;
- subtab->SubstFormat = sfnt_get_ushort(sfont); /* Must be 1 */
- if (subtab->SubstFormat != 1) {
- WARN("Unknown GSUB SubstFormat for Alternate: %u",
- subtab->SubstFormat);
- return -1;
- }
-
- len = 2;
- subtab->table.alternate1 =
- data = NEW(1, struct otl_gsub_alternate1);
-
- cov_offset = sfnt_get_ushort(sfont);
- len += 2;
- len += clt_read_number_list(&altset_offsets, sfont);
- data->AlternateSetCount = altset_offsets.count;
- if (data->AlternateSetCount == 0) {
- data->AlternateSet = NULL;
- data->coverage.count = 0;
- data->coverage.format = 0;
- data->coverage.list = NULL;
- return len;
- }
- data->AlternateSet = NEW(data->AlternateSetCount,
- struct otl_gsub_altset);
- for (i = 0; i < data->AlternateSetCount; i++) {
- struct otl_gsub_altset *altset;
- ULONG altset_offset;
-
- altset = &(data->AlternateSet[i]);
-
- altset_offset = offset + altset_offsets.value[i];
- sfnt_seek_set(sfont, altset_offset);
- altset->GlyphCount = sfnt_get_ushort(sfont);
- len += 2;
- if (altset->GlyphCount == 0) {
- altset->Alternate = NULL;
- break;
- }
- altset->Alternate = NEW(altset->GlyphCount, GlyphID);
- for (j = 0; j < altset->GlyphCount; j++) {
- altset->Alternate[j] = sfnt_get_ushort(sfont);
- len += 2;
- }
- }
- clt_release_number_list(&altset_offsets);
-
- sfnt_seek_set(sfont, offset + cov_offset);
- len += clt_read_coverage(&data->coverage, sfont);
-
- return len;
-}
-
-static long
-otl_gsub_read_ligature (struct otl_gsub_subtab *subtab, sfnt *sfont)
-{
- long len;
- USHORT i, j;
- ULONG offset; /* not Offset which is USHORT */
- Offset cov_offset; /* subtable offset, offset to Coverage table */
- struct clt_number_list ligset_offsets;
- struct otl_gsub_ligature1 *data;
-
- ASSERT(subtab && sfont);
-
-#ifdef XETEX
- offset = sfont->loc;
-#else
- offset = tell_position(sfont->stream);
-#endif
-
- subtab->LookupType = OTL_GSUB_TYPE_LIGATURE;
- subtab->SubstFormat = sfnt_get_ushort(sfont); /* Must be 1 */
- if (subtab->SubstFormat != 1) {
- WARN("Unknown GSUB SubstFormat for Ligature: %u",
- subtab->SubstFormat);
- return -1;
- }
-
- len = 2;
- subtab->table.ligature1 =
- data = NEW(1, struct otl_gsub_ligature1);
-
- cov_offset = sfnt_get_ushort(sfont);
- len += 2;
- len += clt_read_number_list(&ligset_offsets, sfont);
- data->LigSetCount = ligset_offsets.count;
- if (data->LigSetCount == 0) {
- data->LigatureSet = NULL;
- data->coverage.count = 0;
- data->coverage.format = 0;
- data->coverage.list = NULL;
- return len;
- }
- data->LigatureSet = NEW(data->LigSetCount,
- struct otl_gsub_ligset);
- for (i = 0; i < data->LigSetCount; i++) {
- struct clt_number_list ligset_tab;
- struct otl_gsub_ligset *ligset;
- ULONG ligset_offset;
- USHORT count;
-
- ligset = &(data->LigatureSet[i]);
-
- ligset_offset = offset + ligset_offsets.value[i];
- sfnt_seek_set(sfont, ligset_offset);
- len += clt_read_number_list(&ligset_tab, sfont);
-
- ligset->LigatureCount = ligset_tab.count;
- if (ligset_tab.count == 0) {
- ligset->Ligature = NULL;
- break;
- }
- ligset->Ligature = NEW(ligset_tab.count,
- struct otl_gsub_ligtab);
- for (j = 0; j < ligset_tab.count; j++) {
- sfnt_seek_set(sfont, ligset_offset + ligset_tab.value[j]);
- ligset->Ligature[j].LigGlyph = sfnt_get_ushort(sfont);
- ligset->Ligature[j].CompCount = sfnt_get_ushort(sfont);
- if (ligset->Ligature[j].CompCount == 0) {
- ligset->Ligature[j].Component = NULL;
- break;
- }
- ligset->Ligature[j].Component =
- NEW(ligset->Ligature[j].CompCount - 1, GlyphID);
- for (count = 0;
- count < ligset->Ligature[j].CompCount - 1; count++) {
- ligset->Ligature[j].Component[count] = sfnt_get_ushort(sfont);
- }
- len += 4 + count * 2;
- }
- clt_release_number_list(&ligset_tab);
- }
- clt_release_number_list(&ligset_offsets);
-
- sfnt_seek_set(sfont, offset + cov_offset);
- len += clt_read_coverage(&data->coverage, sfont);
-
- return len;
-}
-
-static void
-otl_gsub_release_single (struct otl_gsub_subtab *subtab)
-{
- if (subtab) {
- switch((int) subtab->SubstFormat) {
- case 1:
- {
- struct otl_gsub_single1 *data;
-
- data = subtab->table.single1;
- if (data) {
- clt_release_coverage(&data->coverage);
- RELEASE(data);
- }
- subtab->table.single1 = NULL;
- }
- break;
- case 2:
- {
- struct otl_gsub_single2 *data;
-
- data = subtab->table.single2;
- if (data) {
- if (data->Substitute)
- RELEASE(data->Substitute);
- clt_release_coverage(&data->coverage);
- RELEASE(data);
- }
- subtab->table.single2 = NULL;
- }
- break;
- default:
- ERROR("Unknown format for single substitution");
- }
- }
-}
-
-static void
-otl_gsub_release_ligature (struct otl_gsub_subtab *subtab)
-{
- if (subtab) {
- struct otl_gsub_ligature1 *data;
- USHORT i, j;
-
- data = subtab->table.ligature1;
- if (data && data->LigatureSet) {
- for (i = 0; i < data->LigSetCount; i++) {
- struct otl_gsub_ligset *ligset;
-
- ligset = &(data->LigatureSet[i]);
- for (j = 0;
- j < ligset->LigatureCount; j++) {
- if (ligset->Ligature[j].Component)
- RELEASE(ligset->Ligature[j].Component);
- ligset->Ligature[j].Component = NULL;
- }
- RELEASE(ligset->Ligature);
- ligset->Ligature = NULL;
- }
- RELEASE(data->LigatureSet);
- }
- clt_release_coverage(&data->coverage);
- data->LigatureSet = NULL;
- RELEASE(data);
- subtab->table.ligature1 = NULL;
- }
-}
-
-static void
-otl_gsub_release_alternate (struct otl_gsub_subtab *subtab)
-{
- if (subtab) {
- struct otl_gsub_alternate1 *data;
- USHORT i;
-
- data = subtab->table.alternate1;
- if (data && data->AlternateSet) {
- for (i = 0; i < data->AlternateSetCount; i++) {
- struct otl_gsub_altset *altset;
-
- altset = &(data->AlternateSet[i]);
- if (altset->Alternate)
- RELEASE(altset->Alternate);
- altset->Alternate = NULL;
- }
- RELEASE(data->AlternateSet);
- }
- clt_release_coverage(&data->coverage);
- data->AlternateSet = NULL;
- RELEASE(data);
- subtab->table.alternate1 = NULL;
- }
-}
-
-static long
-otl_gsub_read_header (struct otl_gsub_header *head, sfnt *sfont)
-{
- ASSERT(head && sfont);
-
- head->version = sfnt_get_ulong (sfont);
- head->ScriptList = sfnt_get_ushort(sfont);
- head->FeatureList = sfnt_get_ushort(sfont);
- head->LookupList = sfnt_get_ushort(sfont);
-
- return 10;
-}
-
-/*
- * script -- langsys --> feature indices
- * |
- * +- langsys --> feature indices
- *
- * feature --> lookup indices
- */
-
-struct otl_gsub_tab
-{
- char *script;
- char *language;
- char *feature;
-
- int num_subtables;
- struct otl_gsub_subtab *subtables;
-};
-
-
-static int
-otl_gsub_read_feat (struct otl_gsub_tab *gsub, sfnt *sfont)
-{
- long feat_idx, script_idx;
- ULONG gsub_offset, offset;
- struct otl_gsub_header head;
- struct otl_gsub_subtab *subtab = NULL;
- USHORT num_subtabs = 0;
- unsigned char feat_bits[8192];
- struct clt_record_list feature_list;
- struct clt_record_list script_list;
- struct clt_number_list lookup_list ;
- otl_opt *script, *language, *feature;
-
- ASSERT(gsub && sfont);
-
- gsub_offset = sfnt_find_table_pos(sfont, "GSUB");
- if (gsub_offset == 0)
- return -1; /* not found */
-
- script = otl_new_opt();
- otl_parse_optstring(script, gsub->script);
- language = otl_new_opt();
- otl_parse_optstring(language, gsub->language);
- feature = otl_new_opt();
- otl_parse_optstring(feature, gsub->feature);
-
- memset(feat_bits, 0, 8192);
-
- /* GSUB header */
- sfnt_seek_set(sfont, gsub_offset);
- otl_gsub_read_header(&head, sfont);
-
- /* Script */
- offset = gsub_offset + head.ScriptList;
- sfnt_seek_set(sfont, offset);
- clt_read_record_list(&script_list, sfont);
-
-#define SET_BIT(b,p) do {\
- (b)[(p)/8] |= (1<<(7-((p) % 8)));\
-} while (0)
-#define BIT_SET(b,p) (((b)[(p)/8]) & (1 << (7-((p)%8))))
-
- for (script_idx = 0;
- script_idx < script_list.count; script_idx++) {
- if (otl_match_optrule(script,
- script_list.record[script_idx].tag)) {
- struct clt_script_table script_tab;
- long langsys_idx;
-
- offset = gsub_offset +
- head.ScriptList + script_list.record[script_idx].offset;
- sfnt_seek_set(sfont, offset);
- clt_read_script_table(&script_tab, sfont);
-
- if (otl_match_optrule(language, "dflt") &&
- script_tab.DefaultLangSys != 0) {
- struct clt_langsys_table langsys_tab;
-
- if(verbose > VERBOSE_LEVEL_MIN) {
- MESG("otl_gsub>> OTL script-language enabled: %c%c%c%c.dflt\n",
- script_list.record[script_idx].tag[0],
- script_list.record[script_idx].tag[1],
- script_list.record[script_idx].tag[2],
- script_list.record[script_idx].tag[3]);
- }
-
- sfnt_seek_set(sfont, offset + script_tab.DefaultLangSys);
- clt_read_langsys_table(&langsys_tab, sfont);
- if (otl_match_optrule(feature, "____") && /* _FIXME_ */
- langsys_tab.ReqFeatureIndex != 0xFFFF)
- SET_BIT(feat_bits, langsys_tab.ReqFeatureIndex);
- for (feat_idx = 0;
- feat_idx < langsys_tab.FeatureIndex.count;
- feat_idx++) {
- SET_BIT(feat_bits,
- langsys_tab.FeatureIndex.value[feat_idx]);
- }
- clt_release_langsys_table(&langsys_tab);
- }
- for (langsys_idx = 0;
- langsys_idx < script_tab.LangSysRecord.count;
- langsys_idx++) {
- struct clt_record *langsys_rec;
-
- langsys_rec = &(script_tab.LangSysRecord.record[langsys_idx]);
- if (otl_match_optrule(language, langsys_rec->tag)) {
- struct clt_langsys_table langsys_tab;
-
- if(verbose > VERBOSE_LEVEL_MIN) {
- MESG("otl_gsub>> OTL script-language enabled: %c%c%c%c.%c%c%c%c\n",
- script_list.record[script_idx].tag[0],
- script_list.record[script_idx].tag[1],
- script_list.record[script_idx].tag[2],
- script_list.record[script_idx].tag[3],
- langsys_rec->tag[0], langsys_rec->tag[1],
- langsys_rec->tag[2], langsys_rec->tag[3]);
- }
-
- sfnt_seek_set(sfont, offset + langsys_rec->offset);
- clt_read_langsys_table(&langsys_tab, sfont);
- if (otl_match_optrule(feature, "____") || /* _FIXME_ */
- langsys_tab.ReqFeatureIndex != 0xFFFF)
- SET_BIT(feat_bits, langsys_tab.ReqFeatureIndex);
- for (feat_idx = 0;
- feat_idx < langsys_tab.FeatureIndex.count;
- feat_idx++) {
- SET_BIT(feat_bits,
- langsys_tab.FeatureIndex.value[feat_idx]);
- }
- clt_release_langsys_table(&langsys_tab);
- }
- }
- clt_release_script_table(&script_tab);
- }
- }
-
- /* Feature List */
- offset = gsub_offset + head.FeatureList;
- sfnt_seek_set(sfont, offset);
- clt_read_record_list(&feature_list, sfont);
-
- /* Lookup List */
- offset = gsub_offset + head.LookupList;
- sfnt_seek_set(sfont, offset);
- clt_read_number_list(&lookup_list, sfont);
-
- if(verbose > VERBOSE_LEVEL_MIN) {
- MESG("otl_gsub>> Reading OTL feature(s):");
- }
-
- for (feat_idx = 0;
- feat_idx < feature_list.count; feat_idx++) {
- if (BIT_SET(feat_bits, feat_idx) &&
- (otl_match_optrule(feature,
- feature_list.record[feat_idx].tag))) {
- struct clt_feature_table feature_table;
- long i;
-
- if(verbose > VERBOSE_LEVEL_MIN) {
- MESG(" %c%c%c%c",
- feature_list.record[feat_idx].tag[0],
- feature_list.record[feat_idx].tag[1],
- feature_list.record[feat_idx].tag[2],
- feature_list.record[feat_idx].tag[3]);
- }
-
- /* Feature Table */
- offset = gsub_offset +
- head.FeatureList + feature_list.record[feat_idx].offset;
-
- sfnt_seek_set(sfont, offset);
- clt_read_feature_table(&feature_table, sfont);
- if (feature_table.FeatureParams != 0) {
- ERROR("unrecognized FeatureParams");
- }
-
- /* Lookup table */
- for (i = 0; i < feature_table.LookupListIndex.count; i++) {
- struct clt_lookup_table lookup_table;
- long ll_idx, st_idx, r, n_st;
-
- ll_idx = feature_table.LookupListIndex.value[i];
- if (ll_idx >= lookup_list.count)
- ERROR("invalid Lookup index.");
-
- offset = gsub_offset +
- head.LookupList + (lookup_list.value)[ll_idx];
- sfnt_seek_set(sfont, offset);
- clt_read_lookup_table(&lookup_table, sfont);
-
- if (lookup_table.LookupType != OTL_GSUB_TYPE_SINGLE &&
- lookup_table.LookupType != OTL_GSUB_TYPE_ALTERNATE &&
- lookup_table.LookupType != OTL_GSUB_TYPE_LIGATURE &&
- lookup_table.LookupType != OTL_GSUB_TYPE_ESUBST) {
- if (verbose > VERBOSE_LEVEL_MIN)
- WARN("Skipping unsupported GSUB subtable: LookupType=%d", lookup_table.LookupType);
- continue;
- }
-
- subtab = RENEW(subtab,
- num_subtabs + lookup_table.SubTableList.count,
- struct otl_gsub_subtab);
- for (n_st = 0, st_idx = 0;
- st_idx < lookup_table.SubTableList.count; st_idx++) {
-
- offset = gsub_offset + head.LookupList +
- lookup_list.value[ll_idx] +
- (lookup_table.SubTableList.value)[st_idx];
-
- sfnt_seek_set(sfont, offset);
-
- switch ((int) lookup_table.LookupType) {
- case OTL_GSUB_TYPE_SINGLE:
- r = otl_gsub_read_single(&subtab[num_subtabs + n_st],
- sfont);
- if (r <= 0)
- WARN("Reading GSUB subtable (single) failed...");
- else {
- if(verbose > VERBOSE_LEVEL_MIN) {
- MESG("(single)");
- }
- n_st++;
- }
- break;
-
- case OTL_GSUB_TYPE_ALTERNATE:
- r = otl_gsub_read_alternate(&subtab[num_subtabs + n_st],
- sfont);
- if (r <= 0)
- WARN("Reading GSUB subtable (alternate) failed...");
- else {
- if(verbose > VERBOSE_LEVEL_MIN) {
- MESG("(alternate)");
- }
- n_st++;
- }
- break;
-
- case OTL_GSUB_TYPE_LIGATURE:
- r = otl_gsub_read_ligature(&subtab[num_subtabs + n_st],
- sfont);
- if (r <= 0)
- WARN("Reading GSUB subtable (ligature) failed...");
- else {
- if(verbose > VERBOSE_LEVEL_MIN) {
- MESG("(ligature)");
- }
- n_st++;
- }
- break;
-
- case OTL_GSUB_TYPE_ESUBST:
- {
- USHORT SubstFormat;
- USHORT ExtensionLookupType;
- ULONG ExtensionOffset;
-
- SubstFormat = sfnt_get_ushort(sfont);
- if (SubstFormat != 1)
- break;
- ExtensionLookupType = sfnt_get_ushort(sfont);
- ExtensionOffset = sfnt_get_ulong (sfont);
-
- sfnt_seek_set(sfont, offset + ExtensionOffset);
- switch (ExtensionLookupType) {
- case OTL_GSUB_TYPE_SINGLE:
- r = otl_gsub_read_single(&subtab[num_subtabs + n_st],
- sfont);
- if (r <= 0)
- WARN("Reading GSUB subtable (ext:single) failed...");
- else {
- if(verbose > VERBOSE_LEVEL_MIN) {
- MESG("(ext:single)");
- }
- n_st++;
- }
- break;
-
- case OTL_GSUB_TYPE_ALTERNATE:
- r = otl_gsub_read_alternate(&subtab[num_subtabs + n_st],
- sfont);
- if (r <= 0)
- WARN("Reading GSUB subtable (alternate) failed...");
- else {
- if(verbose > VERBOSE_LEVEL_MIN) {
- MESG("(alternate)");
- }
- n_st++;
- }
- break;
-
- case OTL_GSUB_TYPE_LIGATURE:
- r = otl_gsub_read_ligature(&subtab[num_subtabs + n_st],
- sfont);
- if (r <= 0)
- WARN("Reading GSUB subtable (ext:ligature) failed...");
- else {
- if(verbose > VERBOSE_LEVEL_MIN) {
- MESG("(ext:ligature)");
- }
- n_st++;
- }
- break;
-
- }
- }
- break;
-
- default:
- break;
- }
- }
- num_subtabs += n_st; /* lookup_table.SubTableList.count; */
- clt_release_lookup_table(&lookup_table);
- }
- clt_release_feature_table(&feature_table);
- }
- }
-
- if(verbose > VERBOSE_LEVEL_MIN) {
- MESG("\n");
- MESG("otl_gsub>> %ld subtable(s) read.\n", num_subtabs);
- }
-
- clt_release_number_list(&lookup_list);
- clt_release_record_list(&feature_list);
- clt_release_record_list(&script_list);
-
- otl_release_opt(script);
- otl_release_opt(language);
- otl_release_opt(feature);
-
- if (subtab != NULL) {
- gsub->num_subtables = num_subtabs;
- gsub->subtables = subtab;
- } else {
- return -1;
- }
-
- return 0;
-}
-
-
-static int
-otl_gsub_apply_single (struct otl_gsub_subtab *subtab, USHORT *gid)
-{
- long idx;
-
- ASSERT(subtab && gid);
-
- if (subtab->SubstFormat == 1) {
- struct otl_gsub_single1 *data;
-
- data = (subtab->table).single1;
- idx = clt_lookup_coverage(&data->coverage, *gid);
- if (idx >= 0) {
- *gid += data->DeltaGlyphID;
- return 0; /* found */
- }
- } else if (subtab->SubstFormat == 2) {
- struct otl_gsub_single2 *data;
-
- data = (subtab->table).single2;
- idx = clt_lookup_coverage(&data->coverage, *gid);
- if (idx >= 0 &&
- idx < data->GlyphCount) {
- *gid = (data->Substitute)[idx];
- return 0; /* found */
- }
- }
-
- return -1;
-}
-
-static int
-otl_gsub_apply_alternate (struct otl_gsub_subtab *subtab,
- USHORT alt_idx, USHORT *gid)
-{
- long idx;
-
- ASSERT(subtab && gid);
-
- if (subtab->SubstFormat == 1) {
- struct otl_gsub_alternate1 *data;
-
- data = subtab->table.alternate1;
- idx = clt_lookup_coverage(&data->coverage, *gid);
- if (idx < 0 || idx >= data->AlternateSetCount)
- return -1;
- else {
- struct otl_gsub_altset *altset;
- altset = &(data->AlternateSet[idx]);
- if (alt_idx >= altset->GlyphCount)
- return -1;
- else {
- *gid = altset->Alternate[alt_idx];
- return 0;
- }
- }
- }
-
- return -1;
-}
-
-/* NOTE: Ligature table is in preference order */
-static int
-glyph_seq_cmp (GlyphID *glyph_seq0, USHORT n_glyphs0,
- GlyphID *glyph_seq1, USHORT n_glyphs1)
-{
- USHORT i;
-
- if (n_glyphs0 != n_glyphs1)
- return n_glyphs0 - n_glyphs1;
-
- for (i = 0; i < n_glyphs0; i++) {
- if (glyph_seq0[i] != glyph_seq1[i])
- return glyph_seq0[i] - glyph_seq1[i];
- }
-
- return 0;
-}
-
-static int
-otl_gsub_apply_ligature (struct otl_gsub_subtab *subtab,
- USHORT *gid_in, USHORT num_gids,
- USHORT *gid_out)
-{
- long idx;
-
- ASSERT(subtab && gid_out);
-
- if (!gid_in || num_gids < 1)
- return -1;
-
- if (subtab->SubstFormat == 1) {
- struct otl_gsub_ligature1 *data;
-
- data = subtab->table.ligature1;
- idx = clt_lookup_coverage(&data->coverage, gid_in[0]);
- if (idx >= 0 && idx < data->LigSetCount) {
- struct otl_gsub_ligset *ligset;
- USHORT j;
-
- ligset = &(data->LigatureSet[idx]);
- for (j = 0; j < ligset->LigatureCount; j++) {
- if (!glyph_seq_cmp(&gid_in[1], (USHORT)(num_gids - 1),
- ligset->Ligature[j].Component,
- (USHORT)(ligset->Ligature[j].CompCount - 1))) {
- *gid_out = ligset->Ligature[j].LigGlyph;
- return 0; /* found */
- }
- }
- }
- }
-
- return -1;
-}
-
-#define GSUB_LIST_MAX 32
-struct otl_gsub
-{
- int num_gsubs;
- int select;
- struct otl_gsub_tab gsubs[GSUB_LIST_MAX];
-};
-
-otl_gsub *
-otl_gsub_new (void)
-{
- struct otl_gsub *gsub_list;
-
- gsub_list = NEW(1, struct otl_gsub);
- gsub_list->num_gsubs = 0;
- gsub_list->select = -1;
-
- return (otl_gsub *) gsub_list;
-}
-
-int
-otl_gsub_add_feat (otl_gsub *gsub_list,
- const char *script,
- const char *language,
- const char *feature,
- sfnt *sfont)
-{
- int retval = -1;
- int i;
- struct otl_gsub_tab *gsub;
-
- if (gsub_list->num_gsubs > GSUB_LIST_MAX) {
- ERROR("Too many GSUB features...");
- return -1;
- }
- for (i = 0; i < gsub_list->num_gsubs; i++) {
- gsub = &(gsub_list->gsubs[i]);
- if (!strcmp(script, gsub->script) &&
- !strcmp(language, gsub->language) &&
- !strcmp(feature, gsub->feature)) {
- gsub_list->select = i;
- return 0;
- }
- }
- gsub = &gsub_list->gsubs[i];
-
- gsub->script = NEW(strlen(script) +1, char);
- strcpy(gsub->script, script);
- gsub->language = NEW(strlen(language)+1, char);
- strcpy(gsub->language, language);
- gsub->feature = NEW(strlen(feature) +1, char);
- strcpy(gsub->feature, feature);
-
- if(verbose > VERBOSE_LEVEL_MIN) {
- MESG("\n");
- MESG("otl_gsub>> Reading \"%s.%s.%s\"...\n", script, language, feature);
- }
-
- retval = otl_gsub_read_feat(gsub, sfont);
- if (retval >= 0) {
- gsub_list->select = i;
- gsub_list->num_gsubs++;
- } else {
- if(verbose > VERBOSE_LEVEL_MIN) {
- MESG("otl_gsub>> Failed\n");
- }
- RELEASE(gsub->script);
- RELEASE(gsub->language);
- RELEASE(gsub->feature);
- }
-
- return retval;
-}
-
-void
-otl_gsub_release (otl_gsub *gsub_list)
-{
- struct otl_gsub_tab *gsub;
- struct otl_gsub_subtab *subtab;
- int i, j;
-
- if (!gsub_list)
- return;
-
- for (i = 0; i < gsub_list->num_gsubs; i++) {
- gsub = &(gsub_list->gsubs[i]);
-
- if (gsub->script)
- RELEASE(gsub->script);
- if (gsub->language)
- RELEASE(gsub->language);
- if (gsub->feature)
- RELEASE(gsub->feature);
-
- for (j = 0; j < gsub->num_subtables; j++) {
- subtab = &(gsub->subtables[j]);
- switch ((int) subtab->LookupType) {
- case OTL_GSUB_TYPE_SINGLE:
- otl_gsub_release_single(subtab);
- break;
- case OTL_GSUB_TYPE_ALTERNATE:
- otl_gsub_release_alternate(subtab);
- break;
- case OTL_GSUB_TYPE_LIGATURE:
- otl_gsub_release_ligature(subtab);
- break;
- default:
- ERROR("???");
- break;
- }
- }
- RELEASE(gsub->subtables);
- }
-
- RELEASE(gsub_list);
-}
-
-int
-otl_gsub_apply (otl_gsub *gsub_list, USHORT *gid)
-{
- int retval = -1;
- struct otl_gsub_tab *gsub;
- struct otl_gsub_subtab *subtab;
- int i, j;
-
- if (!gsub_list || !gid)
- return retval;
-
- i = gsub_list->select;
- if (i < 0 || i >= gsub_list->num_gsubs) {
- ERROR("GSUB not selected...");
- return -1;
- }
- gsub = &(gsub_list->gsubs[i]);
-
- for (j = 0;
- retval < 0 && j < gsub->num_subtables; j++) {
- subtab = &(gsub->subtables[j]);
- switch ((int) subtab->LookupType){
- case OTL_GSUB_TYPE_SINGLE:
- retval = otl_gsub_apply_single(subtab, gid);
- break;
- default:
- break;
- }
- }
-
- return retval;
-}
-
-int
-otl_gsub_apply_alt (otl_gsub *gsub_list, USHORT alt_idx, USHORT *gid)
-{
- int retval = -1;
- struct otl_gsub_tab *gsub;
- struct otl_gsub_subtab *subtab;
- int i, j;
-
- if (!gsub_list || !gid)
- return retval;
-
- i = gsub_list->select;
- if (i < 0 || i >= gsub_list->num_gsubs) {
- ERROR("GSUB not selected...");
- return -1;
- }
- gsub = &(gsub_list->gsubs[i]);
-
- for (j = 0;
- retval < 0 && j < gsub->num_subtables; j++) {
- subtab = &(gsub->subtables[j]);
- switch ((int) subtab->LookupType){
- case OTL_GSUB_TYPE_ALTERNATE:
- retval = otl_gsub_apply_alternate(subtab, alt_idx, gid);
- break;
- default:
- break;
- }
- }
-
- return retval;
-}
-
-int
-otl_gsub_apply_lig (otl_gsub *gsub_list,
- USHORT *gid_in, USHORT num_gids, USHORT *gid_out)
-{
- int retval = -1;
- struct otl_gsub_tab *gsub;
- struct otl_gsub_subtab *subtab;
- int i, j;
-
- if (!gsub_list || !gid_out)
- return retval;
-
- i = gsub_list->select;
- if (i < 0 || i >= gsub_list->num_gsubs) {
- ERROR("GSUB not selected...");
- return -1;
- }
- gsub = &(gsub_list->gsubs[i]);
-
- for (j = 0;
- retval < 0 && j < gsub->num_subtables; j++) {
- subtab = &(gsub->subtables[j]);
- switch ((int) subtab->LookupType){
- case OTL_GSUB_TYPE_LIGATURE:
- retval = otl_gsub_apply_ligature(subtab,
- gid_in, num_gids, gid_out);
- break;
- default:
- break;
- }
- }
-
- return retval;
-}
-
-int
-otl_gsub_select (otl_gsub *gsub_list,
- const char *script,
- const char *language,
- const char *feature)
-{
- int i;
- struct otl_gsub_tab *gsub;
-
- for (i = 0; i < gsub_list->num_gsubs; i++) {
- gsub = &(gsub_list->gsubs[i]);
- if (!strcmp(gsub->script, script) &&
- !strcmp(gsub->language, language) &&
- !strcmp(gsub->feature, feature)) {
- gsub_list->select = i;
- return i;
- }
- }
-
- gsub_list->select = -1;
-
- return -1;
-}
-
-#if 0
-static int
-otl_gsub_dump_single (struct otl_gsub_subtab *subtab)
-{
- long gid, idx;
-
- ASSERT(subtab);
-
- if (subtab->SubstFormat == 1) {
- struct otl_gsub_single1 *data;
-
- data = (subtab->table).single1;
- for (gid = 0; gid < 0x10000; gid++) {
- idx = clt_lookup_coverage(&data->coverage, gid);
- if (idx >= 0) {
- fprintf(stdout, "substitute \\%u by \\%u;\n",
- (USHORT) gid, (USHORT) (gid + data->DeltaGlyphID));
- }
- }
- } else if (subtab->SubstFormat == 2) {
- struct otl_gsub_single2 *data;
-
- data = (subtab->table).single2;
- for (gid = 0; gid < 0x10000; gid++) {
- idx = clt_lookup_coverage(&data->coverage, gid);
- if (idx >= 0 &&
- idx < data->GlyphCount) {
- fprintf(stdout, "substitute \\%u by \\%u;\n",
- (USHORT) gid, (data->Substitute)[idx]);
- }
- }
- }
-
- return 0;
-}
-
-static int
-otl_gsub_dump_alternate (struct otl_gsub_subtab *subtab)
-{
- long gid, idx;
-
- ASSERT(subtab);
-
- if (subtab->SubstFormat == 1) {
- struct otl_gsub_alternate1 *data;
-
- data = subtab->table.alternate1;
- for (gid = 0; gid < 0x10000; gid++) {
- idx = clt_lookup_coverage(&data->coverage, gid);
- if (idx >= 0 && idx < data->AlternateSetCount) {
- struct otl_gsub_altset *altset;
- USHORT i;
- altset = &(data->AlternateSet[idx]);
- if (altset->GlyphCount == 0)
- continue;
- fprintf(stdout, "substitute \\%u from [", (USHORT) gid);
- for (i = 0; i < altset->GlyphCount; i++) {
- fprintf(stdout, " \\%u", altset->Alternate[i]);
- }
- fprintf(stdout, " ];\n");
- }
- }
- }
-
- return 0;
-}
-
-static int
-otl_gsub_dump_ligature (struct otl_gsub_subtab *subtab)
-{
- long gid, idx;
-
- ASSERT(subtab);
-
- if (subtab->SubstFormat == 1) {
- struct otl_gsub_ligature1 *data;
-
- data = subtab->table.ligature1;
- for (gid = 0; gid < 0x10000; gid++) {
- idx = clt_lookup_coverage(&data->coverage, gid);
- if (idx >= 0 && idx < data->LigSetCount) {
- struct otl_gsub_ligset *ligset;
- USHORT i, j;
- ligset = &(data->LigatureSet[idx]);
- for (j = 0; j < ligset->LigatureCount; j++) {
- fprintf(stdout, "substitute \\%u", (USHORT) gid);
- for (i = 0; i < ligset->Ligature[j].CompCount - 1; i++) {
- fprintf(stdout, " \\%u", ligset->Ligature[j].Component[i]);
- }
- fprintf(stdout, " by \\%u;\n", ligset->Ligature[j].LigGlyph);
- }
- }
- }
- }
-
- return 0;
-}
-
-int
-otl_gsub_dump (otl_gsub *gsub_list,
- const char *script, const char *language, const char *feature)
-{
- int error = -1;
- struct otl_gsub_tab *gsub;
- struct otl_gsub_subtab *subtab;
- int sel, i, j;
-
- if (!gsub_list)
- return -1;
-
- sel = gsub_list->select;
- error = otl_gsub_select(gsub_list, script, language, feature);
- if (error < 0) {
- ERROR("GSUB feature %s.%s.%s not found.", script, language, feature);
- }
-
- i = gsub_list->select;
- if (i < 0 || i >= gsub_list->num_gsubs) {
- ERROR("GSUB not selected...");
- return -1;
- }
- gsub = &(gsub_list->gsubs[i]);
-
- for (j = 0;
- !error &&
- j < gsub->num_subtables; j++) {
- subtab = &(gsub->subtables[j]);
- switch ((int) subtab->LookupType){
- case OTL_GSUB_TYPE_SINGLE:
- error = otl_gsub_dump_single(subtab);
- break;
- case OTL_GSUB_TYPE_ALTERNATE:
- error = otl_gsub_dump_alternate(subtab);
- break;
- case OTL_GSUB_TYPE_LIGATURE:
- error = otl_gsub_dump_ligature(subtab);
- break;
- }
- }
- gsub_list->select = sel;
-
- return error;
-}
-#endif