+/* otfopen.c -- OpenType font reader.
+
+Copyright (C) 2003
+ by AIST (National Institute of Advanced Industrial Science and Technology)
+ Registration Number H15PRO???
+
+This file is part of the OTF library.
+
+The OTF library 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, or (at
+your option) any later version.
+
+The OTF library is distributed in the hope that it will be useful, but
+WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with the OTF library; see the file COPYING. If not, write to
+the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+Boston, MA 02111-1307, USA. */
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "otf.h"
#include "otferror.h"
-/* OTF_Stream
+/***
+ Table of contents (almost parallel to otf.h):
+
+ (0) Stream handler
+
+ (1) Readers for OTF Layout tables and OTF itself
+ (1-1) Basic types and functions
+ (1-2) "head" table
+ (1-3) "name" table
+ (1-4) "cmap" table
+ (1-5) Structures common to GDEF, GSUB, and GPOS
+ (1-6) "GDEF" table
+ (1-7) Structures for ScriptList, FeatureList, and LookupList
+ (1-8) Structures common to GSUB and GPOS
+ (1-9) "GSUB" table
+ (1-10) "GPOS" table
+ (1-11) Structure for OTF
+
+ (2) APIs for reading OTF
+ (2-1) OTF_open()
+ (2-2) OTF_close()
+ (2-3) OTF_get_table()
+
+ (5) APIs miscellaneous
+*/
+\f
+/* (0) Stream handler
Example of typical usage of OTF_Stream.
#define READ_GLYPHID READ_USHORT
\f
+/*** (1) Structures for OTF Layout tables and OTF itself */
+
+/*** (1-1) Basic types and functions */
enum OTF_TableType
{
} \
} while (0)
-
-\f
-
-static void *read_head_table (OTF *otf, OTF_Stream *stream);
-static void *read_name_table (OTF *otf, OTF_Stream *stream);
-static void *read_cmap_table (OTF *otf, OTF_Stream *stream);
-static void *read_gdef_table (OTF *otf, OTF_Stream *stream);
-static void *read_gsub_table (OTF *otf, OTF_Stream *stream);
-static void *read_gpos_table (OTF *otf, OTF_Stream *stream);
-
-int
-read_offset_table (OTF *otf, OTF_Stream *stream, OTF_OffsetTable *table)
-{
- int errret = -1;
-
- READ_FIXED (stream, table->sfnt_version);
- READ_USHORT (stream, table->numTables);
- READ_USHORT (stream, table->searchRange);
- READ_USHORT (stream, table->enterSelector);
- READ_USHORT (stream, table->rangeShift);
- return 0;
-}
-
-static OTF_Tag
-read_table_directory (OTF_Stream *stream, OTF_TableDirectory *table)
-{
- int errret = 0;
- OTF_Tag tag;
-
- READ_TAG (stream, tag);
- table->tag = tag;
- table->name[0] = tag >> 24;
- table->name[1] = (tag >> 16) & 0xFF;
- table->name[0] = (tag >> 8) & 0xFF;
- table->name[0] = tag >> 8;
- table->name[0] = '\0';
- READ_ULONG (stream, table->checkSum);
- READ_ULONG (stream, table->offset);
- READ_ULONG (stream, table->length);
- return tag;
-}
-
-static int
-read_header_part (OTF *otf, FILE *fp)
-{
- char *errfmt = "otf header%s";
- int errret = -1;
- OTF_Tag head_tag, name_tag, cmap_tag, gdef_tag, gsub_tag, gpos_tag;
- OTF_Stream *stream;
- int i;
- OTF_InternalData *internal_data = (OTF_InternalData *) otf->internal_data;
-
- internal_data->table_info[OTF_TABLE_TYPE_HEAD].address = (void *) &otf->head;
- internal_data->table_info[OTF_TABLE_TYPE_HEAD].reader = read_head_table;
- internal_data->table_info[OTF_TABLE_TYPE_NAME].address = (void *) &otf->name;
- internal_data->table_info[OTF_TABLE_TYPE_NAME].reader = read_name_table;
- internal_data->table_info[OTF_TABLE_TYPE_CMAP].address = (void *) &otf->cmap;
- internal_data->table_info[OTF_TABLE_TYPE_CMAP].reader = read_cmap_table;
- internal_data->table_info[OTF_TABLE_TYPE_GDEF].address = (void *) &otf->gdef;
- internal_data->table_info[OTF_TABLE_TYPE_GDEF].reader = read_gdef_table;
- internal_data->table_info[OTF_TABLE_TYPE_GSUB].address = (void *) &otf->gsub;
- internal_data->table_info[OTF_TABLE_TYPE_GSUB].reader = read_gsub_table;
- internal_data->table_info[OTF_TABLE_TYPE_GPOS].address = (void *) &otf->gpos;
- internal_data->table_info[OTF_TABLE_TYPE_GPOS].reader = read_gpos_table;
-
- head_tag = OTF_tag ("head");
- name_tag = OTF_tag ("name");
- cmap_tag = OTF_tag ("cmap");
- gdef_tag = OTF_tag ("GDEF");
- gsub_tag = OTF_tag ("GSUB");
- gpos_tag = OTF_tag ("GPOS");
-
- stream = make_stream ();
- if (! stream)
- return -1;
-
- internal_data->header_stream = stream;
-
- /* Size of Offset Table is 12 bytes. */
- if (setup_stream (stream, fp, 0, 12, "Offset Table") < 0)
- return -1;
- if (read_offset_table (otf, stream, &otf->offset_table) < 0)
- return -1;
-
- /* Size of each Table Directory is 16 bytes. */
- if (setup_stream (stream, fp, 12, 16 * otf->offset_table.numTables,
- "Table Directory") < 0)
- return -1;
-
- OTF_CALLOC (otf->table_dirs, otf->offset_table.numTables, " (OffsetTable)");
- for (i = 0; i < otf->offset_table.numTables; i++)
- {
- OTF_Tag tag = read_table_directory (stream, otf->table_dirs + i);
- OTF_TableInfo *table_info = NULL;
-
- if (! tag)
- return -1;
- if (tag == head_tag)
- table_info = internal_data->table_info + OTF_TABLE_TYPE_HEAD;
- else if (tag == name_tag)
- table_info = internal_data->table_info + OTF_TABLE_TYPE_NAME;
- else if (tag == cmap_tag)
- table_info = internal_data->table_info + OTF_TABLE_TYPE_CMAP;
- else if (tag == gdef_tag)
- table_info = internal_data->table_info + OTF_TABLE_TYPE_GDEF;
- else if (tag == gsub_tag)
- table_info = internal_data->table_info + OTF_TABLE_TYPE_GSUB;
- else if (tag == gpos_tag)
- table_info = internal_data->table_info + OTF_TABLE_TYPE_GPOS;
-
- if (table_info)
- {
- table_info->stream = make_stream ();
- if (setup_stream (table_info->stream, fp,
- otf->table_dirs[i].offset,
- otf->table_dirs[i].length,
- otf->table_dirs[i].name) < 0)
- return -1;
- }
- }
-
- internal_data->header_stream = NULL;
- free_stream (stream);
- return 0;
-}
-
-
\f
+/*** (1-2) "head" table */
static void *
read_head_table (OTF *otf, OTF_Stream *stream)
}
\f
+/*** (1-3) "name" table */
-static int
-read_script_list (OTF *otf, OTF_Stream *stream, long offset,
- OTF_ScriptList *list)
+static char *
+read_name (OTF *otf, OTF_Stream *stream, OTF_NameRecord *rec, int bytes)
{
- char *errfmt = "Script List%s";
- int errret = -1;
- int i, j, k;
+ char *errfmt = "nameID (%d)";
+ void *errret = NULL;
+ OTF_StreamState state;
+ char *str;
+ int i;
+ int c;
- SEEK_STREAM (stream, offset);
- READ_USHORT (stream, list->ScriptCount);
- OTF_CALLOC (list->Script, list->ScriptCount, "");
+ SAVE_STREAM (stream, state);
+ SEEK_STREAM (stream, stream->pos + rec->offset);
- for (i = 0; i < list->ScriptCount; i++)
+ if (bytes == 1)
{
- READ_TAG (stream, list->Script[i].ScriptTag);
- READ_OFFSET (stream, list->Script[i].offset);
+ OTF_MALLOC (str, rec->length + 1, (void *) rec->nameID);
+ READ_BYTES (stream, str, rec->length);
+ for (i = 0; i < rec->length; i++)
+ if (str[i] < 0)
+ str[i] = '?';
}
- for (i = 0; i < list->ScriptCount; i++)
+ else if (bytes == 2)
{
- OTF_Script *script = list->Script + i;
- long script_offset = offset + script->offset;
-
- SEEK_STREAM (stream, script_offset);
- READ_OFFSET (stream, script->DefaultLangSysOffset);
- READ_USHORT (stream, script->LangSysCount);
- OTF_MALLOC (script->LangSysRecord, script->LangSysCount, " (LangSys)");
- OTF_CALLOC (script->LangSys, script->LangSysCount, " (LangSys)");
- for (j = 0; j < script->LangSysCount; j++)
- {
- READ_TAG (stream, script->LangSysRecord[j].LangSysTag);
- READ_OFFSET (stream, script->LangSysRecord[j].LangSys);
- }
-
- if (script->DefaultLangSysOffset)
+ OTF_MALLOC (str, rec->length / 2 + 1, (void *) rec->nameID);
+ for (i = 0; i < rec->length / 2; i++)
{
- OTF_LangSys *langsys = &script->DefaultLangSys;
-
- SEEK_STREAM (stream, script_offset + script->DefaultLangSysOffset);
- READ_OFFSET (stream, langsys->LookupOrder);
- READ_USHORT (stream, langsys->ReqFeatureIndex);
- READ_USHORT (stream, langsys->FeatureCount);
- OTF_MALLOC (langsys->FeatureIndex, langsys->FeatureCount,
- " (FeatureIndex)");
- for (k = 0; k < langsys->FeatureCount; k++)
- READ_USHORT (stream, langsys->FeatureIndex[k]);
+ READ_USHORT (stream, c);
+ if (c >= 128)
+ c = '?';
+ str[i] = c;
}
-
- for (j = 0; j < script->LangSysCount; j++)
+ }
+ else if (bytes == 4)
+ {
+ OTF_MALLOC (str, rec->length / 4 + 1, (void *) rec->nameID);
+ for (i = 0; i < rec->length / 4; i++)
{
- OTF_LangSys *langsys = script->LangSys + j;
-
- SEEK_STREAM (stream,
- script_offset + script->LangSysRecord[j].LangSys);
- READ_OFFSET (stream, langsys->LookupOrder);
- READ_USHORT (stream, langsys->ReqFeatureIndex);
- READ_USHORT (stream, langsys->FeatureCount);
- OTF_MALLOC (langsys->FeatureIndex, langsys->FeatureCount,
- " (FeatureIndex)");
- for (k = 0; k < langsys->FeatureCount; k++)
- READ_USHORT (stream, langsys->FeatureIndex[k]);
+ READ_ULONG (stream, c);
+ if (c >= 128)
+ c = '?';
+ str[i] = c;
}
}
-
- return 0;
+ str[i] = '\0';
+ RESTORE_STREAM (stream, state);
+ return str;
}
-static int
-read_feature_list (OTF *otf, OTF_Stream *stream, long offset,
- OTF_FeatureList *list)
+static void *
+read_name_table (OTF *otf, OTF_Stream *stream)
{
- char *errfmt = "Feature List%s";
- int errret = -1;
- int i, j;
+ char *errfmt = "name%s";
+ void *errret = NULL;
+ OTF_name *name;
+ int i;
- READ_UINT16 (stream, list->FeatureCount);
- OTF_CALLOC (list->Feature, list->FeatureCount, "");
- for (i = 0; i < list->FeatureCount; i++)
+ OTF_CALLOC (name, 1, "");
+ READ_USHORT (stream, name->format);
+ READ_USHORT (stream, name->count);
+ READ_USHORT (stream, name->stringOffset);
+ OTF_MALLOC (name->nameRecord, name->count, "");
+ for (i = 0; i < name->count; i++)
{
- READ_TAG (stream, list->Feature[i].FeatureTag);
- READ_OFFSET (stream, list->Feature[i].offset);
+ OTF_NameRecord *rec = name->nameRecord + i;
+
+ READ_USHORT (stream, rec->platformID);
+ READ_USHORT (stream, rec->encodingID);
+ READ_USHORT (stream, rec->languageID);
+ READ_USHORT (stream, rec->nameID);
+ READ_USHORT (stream, rec->length);
+ READ_USHORT (stream, rec->offset);
}
- for (i = 0; i < list->FeatureCount; i++)
+ for (i = 0; i < name->count; i++)
{
- OTF_Feature *feature = list->Feature + i;
+ OTF_NameRecord *rec = name->nameRecord + i;
+ int nameID = rec->nameID;
- SEEK_STREAM (stream, offset + feature->offset);
- READ_OFFSET (stream, feature->FeatureParams);
- READ_UINT16 (stream, feature->LookupCount);
- OTF_MALLOC (feature->LookupListIndex, feature->LookupCount,
- " (LookupListIndex)");
- for (j = 0; j < feature->LookupCount; j++)
- READ_UINT16 (stream, feature->LookupListIndex[j]);
+ if (nameID <= OTF_max_nameID
+ && ! name->name[nameID])
+ {
+ if (rec->platformID == 0)
+ name->name[nameID] = read_name (otf, stream, rec,
+ rec->encodingID <= 3 ? 2 : 4);
+ else if (rec->platformID == 1
+ && rec->encodingID == 0)
+ name->name[nameID] = read_name (otf, stream, rec, 1);
+ else if (rec->platformID == 3
+ && (rec->encodingID == 1 || rec->encodingID == 10))
+ name->name[nameID] = read_name (otf, stream,
+ rec, rec->encodingID == 1 ? 2 : 4);
+ }
}
- return 0;
+ return name;
}
-static int read_lookup_subtable_gsub (OTF *otf, OTF_Stream *stream,
- long offset, unsigned type,
- OTF_LookupSubTableGSUB *subtable);
-static int read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream,
- long offset, unsigned type,
- OTF_LookupSubTableGPOS *subtable);
+\f
+/*** (1-4) "cmap" table */
-static int
-read_lookup_list (OTF *otf, OTF_Stream *stream, long offset,
- OTF_LookupList *list, int gsub)
+static void *
+read_cmap_table (OTF *otf, OTF_Stream *stream)
{
- char *errfmt = "Lookup List%s";
- int errret = -1;
- int i, j;
-
- SEEK_STREAM (stream, offset);
- READ_UINT16 (stream, list->LookupCount);
- OTF_CALLOC (list->Lookup, list->LookupCount, "");
+ char *errfmt = "cmap%s";
+ void *errret = NULL;
+ OTF_cmap *cmap;
+ int i;
- for (i = 0; i < list->LookupCount; i++)
- READ_OFFSET (stream, list->Lookup[i].offset);
- for (i = 0; i < list->LookupCount; i++)
+ OTF_CALLOC (cmap, 1, "");
+ READ_USHORT (stream, cmap->version);
+ READ_USHORT (stream, cmap->numTables);
+ OTF_MALLOC (cmap->EncodingRecord, cmap->numTables, "");
+ for (i = 0; i < cmap->numTables; i++)
{
- OTF_Lookup *lookup = list->Lookup + i;
+ READ_USHORT (stream, cmap->EncodingRecord[i].platformID);
+ READ_USHORT (stream, cmap->EncodingRecord[i].encodingID);
+ READ_ULONG (stream, cmap->EncodingRecord[i].offset);
+ if (cmap->EncodingRecord[i].platformID == 3
+ && cmap->EncodingRecord[i].encodingID == 1)
+ cmap->Unicode = cmap->EncodingRecord + i;
+ }
+ for (i = 0; i < cmap->numTables; i++)
+ {
+ unsigned format;
- SEEK_STREAM (stream, offset + lookup->offset);
- READ_UINT16 (stream, lookup->LookupType);
- READ_UINT16 (stream, lookup->LookupFlag);
- READ_UINT16 (stream, lookup->SubTableCount);
- OTF_MALLOC (lookup->SubTableOffset, lookup->SubTableCount,
- " (SubTableOffset)");
- if (gsub)
- OTF_CALLOC (lookup->SubTable.gsub, lookup->SubTableCount,
- " (SubTable)");
+ SEEK_STREAM (stream, cmap->EncodingRecord[i].offset);
+ READ_USHORT (stream, format);
+ cmap->EncodingRecord[i].subtable.format = format;
+ READ_USHORT (stream, cmap->EncodingRecord[i].subtable.length);
+ if (format == 8 || format == 10 || format == 12)
+ {
+ READ_ULONG (stream, cmap->EncodingRecord[i].subtable.length);
+ READ_ULONG (stream, cmap->EncodingRecord[i].subtable.language);
+ }
else
- OTF_CALLOC (lookup->SubTable.gpos, lookup->SubTableCount,
- " (SubTable)");
- for (j = 0; j < lookup->SubTableCount; j++)
- READ_OFFSET (stream, lookup->SubTableOffset[j]);
- for (j = 0; j < lookup->SubTableCount; j++)
{
- long this_offset
- = offset + lookup->offset + lookup->SubTableOffset[j];
+ READ_USHORT (stream, cmap->EncodingRecord[i].subtable.language);
+ }
+ switch (format)
+ {
+ case 0:
+ {
+ OTF_MALLOC (cmap->EncodingRecord[i].subtable.f.f0, 1,
+ " (EncodingRecord)");
+ READ_BYTES (stream,
+ cmap->EncodingRecord[i].subtable.f.f0->glyphIdArray,
+ 256);
+ }
+ break;
- if (gsub
- ? read_lookup_subtable_gsub (otf, stream, this_offset,
- lookup->LookupType,
- lookup->SubTable.gsub + j) < 0
- : read_lookup_subtable_gpos (otf, stream, this_offset,
- lookup->LookupType,
- lookup->SubTable.gpos + j) < 0)
- return errret;
+ case 2:
+ break;
+
+ case 4:
+ {
+ OTF_EncodingSubtable4 *sub4;
+ int segCount;
+ int j;
+ unsigned dummy;
+
+ OTF_MALLOC (sub4, 1, " (EncodingSubtable4)");
+ cmap->EncodingRecord[i].subtable.f.f4 = sub4;
+ READ_USHORT (stream, sub4->segCountX2);
+ segCount = sub4->segCountX2 / 2;
+ READ_USHORT (stream, sub4->searchRange);
+ READ_USHORT (stream, sub4->entrySelector);
+ READ_USHORT (stream, sub4->rangeShift);
+ OTF_MALLOC (sub4->segments, segCount, " (segCount)");
+ for (j = 0; j < segCount; j++)
+ READ_USHORT (stream, sub4->segments[j].endCount);
+ READ_USHORT (stream, dummy);
+ for (j = 0; j < segCount; j++)
+ READ_USHORT (stream, sub4->segments[j].startCount);
+ for (j = 0; j < segCount; j++)
+ READ_SHORT (stream, sub4->segments[j].idDelta);
+ for (j = 0; j < segCount; j++)
+ {
+ unsigned off;
+ unsigned rest = 2 * (segCount - j);
+
+ READ_USHORT (stream, off);
+ if (off == 0)
+ sub4->segments[j].idRangeOffset = 0xFFFF;
+ else
+ sub4->segments[j].idRangeOffset = (off - rest) / 2;
+ }
+ j = (cmap->EncodingRecord[i].subtable.length
+ - (14 + 2 * (segCount * 4 + 1)));
+ sub4->GlyphCount = j / 2;
+ OTF_MALLOC (sub4->glyphIdArray, sub4->GlyphCount, " (GlyphCount)");
+ for (j = 0; j < sub4->GlyphCount; j++)
+ READ_USHORT (stream, sub4->glyphIdArray[j]);
+ }
}
}
-
- return 0;
+ return cmap;
}
+\f
+/*** (1-5) Structures common to GDEF, GSUB, and GPOS */
/* Read Glyph-IDs from STREAM. Allocate memory for IDS, and store the
Glyph-IDs there. If COUNT is negative, read the number of
return 0;
}
-static unsigned
-read_lookup_record_list (OTF *otf, OTF_Stream *stream,
- OTF_LookupRecord **record, int count)
+\f
+/*** (1-6) "GDEF" table */
+
+static int
+read_attach_list (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_AttachList *list)
{
- char *errfmt = "LookupRecord%s";
- unsigned errret = 0;
- int i;
+ char *errfmt = "AttachList%s";
+ int errret = -1;
+ int i, j;
- if (count < 0)
- READ_UINT16 (stream, count);
- if (! count)
- OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
- OTF_MALLOC (*record, count, "");
- for (i = 0; i < count; i++)
+ if (read_coverage (otf, stream, offset, &list->Coverage) < 0)
+ return -1;
+ READ_UINT16 (stream, list->GlyphCount);
+ OTF_MALLOC (list->AttachPoint, list->GlyphCount, "");
+ for (i = 0; i < list->GlyphCount; i++)
+ READ_OFFSET (stream, list->AttachPoint[i].offset);
+ for (i = 0; i < list->GlyphCount; i++)
{
- READ_UINT16 (stream, (*record)[i].SequenceIndex);
- READ_UINT16 (stream, (*record)[i].LookupListIndex);
+ int count;
+
+ SEEK_STREAM (stream, offset + list->AttachPoint[i].offset);
+ READ_UINT16 (stream, count);
+ list->AttachPoint[i].PointCount = count;
+ OTF_MALLOC (list->AttachPoint[i].PointIndex, count, " (PointIndex)");
+ for (j = 0; j < count; j++)
+ READ_UINT16 (stream, list->AttachPoint[i].PointIndex[j]);
}
- return count;
+ return 0;
}
-static unsigned
-read_rule_list (OTF *otf, OTF_Stream *stream, long offset, OTF_Rule **rule)
+static int
+read_caret_value (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_CaretValue *caret)
{
- char *errfmt = "List of Rule%s";
- unsigned errret = 0;
- OTF_StreamState state;
- unsigned count;
- int i;
+ char *errfmt = "CaretValue%s";
+ int errret = -1;
- READ_UINT16 (stream, count);
- if (! count)
- OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
- OTF_MALLOC (*rule, count, "");
- for (i = 0; i < count; i++)
- {
- READ_OFFSET (stream, (*rule)[i].offset);
- if (! (*rule)[i].offset)
- OTF_ERROR (OTF_ERROR_TABLE, " (zero offset)");
- }
- SAVE_STREAM (stream, state);
- for (i = 0; i < count; i++)
+ SEEK_STREAM (stream, offset + caret->offset);
+ READ_UINT16 (stream, caret->CaretValueFormat);
+ if (caret->CaretValueFormat == 1)
+ READ_INT16 (stream, caret->f.f1.Coordinate);
+ else if (caret->CaretValueFormat == 2)
+ READ_UINT16 (stream, caret->f.f2.CaretValuePoint);
+ else if (caret->CaretValueFormat == 3)
{
- SEEK_STREAM (stream, offset + (*rule)[i].offset);
- READ_UINT16 (stream, (*rule)[i].GlyphCount);
- if ((*rule)[i].GlyphCount == 0)
- OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
- READ_UINT16 (stream, (*rule)[i].LookupCount);
- if (read_glyph_ids (otf, stream, &(*rule)[i].Input, 0,
- (*rule)[i].GlyphCount) < 0)
- return errret;
- if (read_lookup_record_list (otf, stream, &(*rule)[i].LookupRecord,
- (*rule)[i].LookupCount) == 0)
- return errret;
+ READ_INT16 (stream, caret->f.f3.Coordinate);
+ if (read_device_table (otf, stream, offset + caret->offset,
+ &caret->f.f3.DeviceTable) < 0)
+ return -1;
}
- RESTORE_STREAM (stream, state);
- return count;
+ else
+ OTF_ERROR (OTF_ERROR_TABLE, " (Invalid format)");
+ return 0;
}
-
-static unsigned
-read_rule_set_list (OTF *otf, OTF_Stream *stream, long offset,
- OTF_RuleSet **set)
+static int
+read_lig_caret_list (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_LigCaretList *list)
{
- char *errfmt = "List of RuleSet%s";
- unsigned errret = 0;
- OTF_StreamState state;
- unsigned count;
- int i;
-
+ char *errfmt = "LigCaretList%s";
+ int errret = -1;
+ int i, j;
+
+ if (read_coverage (otf, stream, offset, &list->Coverage) < 0)
+ return -1;
+ READ_UINT16 (stream, list->LigGlyphCount);
+ OTF_MALLOC (list->LigGlyph, list->LigGlyphCount, "");
+ for (i = 0; i < list->LigGlyphCount; i++)
+ READ_OFFSET (stream, list->LigGlyph[i].offset);
+ for (i = 0; i < list->LigGlyphCount; i++)
+ {
+ int count;
+
+ SEEK_STREAM (stream, offset + list->LigGlyph[i].offset);
+ READ_UINT16 (stream, count);
+ list->LigGlyph[i].CaretCount = count;
+ OTF_MALLOC (list->LigGlyph[i].CaretValue, count, " (CaretValue)");
+ for (j = 0; j < count; j++)
+ READ_OFFSET (stream, list->LigGlyph[i].CaretValue[j].offset);
+ for (j = 0; j < count; j++)
+ if (read_caret_value (otf, stream, offset + list->LigGlyph[i].offset,
+ &list->LigGlyph[i].CaretValue[j]) < 0)
+ return -1;
+ }
+ return 0;
+}
+
+static int
+read_gdef_header (OTF_Stream *stream, OTF_GDEFHeader *header)
+{
+ int errret = -1;
+
+ READ_FIXED (stream, header->Version);
+ READ_OFFSET (stream, header->GlyphClassDef);
+ READ_OFFSET (stream, header->AttachList);
+ READ_OFFSET (stream, header->LigCaretList);
+ READ_OFFSET (stream, header->MarkAttachClassDef);
+ return 0;
+}
+
+static void *
+read_gdef_table (OTF *otf, OTF_Stream *stream)
+{
+ char *errfmt = "GDEF%s";
+ void *errret = NULL;
+ OTF_GDEF *gdef;
+
+ OTF_CALLOC (gdef, 1, "");
+ read_gdef_header (stream, (OTF_GDEFHeader *) &gdef->header);
+ if (gdef->header.GlyphClassDef)
+ {
+ gdef->glyph_class_def.offset = gdef->header.GlyphClassDef;
+ read_class_def_without_offset (otf, stream, &gdef->glyph_class_def);
+ }
+ if (gdef->header.AttachList)
+ read_attach_list (otf, stream, gdef->header.AttachList,
+ &gdef->attach_list);
+ if (gdef->header.LigCaretList)
+ read_lig_caret_list (otf, stream, gdef->header.LigCaretList,
+ &gdef->lig_caret_list);
+ if (gdef->header.MarkAttachClassDef)
+ {
+ gdef->mark_attach_class_def.offset = gdef->header.MarkAttachClassDef;
+ read_class_def_without_offset (otf, stream, &gdef->mark_attach_class_def);
+ }
+
+ return gdef;
+}
+
+\f
+/*** (1-7) Structures for ScriptList, FeatureList, and LookupList */
+
+static int
+read_script_list (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_ScriptList *list)
+{
+ char *errfmt = "Script List%s";
+ int errret = -1;
+ int i, j, k;
+
+ SEEK_STREAM (stream, offset);
+ READ_USHORT (stream, list->ScriptCount);
+ OTF_CALLOC (list->Script, list->ScriptCount, "");
+
+ for (i = 0; i < list->ScriptCount; i++)
+ {
+ READ_TAG (stream, list->Script[i].ScriptTag);
+ READ_OFFSET (stream, list->Script[i].offset);
+ }
+ for (i = 0; i < list->ScriptCount; i++)
+ {
+ OTF_Script *script = list->Script + i;
+ long script_offset = offset + script->offset;
+
+ SEEK_STREAM (stream, script_offset);
+ READ_OFFSET (stream, script->DefaultLangSysOffset);
+ READ_USHORT (stream, script->LangSysCount);
+ OTF_MALLOC (script->LangSysRecord, script->LangSysCount, " (LangSys)");
+ OTF_CALLOC (script->LangSys, script->LangSysCount, " (LangSys)");
+ for (j = 0; j < script->LangSysCount; j++)
+ {
+ READ_TAG (stream, script->LangSysRecord[j].LangSysTag);
+ READ_OFFSET (stream, script->LangSysRecord[j].LangSys);
+ }
+
+ if (script->DefaultLangSysOffset)
+ {
+ OTF_LangSys *langsys = &script->DefaultLangSys;
+
+ SEEK_STREAM (stream, script_offset + script->DefaultLangSysOffset);
+ READ_OFFSET (stream, langsys->LookupOrder);
+ READ_USHORT (stream, langsys->ReqFeatureIndex);
+ READ_USHORT (stream, langsys->FeatureCount);
+ OTF_MALLOC (langsys->FeatureIndex, langsys->FeatureCount,
+ " (FeatureIndex)");
+ for (k = 0; k < langsys->FeatureCount; k++)
+ READ_USHORT (stream, langsys->FeatureIndex[k]);
+ }
+
+ for (j = 0; j < script->LangSysCount; j++)
+ {
+ OTF_LangSys *langsys = script->LangSys + j;
+
+ SEEK_STREAM (stream,
+ script_offset + script->LangSysRecord[j].LangSys);
+ READ_OFFSET (stream, langsys->LookupOrder);
+ READ_USHORT (stream, langsys->ReqFeatureIndex);
+ READ_USHORT (stream, langsys->FeatureCount);
+ OTF_MALLOC (langsys->FeatureIndex, langsys->FeatureCount,
+ " (FeatureIndex)");
+ for (k = 0; k < langsys->FeatureCount; k++)
+ READ_USHORT (stream, langsys->FeatureIndex[k]);
+ }
+ }
+
+ return 0;
+}
+
+static int
+read_feature_list (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_FeatureList *list)
+{
+ char *errfmt = "Feature List%s";
+ int errret = -1;
+ int i, j;
+
+ READ_UINT16 (stream, list->FeatureCount);
+ OTF_CALLOC (list->Feature, list->FeatureCount, "");
+ for (i = 0; i < list->FeatureCount; i++)
+ {
+ READ_TAG (stream, list->Feature[i].FeatureTag);
+ READ_OFFSET (stream, list->Feature[i].offset);
+ }
+ for (i = 0; i < list->FeatureCount; i++)
+ {
+ OTF_Feature *feature = list->Feature + i;
+
+ SEEK_STREAM (stream, offset + feature->offset);
+ READ_OFFSET (stream, feature->FeatureParams);
+ READ_UINT16 (stream, feature->LookupCount);
+ OTF_MALLOC (feature->LookupListIndex, feature->LookupCount,
+ " (LookupListIndex)");
+ for (j = 0; j < feature->LookupCount; j++)
+ READ_UINT16 (stream, feature->LookupListIndex[j]);
+ }
+
+ return 0;
+}
+
+static int read_lookup_subtable_gsub (OTF *otf, OTF_Stream *stream,
+ long offset, unsigned type,
+ OTF_LookupSubTableGSUB *subtable);
+static int read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream,
+ long offset, unsigned type,
+ OTF_LookupSubTableGPOS *subtable);
+
+static int
+read_lookup_list (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_LookupList *list, int gsubp)
+{
+ char *errfmt = "Lookup List%s";
+ int errret = -1;
+ int i, j;
+
+ SEEK_STREAM (stream, offset);
+ READ_UINT16 (stream, list->LookupCount);
+ OTF_CALLOC (list->Lookup, list->LookupCount, "");
+
+ for (i = 0; i < list->LookupCount; i++)
+ READ_OFFSET (stream, list->Lookup[i].offset);
+ for (i = 0; i < list->LookupCount; i++)
+ {
+ OTF_Lookup *lookup = list->Lookup + i;
+
+ SEEK_STREAM (stream, offset + lookup->offset);
+ READ_UINT16 (stream, lookup->LookupType);
+ READ_UINT16 (stream, lookup->LookupFlag);
+ READ_UINT16 (stream, lookup->SubTableCount);
+ OTF_MALLOC (lookup->SubTableOffset, lookup->SubTableCount,
+ " (SubTableOffset)");
+ if (gsubp)
+ OTF_CALLOC (lookup->SubTable.gsub, lookup->SubTableCount,
+ " (SubTable)");
+ else
+ OTF_CALLOC (lookup->SubTable.gpos, lookup->SubTableCount,
+ " (SubTable)");
+ for (j = 0; j < lookup->SubTableCount; j++)
+ READ_OFFSET (stream, lookup->SubTableOffset[j]);
+ for (j = 0; j < lookup->SubTableCount; j++)
+ {
+ long this_offset
+ = offset + lookup->offset + lookup->SubTableOffset[j];
+
+ if (gsubp
+ ? read_lookup_subtable_gsub (otf, stream, this_offset,
+ lookup->LookupType,
+ lookup->SubTable.gsub + j) < 0
+ : read_lookup_subtable_gpos (otf, stream, this_offset,
+ lookup->LookupType,
+ lookup->SubTable.gpos + j) < 0)
+ return errret;
+ }
+ }
+
+ return 0;
+}
+
+\f
+/*** (1-8) Structures common to GSUB and GPOS */
+
+static unsigned
+read_lookup_record_list (OTF *otf, OTF_Stream *stream,
+ OTF_LookupRecord **record, int count)
+{
+ char *errfmt = "LookupRecord%s";
+ unsigned errret = 0;
+ int i;
+
+ if (count < 0)
+ READ_UINT16 (stream, count);
+ if (! count)
+ OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
+ OTF_MALLOC (*record, count, "");
+ for (i = 0; i < count; i++)
+ {
+ READ_UINT16 (stream, (*record)[i].SequenceIndex);
+ READ_UINT16 (stream, (*record)[i].LookupListIndex);
+ }
+ return count;
+}
+
+static unsigned
+read_rule_list (OTF *otf, OTF_Stream *stream, long offset, OTF_Rule **rule)
+{
+ char *errfmt = "List of Rule%s";
+ unsigned errret = 0;
+ OTF_StreamState state;
+ unsigned count;
+ int i;
+
+ READ_UINT16 (stream, count);
+ if (! count)
+ OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
+ OTF_MALLOC (*rule, count, "");
+ for (i = 0; i < count; i++)
+ {
+ READ_OFFSET (stream, (*rule)[i].offset);
+ if (! (*rule)[i].offset)
+ OTF_ERROR (OTF_ERROR_TABLE, " (zero offset)");
+ }
+ SAVE_STREAM (stream, state);
+ for (i = 0; i < count; i++)
+ {
+ SEEK_STREAM (stream, offset + (*rule)[i].offset);
+ READ_UINT16 (stream, (*rule)[i].GlyphCount);
+ if ((*rule)[i].GlyphCount == 0)
+ OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
+ READ_UINT16 (stream, (*rule)[i].LookupCount);
+ if (read_glyph_ids (otf, stream, &(*rule)[i].Input, 0,
+ (*rule)[i].GlyphCount) < 0)
+ return errret;
+ if (read_lookup_record_list (otf, stream, &(*rule)[i].LookupRecord,
+ (*rule)[i].LookupCount) == 0)
+ return errret;
+ }
+ RESTORE_STREAM (stream, state);
+ return count;
+}
+
+
+static unsigned
+read_rule_set_list (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_RuleSet **set)
+{
+ char *errfmt = "List of RuleSet%s";
+ unsigned errret = 0;
+ OTF_StreamState state;
+ unsigned count;
+ int i;
+
READ_UINT16 (stream, count);
if (! count)
OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
static unsigned
read_chain_class_set_list (OTF *otf, OTF_Stream *stream, long offset,
OTF_ChainClassSet **set)
-{
- char *errfmt = "ChainClassSet%s";
- unsigned errret = 0;
- OTF_StreamState state;
- unsigned count;
- int i;
-
- READ_UINT16 (stream, count);
- if (! count)
- OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
- OTF_MALLOC (*set, count, "");
- for (i = 0; i < count; i++)
- /* Offset may be zero. */
- READ_OFFSET (stream, (*set)[i].offset);
- SAVE_STREAM (stream, state);
- for (i = 0; i < count; i++)
- if ((*set)[i].offset)
- {
- SEEK_STREAM (stream, offset + (*set)[i].offset);
- (*set)[i].ChainClassRuleCnt
- = read_chain_class_rule_list (otf, stream, offset + (*set)[i].offset,
- &(*set)[i].ChainClassRule);
- if (! (*set)[i].ChainClassRuleCnt)
- return errret;
- }
- RESTORE_STREAM (stream, state);
- return count;
-}
-
-\f
-/* GSUB */
-
-static void *
-read_gsub_table (OTF *otf, OTF_Stream *stream)
-{
- char *errfmt = "GSUB%s";
- void *errret = NULL;
- OTF_GSUB *gsub;
-
- OTF_CALLOC (gsub, 1, "");
- READ_FIXED (stream, gsub->Version);
- READ_OFFSET (stream, gsub->ScriptList.offset);
- READ_OFFSET (stream, gsub->FeatureList.offset);
- READ_OFFSET (stream, gsub->LookupList.offset);
-
- if (read_script_list (otf, stream, gsub->ScriptList.offset,
- &gsub->ScriptList) < 0
- || read_feature_list (otf, stream, gsub->FeatureList.offset,
- &gsub->FeatureList) < 0
- || read_lookup_list (otf, stream, gsub->LookupList.offset,
- &gsub->LookupList, 1) < 0)
- return NULL;
- return gsub;
-}
-
-static unsigned
-read_sequence (OTF *otf, OTF_Stream *stream, long offset, OTF_Sequence **seq)
-{
- char *errfmt = "Sequence%s";
- unsigned errret = 0;
- unsigned count;
- int i;
-
- READ_UINT16 (stream, count);
- if (! count)
- OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
- OTF_MALLOC (*seq, count, "");
- for (i = 0; i < count; i++)
- READ_OFFSET (stream, (*seq)[i].offset);
- for (i = 0; i < count; i++)
- {
- SEEK_STREAM (stream, offset + (*seq)[i].offset);
- (*seq)[i].GlyphCount = read_glyph_ids (otf, stream,
- &(*seq)[i].Substitute, 0, -1);
- if (! (*seq)[i].GlyphCount)
- return 0;
- }
- return count;
-}
-
-static int
-read_ligature (OTF *otf, OTF_Stream *stream, long offset,
- OTF_Ligature **ligature)
-{
- char *errfmt = "Ligature%s";
- int errret = -1;
- int count;
- int i;
-
- READ_UINT16 (stream, count);
- if (! count)
- return 0;
- OTF_MALLOC (*ligature, count, "");
- for (i = 0; i < count; i++)
- READ_OFFSET (stream, (*ligature)[i].offset);
- for (i = 0; i < count; i++)
- {
- SEEK_STREAM (stream, offset + (*ligature)[i].offset);
- READ_GLYPHID (stream, (*ligature)[i].LigGlyph);
- (*ligature)[i].CompCount
- = read_glyph_ids (otf, stream, &(*ligature)[i].Component, -1, -1);
- if (! (*ligature)[i].CompCount)
- return -1;
- }
- return count;
-}
-
-static unsigned
-read_ligature_set_list (OTF *otf, OTF_Stream *stream, long offset,
- OTF_LigatureSet **ligset)
-{
- char *errfmt = "LigatureSet%s";
- int errret = 0;
- int count;
- int i;
-
- READ_UINT16 (stream, count);
- if (! count)
- return errret;
- OTF_MALLOC (*ligset, count, "");
- for (i = 0; i < count; i++)
- READ_OFFSET (stream, (*ligset)[i].offset);
- for (i = 0; i < count; i++)
- {
- int lig_count;
-
- SEEK_STREAM (stream, offset + (*ligset)[i].offset);
- lig_count = read_ligature (otf, stream, offset + (*ligset)[i].offset,
- &(*ligset)[i].Ligature);
- if (lig_count < 0)
- return errret;
- (*ligset)[i].LigatureCount = (unsigned) lig_count;
- }
- return count;
-}
-
-static unsigned
-read_alternate_set_list (OTF *otf, OTF_Stream *stream, long offset,
- OTF_AlternateSet **altset)
-{
- char *errfmt = "AlternateSet%s";
- int errret = -1;
+{
+ char *errfmt = "ChainClassSet%s";
+ unsigned errret = 0;
+ OTF_StreamState state;
unsigned count;
int i;
READ_UINT16 (stream, count);
if (! count)
OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
- OTF_MALLOC (*altset, count, "");
+ OTF_MALLOC (*set, count, "");
for (i = 0; i < count; i++)
- READ_OFFSET (stream, (*altset)[i].offset);
+ /* Offset may be zero. */
+ READ_OFFSET (stream, (*set)[i].offset);
+ SAVE_STREAM (stream, state);
for (i = 0; i < count; i++)
- {
- int alt_count;
-
- SEEK_STREAM (stream, offset + (*altset)[i].offset);
- alt_count = read_glyph_ids (otf, stream, &(*altset)[i].Alternate, 0, -1);
- if (alt_count < 0)
- return errret;
- (*altset)[i].GlyphCount = (unsigned) alt_count;
- }
+ if ((*set)[i].offset)
+ {
+ SEEK_STREAM (stream, offset + (*set)[i].offset);
+ (*set)[i].ChainClassRuleCnt
+ = read_chain_class_rule_list (otf, stream, offset + (*set)[i].offset,
+ &(*set)[i].ChainClassRule);
+ if (! (*set)[i].ChainClassRuleCnt)
+ return errret;
+ }
+ RESTORE_STREAM (stream, state);
return count;
}
-static int
-read_lookup_subtable_gsub (OTF *otf, OTF_Stream *stream, long offset,
- unsigned type, OTF_LookupSubTableGSUB *subtable)
+static int
+read_context1 (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_Coverage *coverage,OTF_Context1 *context1)
{
- char errfmt[256];
- int errret = -1;
- int count;
-
- SEEK_STREAM (stream, offset);
- READ_UINT16 (stream, subtable->Format);
- sprintf (errfmt, "GSUB Lookup %d-%d%%s", type, subtable->Format);
- switch (type)
- {
- case 1:
- if (subtable->Format == 1)
- {
- if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0)
- return -1;
- READ_INT16 (stream, subtable->u.single1.DeltaGlyphID);
- }
- else if (subtable->Format == 2)
- {
- if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0)
- return -1;
- subtable->u.single2.GlyphCount
- = read_glyph_ids (otf, stream, &subtable->u.single2.Substitute,
- 0, -1);
- if (! subtable->u.single2.GlyphCount)
- return -1;
- }
- else
- OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
- break;
-
- case 2:
- if (subtable->Format == 1)
- {
- read_coverage (otf, stream, offset, &subtable->Coverage);
- subtable->u.multiple1.SequenceCount
- = read_sequence (otf, stream, offset,
- &subtable->u.multiple1.Sequence);
- }
- else
- OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
- break;
-
- case 3:
- if (subtable->Format == 1)
- {
- if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0)
- return -1;
- subtable->u.alternate1.AlternateSetCount
- = read_alternate_set_list (otf, stream, offset,
- &subtable->u.alternate1.AlternateSet);
- if (! subtable->u.alternate1.AlternateSetCount)
- return -1;
- }
- else
- OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
- break;
-
- case 4:
- if (subtable->Format == 1)
- {
- if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0)
- return -1;
- subtable->u.ligature1.LigSetCount
- = read_ligature_set_list (otf, stream, offset,
- &subtable->u.ligature1.LigatureSet);
- if (! subtable->u.ligature1.LigSetCount)
- return -1;
- }
- else
- OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
- break;
-
- case 5:
- if (subtable->Format == 1)
- {
- OTF_GSUB_Context1 *context1 = &subtable->u.context1;
-
- read_coverage (otf, stream, offset, &subtable->Coverage);
- context1->SubRuleSetCount
- = read_rule_set_list (otf, stream, offset, &context1->SubRuleSet);
- }
- else if (subtable->Format == 2)
- {
- OTF_GSUB_Context2 *context2 = &subtable->u.context2;
-
- read_coverage (otf, stream, offset, &subtable->Coverage);
- read_class_def (otf, stream, offset, &context2->ClassDef);
- context2->SubClassSetCnt
- = read_class_set_list (otf, stream, offset, &context2->SubClassSet);
- }
- else if (subtable->Format == 3)
- {
- OTF_GSUB_Context3 *context3 = &subtable->u.context3;
-
- READ_USHORT (stream, context3->GlyphCount);
- if (context3->GlyphCount < 0)
- OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
- READ_USHORT (stream, context3->SubstCount);
- if (read_coverage_list (otf, stream, offset,
- &context3->Coverage,
- context3->GlyphCount) < 0)
- return -1;
- if (read_lookup_record_list (otf, stream,
- &context3->LookupRecord,
- context3->SubstCount) < 0)
- return -1;
- }
- else
- OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
- break;
-
- case 6:
- if (subtable->Format == 1)
- {
- OTF_GSUB_ChainContext1 *chain_context1 = &subtable->u.chain_context1;
-
- read_coverage (otf, stream, offset, &subtable->Coverage);
- chain_context1->ChainSubRuleSetCount
- = read_chain_rule_set_list (otf, stream, offset,
- &chain_context1->ChainSubRuleSet);
- }
- else if (subtable->Format == 2)
- {
- OTF_GSUB_ChainContext2 *chain_context2 = &subtable->u.chain_context2;
-
- read_coverage (otf, stream, offset, &subtable->Coverage);
- read_class_def (otf, stream, offset, &chain_context2->Backtrack);
- read_class_def (otf, stream, offset, &chain_context2->Input);
- read_class_def (otf, stream, offset, &chain_context2->LookAhead);
- chain_context2->ChainSubClassSetCnt
- = read_chain_class_set_list (otf, stream, offset,
- &chain_context2->ChainSubClassSet);
- }
- else if (subtable->Format == 3)
- {
- OTF_GSUB_ChainContext3 *chain_context3 = &subtable->u.chain_context3;
-
- count = read_coverage_list (otf, stream, offset,
- &chain_context3->Backtrack, -1);
- if (count < 0)
- return -1;
- chain_context3->BacktrackGlyphCount = (unsigned) count;
- count = read_coverage_list (otf, stream, offset,
- &chain_context3->Input, -1);
- if (count <= 0)
- return -1;
- chain_context3->InputGlyphCount = (unsigned) count;
- subtable->Coverage = chain_context3->Input[0];
- count = read_coverage_list (otf, stream, offset,
- &chain_context3->LookAhead, -1);
- chain_context3->LookaheadGlyphCount = (unsigned) count;
- chain_context3->SubstCount
- = read_lookup_record_list (otf, stream,
- &chain_context3->LookupRecord, -1);
- }
- else
- OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
- break;
-
- case 7:
- case 8:
- OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
- break;
-
- default:
- OTF_ERROR (OTF_ERROR_TABLE, " (Invalid LookupType)");
- }
+ if (read_coverage (otf, stream, offset, coverage) < 0)
+ return -1;
+ context1->RuleSetCount
+ = read_rule_set_list (otf, stream, offset, &context1->RuleSet);
+ if (! context1->RuleSetCount)
+ return -1;
return 0;
}
-\f
-/* GPOS */
+static int
+read_context2 (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_Coverage *coverage,OTF_Context2 *context2)
+{
+ if (read_coverage (otf, stream, offset, coverage) < 0
+ || read_class_def (otf, stream, offset, &context2->ClassDef) < 0)
+ return -1;
+ context2->ClassSetCnt
+ = read_class_set_list (otf, stream, offset, &context2->ClassSet);
+ if (! context2->ClassSetCnt)
+ return -1;
+ return 0;
+}
static int
-read_value_record (OTF *otf, OTF_Stream *stream, long offset,
- enum OTF_ValueFormat bit, OTF_ValueRecord *value_record)
+read_context3 (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_Coverage *coverage,OTF_Context3 *context3)
{
+ char *errfmt = "Context1%s";
int errret = -1;
- OTF_StreamState state;
- int size, i;
-
- if (! bit)
- return 0;
- for (i = 0, size = 0; i < 8; i++)
- if (bit & (1 << i))
- size += 2;
- if (bit & OTF_XPlacement)
- READ_INT16 (stream, value_record->XPlacement);
- if (bit & OTF_XPlacement)
- READ_INT16 (stream, value_record->YPlacement);
- if (bit & OTF_XAdvance)
- READ_INT16 (stream, value_record->XAdvance);
- if (bit & OTF_YAdvance)
- READ_INT16 (stream, value_record->YAdvance);
- if (bit & OTF_XPlaDevice)
- READ_OFFSET (stream, value_record->XPlaDevice.offset);
- if (bit & OTF_YPlaDevice)
- READ_OFFSET (stream, value_record->YPlaDevice.offset);
- if (bit & OTF_XAdvDevice)
- READ_OFFSET (stream, value_record->XAdvDevice.offset);
- if (bit & OTF_YAdvDevice)
- READ_OFFSET (stream, value_record->YAdvDevice.offset);
- SAVE_STREAM (stream, state);
- if (value_record->XPlaDevice.offset)
- {
- if (read_device_table (otf, stream, offset, &value_record->XPlaDevice) < 0)
- return -1;
- }
- if (value_record->YPlaDevice.offset)
- {
- if (read_device_table (otf, stream, offset, &value_record->YPlaDevice) < 0)
- return -1;
- }
- if (value_record->XAdvDevice.offset)
- {
- if (read_device_table (otf, stream, offset, &value_record->XAdvDevice) < 0)
- return -1;
- }
- if (value_record->YAdvDevice.offset)
- {
- if (read_device_table (otf, stream, offset, &value_record->YAdvDevice) < 0)
- return -1;
- }
- RESTORE_STREAM (stream, state);
+ READ_USHORT (stream, context3->GlyphCount);
+ if (context3->GlyphCount < 0)
+ OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
+ READ_USHORT (stream, context3->LookupCount);
+ if (read_coverage_list (otf, stream, offset, &context3->Coverage,
+ context3->GlyphCount) < 0)
+ return errret;
+ if (read_lookup_record_list (otf, stream, &context3->LookupRecord,
+ context3->LookupCount) < 0)
+ return errret;
return 0;
}
+static int
+read_chain_context1 (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_Coverage *coverage, OTF_ChainContext1 *chain_context1)
+{
+ if (read_coverage (otf, stream, offset, coverage) < 0)
+ return -1;
+ chain_context1->ChainRuleSetCount
+ = read_chain_rule_set_list (otf, stream, offset,
+ &chain_context1->ChainRuleSet);
+ if (! chain_context1->ChainRuleSetCount)
+ return -1;
+ return 0;
+}
static int
-read_anchor (OTF *otf, OTF_Stream *stream, long offset, OTF_Anchor *anchor)
+read_chain_context2 (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_Coverage *coverage, OTF_ChainContext2 *chain_context2)
{
- char *errfmt = "Anchor%s";
- int errret = -1;
+ if (read_coverage (otf, stream, offset, coverage) < 0
+ || read_class_def (otf, stream, offset,
+ &chain_context2->BacktrackClassDef) < 0
+ || read_class_def (otf, stream, offset,
+ &chain_context2->InputClassDef) < 0
+ || read_class_def (otf, stream, offset,
+ &chain_context2->LookaheadClassDef) < 0)
+ return -1;
+ chain_context2->ChainClassSetCnt
+ = read_chain_class_set_list (otf, stream, offset,
+ &chain_context2->ChainClassSet);
+ if (! chain_context2->ChainClassSetCnt)
+ return -1;
+ return 0;
+}
- SEEK_STREAM (stream, offset + anchor->offset);
- READ_UINT16 (stream, anchor->AnchorFormat);
- READ_INT16 (stream, anchor->XCoordinate);
- READ_INT16 (stream, anchor->YCoordinate);
- if (anchor->AnchorFormat == 1)
- ;
- else if (anchor->AnchorFormat == 2)
- {
- READ_UINT16 (stream, anchor->f.f1.AnchorPoint);
- }
- else if (anchor->AnchorFormat == 3)
- {
- READ_OFFSET (stream, anchor->f.f2.XDeviceTable.offset);
- READ_OFFSET (stream, anchor->f.f2.YDeviceTable.offset);
- if (anchor->f.f2.XDeviceTable.offset)
- {
- if (read_device_table (otf, stream, offset + anchor->offset,
- &anchor->f.f2.XDeviceTable) < 0)
- return -1;
- }
- if (anchor->f.f2.YDeviceTable.offset)
- {
- if (read_device_table (otf, stream, offset + anchor->offset,
- &anchor->f.f2.YDeviceTable) < 0)
- return -1;
- }
- }
- else
- OTF_ERROR (OTF_ERROR_TABLE, " (invalid format)");
+static int
+read_chain_context3 (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_Coverage *coverage, OTF_ChainContext3 *chain_context3)
+{
+ int count;
+ count = read_coverage_list (otf, stream, offset,
+ &chain_context3->Backtrack, -1);
+ if (count < 0)
+ return -1;
+ chain_context3->BacktrackGlyphCount = (unsigned) count;
+ count = read_coverage_list (otf, stream, offset,
+ &chain_context3->Input, -1);
+ if (count <= 0)
+ return -1;
+ chain_context3->InputGlyphCount = (unsigned) count;
+ *coverage = chain_context3->Input[0];
+ count = read_coverage_list (otf, stream, offset,
+ &chain_context3->LookAhead, -1);
+ chain_context3->LookaheadGlyphCount = (unsigned) count;
+ chain_context3->LookupCount
+ = read_lookup_record_list (otf, stream,
+ &chain_context3->LookupRecord, -1);
return 0;
}
-static int
-read_mark_array (OTF *otf, OTF_Stream *stream, long offset,
- OTF_MarkArray *array)
+static void *
+read_gsub_gpos_table (OTF *otf, OTF_Stream *stream, int gsubp)
{
- char *errfmt = "MarkArray%s";
- int errret = -1;
- OTF_StreamState state;
+ char *errfmt = gsubp ? "GSUB%s" : "GPOS%s";
+ void *errret = NULL;
+ OTF_GSUB_GPOS *gsub_gpos;
+
+ OTF_CALLOC (gsub_gpos, 1, "");
+ READ_FIXED (stream, gsub_gpos->Version);
+ READ_OFFSET (stream, gsub_gpos->ScriptList.offset);
+ READ_OFFSET (stream, gsub_gpos->FeatureList.offset);
+ READ_OFFSET (stream, gsub_gpos->LookupList.offset);
+
+ if (read_script_list (otf, stream, gsub_gpos->ScriptList.offset,
+ &gsub_gpos->ScriptList) < 0
+ || read_feature_list (otf, stream, gsub_gpos->FeatureList.offset,
+ &gsub_gpos->FeatureList) < 0
+ || read_lookup_list (otf, stream, gsub_gpos->LookupList.offset,
+ &gsub_gpos->LookupList, gsubp) < 0)
+ return NULL;
+ return gsub_gpos;
+}
+
+\f
+/* (1-9) "GSUB" table */
+
+static unsigned
+read_sequence (OTF *otf, OTF_Stream *stream, long offset, OTF_Sequence **seq)
+{
+ char *errfmt = "Sequence%s";
+ unsigned errret = 0;
+ unsigned count;
int i;
-
- READ_OFFSET (stream, array->offset);
- SAVE_STREAM (stream, state);
- SEEK_STREAM (stream, offset + array->offset);
- READ_UINT16 (stream, array->MarkCount);
- OTF_MALLOC (array->MarkRecord, array->MarkCount, "");
- for (i = 0; i < array->MarkCount; i++)
+
+ READ_UINT16 (stream, count);
+ if (! count)
+ OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
+ OTF_MALLOC (*seq, count, "");
+ for (i = 0; i < count; i++)
+ READ_OFFSET (stream, (*seq)[i].offset);
+ for (i = 0; i < count; i++)
{
- READ_UINT16 (stream, array->MarkRecord[i].Class);
- READ_OFFSET (stream, array->MarkRecord[i].MarkAnchor.offset);
+ SEEK_STREAM (stream, offset + (*seq)[i].offset);
+ (*seq)[i].GlyphCount = read_glyph_ids (otf, stream,
+ &(*seq)[i].Substitute, 0, -1);
+ if (! (*seq)[i].GlyphCount)
+ return 0;
}
- for (i = 0; i < array->MarkCount; i++)
- if (read_anchor (otf, stream, offset + array->offset,
- &array->MarkRecord[i].MarkAnchor) < 0)
- return -1;;
- RESTORE_STREAM (stream, state);
- return 0;
+ return count;
}
static int
-read_anchor_array (OTF *otf, OTF_Stream *stream, long offset,
- unsigned ClassCount, OTF_AnchorArray *array)
+read_ligature (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_Ligature **ligature)
{
- char *errfmt = "AnchorArray%s";
+ char *errfmt = "Ligature%s";
int errret = -1;
- OTF_StreamState state;
- int i, j;
-
- READ_OFFSET (stream, array->offset);
- SAVE_STREAM (stream, state);
- SEEK_STREAM (stream, offset + array->offset);
- READ_UINT16 (stream, array->Count);
- OTF_MALLOC (array->AnchorRecord, array->Count, "");
- for (i = 0; i < array->Count; i++)
+ int count;
+ int i;
+
+ READ_UINT16 (stream, count);
+ if (! count)
+ return 0;
+ OTF_MALLOC (*ligature, count, "");
+ for (i = 0; i < count; i++)
+ READ_OFFSET (stream, (*ligature)[i].offset);
+ for (i = 0; i < count; i++)
{
- OTF_MALLOC (array->AnchorRecord[i].Anchor, ClassCount,
- " (AnchorRecord)");
- for (j = 0; j < ClassCount; j++)
- READ_OFFSET (stream, array->AnchorRecord[i].Anchor[j].offset);
- }
- for (i = 0; i < array->Count; i++)
- for (j = 0; j < ClassCount; j++)
- if (read_anchor (otf, stream, offset + array->offset,
- &array->AnchorRecord[i].Anchor[j]) < 0)
+ SEEK_STREAM (stream, offset + (*ligature)[i].offset);
+ READ_GLYPHID (stream, (*ligature)[i].LigGlyph);
+ (*ligature)[i].CompCount
+ = read_glyph_ids (otf, stream, &(*ligature)[i].Component, -1, -1);
+ if (! (*ligature)[i].CompCount)
return -1;
- RESTORE_STREAM (stream, state);
- return 0;
+ }
+ return count;
}
+static unsigned
+read_ligature_set_list (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_LigatureSet **ligset)
+{
+ char *errfmt = "LigatureSet%s";
+ int errret = 0;
+ int count;
+ int i;
-static OTF_Class1Record *
-read_class1_record_list (OTF *otf, OTF_Stream *stream, long offset,
- unsigned num1, enum OTF_ValueFormat bit1,
- unsigned num2, enum OTF_ValueFormat bit2)
+ READ_UINT16 (stream, count);
+ if (! count)
+ return errret;
+ OTF_MALLOC (*ligset, count, "");
+ for (i = 0; i < count; i++)
+ READ_OFFSET (stream, (*ligset)[i].offset);
+ for (i = 0; i < count; i++)
+ {
+ int lig_count;
+
+ SEEK_STREAM (stream, offset + (*ligset)[i].offset);
+ lig_count = read_ligature (otf, stream, offset + (*ligset)[i].offset,
+ &(*ligset)[i].Ligature);
+ if (lig_count < 0)
+ return errret;
+ (*ligset)[i].LigatureCount = (unsigned) lig_count;
+ }
+ return count;
+}
+
+static unsigned
+read_alternate_set_list (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_AlternateSet **altset)
{
- char *errfmt = "Class1Record%s";
- void *errret = NULL;
- OTF_Class1Record *rec;
- int i, j;
+ char *errfmt = "AlternateSet%s";
+ int errret = -1;
+ unsigned count;
+ int i;
- OTF_MALLOC (rec, num1, "");
- for (i = 0; i < num1; i++)
+ READ_UINT16 (stream, count);
+ if (! count)
+ OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
+ OTF_MALLOC (*altset, count, "");
+ for (i = 0; i < count; i++)
+ READ_OFFSET (stream, (*altset)[i].offset);
+ for (i = 0; i < count; i++)
{
- OTF_CALLOC (rec[i].Class2Record, num2, " (Class2Record)");
- for (j = 0; j < num2; j++)
- {
- if (read_value_record (otf, stream, offset,
- bit1, &rec[i].Class2Record[j].Value1) < 0
- || read_value_record (otf, stream, offset,
- bit2, &rec[i].Class2Record[j].Value2) < 0)
- return NULL;
- }
+ int alt_count;
+
+ SEEK_STREAM (stream, offset + (*altset)[i].offset);
+ alt_count = read_glyph_ids (otf, stream, &(*altset)[i].Alternate, 0, -1);
+ if (alt_count < 0)
+ return errret;
+ (*altset)[i].GlyphCount = (unsigned) alt_count;
}
- return rec;
+ return count;
}
static int
-read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream,
- long offset, unsigned type,
- OTF_LookupSubTableGPOS *subtable)
+read_lookup_subtable_gsub (OTF *otf, OTF_Stream *stream, long offset,
+ unsigned type, OTF_LookupSubTableGSUB *subtable)
{
char errfmt[256];
int errret = -1;
- int count;
SEEK_STREAM (stream, offset);
READ_UINT16 (stream, subtable->Format);
- sprintf (errfmt, "GPOS Lookup %d-%d%%s", type, subtable->Format);
+ sprintf (errfmt, "GSUB Lookup %d-%d%%s", type, subtable->Format);
switch (type)
{
case 1:
if (subtable->Format == 1)
{
- READ_UINT16 (stream, subtable->u.single1.ValueFormat);
- read_value_record (otf, stream, offset,
- subtable->u.single1.ValueFormat,
- &subtable->u.single1.Value);
+ if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0)
+ return -1;
+ READ_INT16 (stream, subtable->u.single1.DeltaGlyphID);
}
else if (subtable->Format == 2)
{
- OTF_GPOS_Single2 *single2 = &subtable->u.single2;
- int i;
-
- READ_UINT16 (stream, single2->ValueFormat);
- READ_UINT16 (stream, single2->ValueCount);
- OTF_CALLOC (single2->Value, single2->ValueCount," (ValueRecord)");
- for (i = 0; i < single2->ValueCount; i++)
- read_value_record (otf, stream, offset, single2->ValueFormat,
- single2->Value + i);
+ if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0)
+ return -1;
+ subtable->u.single2.GlyphCount
+ = read_glyph_ids (otf, stream, &subtable->u.single2.Substitute,
+ 0, -1);
+ if (! subtable->u.single2.GlyphCount)
+ return -1;
}
else
OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
case 2:
if (subtable->Format == 1)
{
- OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
- }
- else if (subtable->Format == 2)
- {
- SEEK_STREAM (stream, offset + 2);
read_coverage (otf, stream, offset, &subtable->Coverage);
- READ_UINT16 (stream, subtable->u.pair2.ValueFormat1);
- READ_UINT16 (stream, subtable->u.pair2.ValueFormat2);
- read_class_def (otf, stream, offset,
- &subtable->u.pair2.ClassDef1);
- read_class_def (otf, stream, offset,
- &subtable->u.pair2.ClassDef2);
- READ_UINT16 (stream, subtable->u.pair2.Class1Count);
- READ_UINT16 (stream, subtable->u.pair2.Class2Count);
- subtable->u.pair2.Class1Record
- = read_class1_record_list (otf, stream, offset,
- subtable->u.pair2.Class1Count,
- subtable->u.pair2.ValueFormat1,
- subtable->u.pair2.Class2Count,
- subtable->u.pair2.ValueFormat2);
+ subtable->u.multiple1.SequenceCount
+ = read_sequence (otf, stream, offset,
+ &subtable->u.multiple1.Sequence);
}
else
OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
break;
case 3:
- OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
- break;
-
- case 4:
if (subtable->Format == 1)
{
- read_coverage (otf, stream, offset, &subtable->Coverage);
- read_coverage (otf, stream, offset,
- &subtable->u.mark_base1.BaseCoverage);
- READ_UINT16 (stream, subtable->u.mark_base1.ClassCount);
- read_mark_array (otf, stream, offset,
- &subtable->u.mark_base1.MarkArray);
- read_anchor_array (otf, stream, offset,
- subtable->u.mark_base1.ClassCount,
- &subtable->u.mark_base1.BaseArray);
+ if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0)
+ return -1;
+ subtable->u.alternate1.AlternateSetCount
+ = read_alternate_set_list (otf, stream, offset,
+ &subtable->u.alternate1.AlternateSet);
+ if (! subtable->u.alternate1.AlternateSetCount)
+ return -1;
}
else
OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
break;
- case 5:
- OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
- break;
-
- case 6:
+ case 4:
if (subtable->Format == 1)
- {
- read_coverage (otf, stream, offset, &subtable->Coverage);
- read_coverage (otf, stream, offset,
- &subtable->u.mark_mark1.Mark2Coverage);
- READ_UINT16 (stream, subtable->u.mark_base1.ClassCount);
- read_mark_array (otf, stream, offset,
- &subtable->u.mark_mark1.Mark1Array);
- read_anchor_array (otf, stream, offset,
- subtable->u.mark_mark1.ClassCount,
- &subtable->u.mark_mark1.Mark2Array);
+ {
+ if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0)
+ return -1;
+ subtable->u.ligature1.LigSetCount
+ = read_ligature_set_list (otf, stream, offset,
+ &subtable->u.ligature1.LigatureSet);
+ if (! subtable->u.ligature1.LigSetCount)
+ return -1;
}
else
OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
break;
- case 7:
+ case 5:
if (subtable->Format == 1)
{
- OTF_GPOS_Context1 *context1 = &subtable->u.context1;
-
- read_coverage (otf, stream, offset, &subtable->Coverage);
- context1->PosRuleSetCount
- = read_rule_set_list (otf, stream, offset, &context1->PosRuleSet);
+ if (read_context1 (otf, stream, offset, &subtable->Coverage,
+ &subtable->u.context1) < 0)
+ return errret;
}
else if (subtable->Format == 2)
{
- OTF_GPOS_Context2 *context2 = &subtable->u.context2;
-
- read_coverage (otf, stream, offset, &subtable->Coverage);
- read_class_def (otf, stream, offset, &context2->ClassDef);
- context2->PosClassSetCnt
- = read_class_set_list (otf, stream, offset, &context2->PosClassSet);
-
+ if (read_context2 (otf, stream, offset, &subtable->Coverage,
+ &subtable->u.context2) < 0)
+ return errret;
}
else if (subtable->Format == 3)
{
- OTF_GPOS_Context3 *context3 = &subtable->u.context3;
-
- READ_USHORT (stream, context3->GlyphCount);
- if (context3->GlyphCount < 0)
- OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
- READ_USHORT (stream, context3->PosCount);
- if (read_coverage_list (otf, stream, offset,
- &context3->Coverage,
- context3->GlyphCount) < 0)
- return -1;
- if (read_lookup_record_list (otf, stream,
- &context3->LookupRecord,
- context3->PosCount) < 0)
- return -1;
+ if (read_context3 (otf, stream, offset, &subtable->Coverage,
+ &subtable->u.context3) < 0)
+ return errret;
}
else
OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
break;
-
- case 8:
+
+ case 6:
if (subtable->Format == 1)
{
- OTF_GPOS_ChainContext1 *chain_context1 = &subtable->u.chain_context1;
-
- read_coverage (otf, stream, offset, &subtable->Coverage);
- chain_context1->ChainPosRuleSetCount
- = read_chain_rule_set_list (otf, stream, offset,
- &chain_context1->ChainPosRuleSet);
+ if (read_chain_context1 (otf, stream, offset, &subtable->Coverage,
+ &subtable->u.chain_context1) < 0)
+ return errret;
}
else if (subtable->Format == 2)
{
- OTF_GPOS_ChainContext2 *chain_context2 = &subtable->u.chain_context2;
-
- read_coverage (otf, stream, offset, &subtable->Coverage);
- read_class_def (otf, stream, offset, &chain_context2->Backtrack);
- read_class_def (otf, stream, offset, &chain_context2->Input);
- read_class_def (otf, stream, offset, &chain_context2->LookAhead);
- chain_context2->ChainPosClassSetCnt
- = read_chain_class_set_list (otf, stream, offset,
- &chain_context2->ChainPosClassSet);
+ if (read_chain_context2 (otf, stream, offset, &subtable->Coverage,
+ &subtable->u.chain_context2) < 0)
+ return errret;
}
else if (subtable->Format == 3)
{
- OTF_GPOS_ChainContext3 *chain_context3 = &subtable->u.chain_context3;
-
- count = read_coverage_list (otf, stream, offset,
- &chain_context3->Backtrack, -1);
- if (count < 0)
- return -1;
- chain_context3->BacktrackGlyphCount = (unsigned) count;
- count = read_coverage_list (otf, stream, offset,
- &chain_context3->Input, -1);
- if (count <= 0)
- return -1;
- chain_context3->InputGlyphCount = (unsigned) count;
- subtable->Coverage = chain_context3->Input[0];
- count = read_coverage_list (otf, stream, offset,
- &chain_context3->LookAhead, -1);
- chain_context3->LookaheadGlyphCount = (unsigned) count;
- chain_context3->PosCount
- = read_lookup_record_list (otf, stream,
- &chain_context3->LookupRecord, -1);
+ if (read_chain_context3 (otf, stream, offset, &subtable->Coverage,
+ &subtable->u.chain_context3) < 0)
+ return errret;
}
else
OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
break;
-
- case 9:
- OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
+
+ case 7:
+ case 8:
+ OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
break;
default:
return 0;
}
-
static void *
-read_gpos_table (OTF *otf, OTF_Stream *stream)
-{
- char *errfmt = "GPOS%s";
- void *errret = NULL;
- OTF_GPOS *gpos;
-
- OTF_CALLOC (gpos, 1, "");
- READ_FIXED (stream, gpos->Version);
- READ_OFFSET (stream, gpos->ScriptList.offset);
- READ_OFFSET (stream, gpos->FeatureList.offset);
- READ_OFFSET (stream, gpos->LookupList.offset);
-
- if (read_script_list (otf, stream, gpos->ScriptList.offset,
- &gpos->ScriptList) < 0
- || read_feature_list (otf, stream, gpos->FeatureList.offset,
- &gpos->FeatureList) < 0
- || read_lookup_list (otf, stream, gpos->LookupList.offset,
- &gpos->LookupList, 0) < 0)
- return NULL;
- return gpos;
-}
-
-\f
-#if 0
-/* BASE */
-
-static OTF_BASE *
-read_base_table (OTF_Stream *stream, long offset)
+read_gsub_table (OTF *otf, OTF_Stream *stream)
{
- OTF_BASE *base;
-
- OTF_MALLOC (base, 1);
-
- return base;
+ return read_gsub_gpos_table (otf, stream, 1);
}
\f
-/* JSTF */
-
-static OTF_JSTF *
-read_jstf_table (OTF_Stream *stream, long offset)
-{
- OTF_JSTF *jstf;
-
- OTF_MALLOC (jstf, 1);
+/* (1-10) "GPOS" table */
- return jstf;
-}
-#endif /* 0 */
-\f
-/* GDEF */
static int
-read_attach_list (OTF *otf, OTF_Stream *stream, long offset,
- OTF_AttachList *list)
+read_value_record (OTF *otf, OTF_Stream *stream, long offset,
+ enum OTF_ValueFormat bit, OTF_ValueRecord *value_record)
{
- char *errfmt = "AttachList%s";
int errret = -1;
- int i, j;
+ OTF_StreamState state;
+ int size, i;
- if (read_coverage (otf, stream, offset, &list->Coverage) < 0)
- return -1;
- READ_UINT16 (stream, list->GlyphCount);
- OTF_MALLOC (list->AttachPoint, list->GlyphCount, "");
- for (i = 0; i < list->GlyphCount; i++)
- READ_OFFSET (stream, list->AttachPoint[i].offset);
- for (i = 0; i < list->GlyphCount; i++)
- {
- int count;
+ if (! bit)
+ return 0;
+ for (i = 0, size = 0; i < 8; i++)
+ if (bit & (1 << i))
+ size += 2;
- SEEK_STREAM (stream, offset + list->AttachPoint[i].offset);
- READ_UINT16 (stream, count);
- list->AttachPoint[i].PointCount = count;
- OTF_MALLOC (list->AttachPoint[i].PointIndex, count, " (PointIndex)");
- for (j = 0; j < count; j++)
- READ_UINT16 (stream, list->AttachPoint[i].PointIndex[j]);
+ if (bit & OTF_XPlacement)
+ READ_INT16 (stream, value_record->XPlacement);
+ if (bit & OTF_XPlacement)
+ READ_INT16 (stream, value_record->YPlacement);
+ if (bit & OTF_XAdvance)
+ READ_INT16 (stream, value_record->XAdvance);
+ if (bit & OTF_YAdvance)
+ READ_INT16 (stream, value_record->YAdvance);
+ if (bit & OTF_XPlaDevice)
+ READ_OFFSET (stream, value_record->XPlaDevice.offset);
+ if (bit & OTF_YPlaDevice)
+ READ_OFFSET (stream, value_record->YPlaDevice.offset);
+ if (bit & OTF_XAdvDevice)
+ READ_OFFSET (stream, value_record->XAdvDevice.offset);
+ if (bit & OTF_YAdvDevice)
+ READ_OFFSET (stream, value_record->YAdvDevice.offset);
+ SAVE_STREAM (stream, state);
+ if (value_record->XPlaDevice.offset)
+ {
+ if (read_device_table (otf, stream, offset, &value_record->XPlaDevice) < 0)
+ return -1;
+ }
+ if (value_record->YPlaDevice.offset)
+ {
+ if (read_device_table (otf, stream, offset, &value_record->YPlaDevice) < 0)
+ return -1;
+ }
+ if (value_record->XAdvDevice.offset)
+ {
+ if (read_device_table (otf, stream, offset, &value_record->XAdvDevice) < 0)
+ return -1;
+ }
+ if (value_record->YAdvDevice.offset)
+ {
+ if (read_device_table (otf, stream, offset, &value_record->YAdvDevice) < 0)
+ return -1;
}
+ RESTORE_STREAM (stream, state);
return 0;
}
+
static int
-read_caret_value (OTF *otf, OTF_Stream *stream, long offset,
- OTF_CaretValue *caret)
+read_anchor (OTF *otf, OTF_Stream *stream, long offset, OTF_Anchor *anchor)
{
- char *errfmt = "CaretValue%s";
+ char *errfmt = "Anchor%s";
int errret = -1;
- SEEK_STREAM (stream, offset + caret->offset);
- READ_UINT16 (stream, caret->CaretValueFormat);
- if (caret->CaretValueFormat == 1)
- READ_INT16 (stream, caret->f.f1.Coordinate);
- else if (caret->CaretValueFormat == 2)
- READ_UINT16 (stream, caret->f.f2.CaretValuePoint);
- else if (caret->CaretValueFormat == 3)
+ SEEK_STREAM (stream, offset + anchor->offset);
+ READ_UINT16 (stream, anchor->AnchorFormat);
+ READ_INT16 (stream, anchor->XCoordinate);
+ READ_INT16 (stream, anchor->YCoordinate);
+ if (anchor->AnchorFormat == 1)
+ ;
+ else if (anchor->AnchorFormat == 2)
{
- READ_INT16 (stream, caret->f.f3.Coordinate);
- if (read_device_table (otf, stream, offset + caret->offset,
- &caret->f.f3.DeviceTable) < 0)
- return -1;
+ READ_UINT16 (stream, anchor->f.f1.AnchorPoint);
+ }
+ else if (anchor->AnchorFormat == 3)
+ {
+ READ_OFFSET (stream, anchor->f.f2.XDeviceTable.offset);
+ READ_OFFSET (stream, anchor->f.f2.YDeviceTable.offset);
+ if (anchor->f.f2.XDeviceTable.offset)
+ {
+ if (read_device_table (otf, stream, offset + anchor->offset,
+ &anchor->f.f2.XDeviceTable) < 0)
+ return -1;
+ }
+ if (anchor->f.f2.YDeviceTable.offset)
+ {
+ if (read_device_table (otf, stream, offset + anchor->offset,
+ &anchor->f.f2.YDeviceTable) < 0)
+ return -1;
+ }
}
else
- OTF_ERROR (OTF_ERROR_TABLE, " (Invalid format)");
+ OTF_ERROR (OTF_ERROR_TABLE, " (invalid format)");
+
return 0;
}
static int
-read_lig_caret_list (OTF *otf, OTF_Stream *stream, long offset,
- OTF_LigCaretList *list)
+read_mark_array (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_MarkArray *array)
{
- char *errfmt = "LigCaretList%s";
+ char *errfmt = "MarkArray%s";
int errret = -1;
- int i, j;
-
- if (read_coverage (otf, stream, offset, &list->Coverage) < 0)
- return -1;
- READ_UINT16 (stream, list->LigGlyphCount);
- OTF_MALLOC (list->LigGlyph, list->LigGlyphCount, "");
- for (i = 0; i < list->LigGlyphCount; i++)
- READ_OFFSET (stream, list->LigGlyph[i].offset);
- for (i = 0; i < list->LigGlyphCount; i++)
+ OTF_StreamState state;
+ int i;
+
+ READ_OFFSET (stream, array->offset);
+ SAVE_STREAM (stream, state);
+ SEEK_STREAM (stream, offset + array->offset);
+ READ_UINT16 (stream, array->MarkCount);
+ OTF_MALLOC (array->MarkRecord, array->MarkCount, "");
+ for (i = 0; i < array->MarkCount; i++)
{
- int count;
-
- SEEK_STREAM (stream, offset + list->LigGlyph[i].offset);
- READ_UINT16 (stream, count);
- list->LigGlyph[i].CaretCount = count;
- OTF_MALLOC (list->LigGlyph[i].CaretValue, count, " (CaretValue)");
- for (j = 0; j < count; j++)
- READ_OFFSET (stream, list->LigGlyph[i].CaretValue[j].offset);
- for (j = 0; j < count; j++)
- if (read_caret_value (otf, stream, offset + list->LigGlyph[i].offset,
- &list->LigGlyph[i].CaretValue[j]) < 0)
- return -1;
+ READ_UINT16 (stream, array->MarkRecord[i].Class);
+ READ_OFFSET (stream, array->MarkRecord[i].MarkAnchor.offset);
}
+ for (i = 0; i < array->MarkCount; i++)
+ if (read_anchor (otf, stream, offset + array->offset,
+ &array->MarkRecord[i].MarkAnchor) < 0)
+ return -1;;
+ RESTORE_STREAM (stream, state);
return 0;
}
static int
-read_gdef_header (OTF_Stream *stream, OTF_GDEFHeader *header)
+read_anchor_array (OTF *otf, OTF_Stream *stream, long offset,
+ unsigned ClassCount, OTF_AnchorArray *array)
{
+ char *errfmt = "AnchorArray%s";
int errret = -1;
-
- READ_FIXED (stream, header->Version);
- READ_OFFSET (stream, header->GlyphClassDef);
- READ_OFFSET (stream, header->AttachList);
- READ_OFFSET (stream, header->LigCaretList);
- READ_OFFSET (stream, header->MarkAttachClassDef);
+ OTF_StreamState state;
+ int i, j;
+
+ READ_OFFSET (stream, array->offset);
+ SAVE_STREAM (stream, state);
+ SEEK_STREAM (stream, offset + array->offset);
+ READ_UINT16 (stream, array->Count);
+ OTF_MALLOC (array->AnchorRecord, array->Count, "");
+ for (i = 0; i < array->Count; i++)
+ {
+ OTF_MALLOC (array->AnchorRecord[i].Anchor, ClassCount,
+ " (AnchorRecord)");
+ for (j = 0; j < ClassCount; j++)
+ READ_OFFSET (stream, array->AnchorRecord[i].Anchor[j].offset);
+ }
+ for (i = 0; i < array->Count; i++)
+ for (j = 0; j < ClassCount; j++)
+ if (read_anchor (otf, stream, offset + array->offset,
+ &array->AnchorRecord[i].Anchor[j]) < 0)
+ return -1;
+ RESTORE_STREAM (stream, state);
return 0;
}
-static void *
-read_gdef_table (OTF *otf, OTF_Stream *stream)
+
+static OTF_Class1Record *
+read_class1_record_list (OTF *otf, OTF_Stream *stream, long offset,
+ unsigned num1, enum OTF_ValueFormat bit1,
+ unsigned num2, enum OTF_ValueFormat bit2)
{
- char *errfmt = "GDEF%s";
+ char *errfmt = "Class1Record%s";
void *errret = NULL;
- OTF_GDEF *gdef;
+ OTF_Class1Record *rec;
+ int i, j;
- OTF_CALLOC (gdef, 1, "");
- read_gdef_header (stream, (OTF_GDEFHeader *) &gdef->header);
- if (gdef->header.GlyphClassDef)
- {
- gdef->glyph_class_def.offset = gdef->header.GlyphClassDef;
- read_class_def_without_offset (otf, stream, &gdef->glyph_class_def);
- }
- if (gdef->header.AttachList)
- read_attach_list (otf, stream, gdef->header.AttachList,
- &gdef->attach_list);
- if (gdef->header.LigCaretList)
- read_lig_caret_list (otf, stream, gdef->header.LigCaretList,
- &gdef->lig_caret_list);
- if (gdef->header.MarkAttachClassDef)
+ OTF_MALLOC (rec, num1, "");
+ for (i = 0; i < num1; i++)
{
- gdef->mark_attach_class_def.offset = gdef->header.MarkAttachClassDef;
- read_class_def_without_offset (otf, stream, &gdef->mark_attach_class_def);
+ OTF_CALLOC (rec[i].Class2Record, num2, " (Class2Record)");
+ for (j = 0; j < num2; j++)
+ {
+ if (read_value_record (otf, stream, offset,
+ bit1, &rec[i].Class2Record[j].Value1) < 0
+ || read_value_record (otf, stream, offset,
+ bit2, &rec[i].Class2Record[j].Value2) < 0)
+ return NULL;
+ }
}
-
- return gdef;
+ return rec;
}
-\f
-
-/* cmap */
-
-static void *
-read_cmap_table (OTF *otf, OTF_Stream *stream)
+static int
+read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream,
+ long offset, unsigned type,
+ OTF_LookupSubTableGPOS *subtable)
{
- char *errfmt = "cmap%s";
- void *errret = NULL;
- OTF_cmap *cmap;
- int i;
+ char errfmt[256];
+ int errret = -1;
- OTF_CALLOC (cmap, 1, "");
- READ_USHORT (stream, cmap->version);
- READ_USHORT (stream, cmap->numTables);
- OTF_MALLOC (cmap->EncodingRecord, cmap->numTables, "");
- for (i = 0; i < cmap->numTables; i++)
- {
- READ_USHORT (stream, cmap->EncodingRecord[i].platformID);
- READ_USHORT (stream, cmap->EncodingRecord[i].encodingID);
- READ_ULONG (stream, cmap->EncodingRecord[i].offset);
- if (cmap->EncodingRecord[i].platformID == 3
- && cmap->EncodingRecord[i].encodingID == 1)
- cmap->Unicode = cmap->EncodingRecord + i;
- }
- for (i = 0; i < cmap->numTables; i++)
+ SEEK_STREAM (stream, offset);
+ READ_UINT16 (stream, subtable->Format);
+ sprintf (errfmt, "GPOS Lookup %d-%d%%s", type, subtable->Format);
+ switch (type)
{
- unsigned format;
-
- SEEK_STREAM (stream, cmap->EncodingRecord[i].offset);
- READ_USHORT (stream, format);
- cmap->EncodingRecord[i].subtable.format = format;
- READ_USHORT (stream, cmap->EncodingRecord[i].subtable.length);
- if (format == 8 || format == 10 || format == 12)
+ case 1:
+ if (subtable->Format == 1)
{
- READ_ULONG (stream, cmap->EncodingRecord[i].subtable.length);
- READ_ULONG (stream, cmap->EncodingRecord[i].subtable.language);
+ READ_UINT16 (stream, subtable->u.single1.ValueFormat);
+ read_value_record (otf, stream, offset,
+ subtable->u.single1.ValueFormat,
+ &subtable->u.single1.Value);
+ }
+ else if (subtable->Format == 2)
+ {
+ OTF_GPOS_Single2 *single2 = &subtable->u.single2;
+ int i;
+
+ READ_UINT16 (stream, single2->ValueFormat);
+ READ_UINT16 (stream, single2->ValueCount);
+ OTF_CALLOC (single2->Value, single2->ValueCount," (ValueRecord)");
+ for (i = 0; i < single2->ValueCount; i++)
+ read_value_record (otf, stream, offset, single2->ValueFormat,
+ single2->Value + i);
}
else
+ OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
+ break;
+
+ case 2:
+ if (subtable->Format == 1)
{
- READ_USHORT (stream, cmap->EncodingRecord[i].subtable.language);
+ OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
}
- switch (format)
+ else if (subtable->Format == 2)
{
- case 0:
- {
- OTF_MALLOC (cmap->EncodingRecord[i].subtable.f.f0, 1,
- " (EncodingRecord)");
- READ_BYTES (stream,
- cmap->EncodingRecord[i].subtable.f.f0->glyphIdArray,
- 256);
- }
- break;
-
- case 2:
- break;
-
- case 4:
- {
- OTF_EncodingSubtable4 *sub4;
- int segCount;
- int j;
- unsigned dummy;
-
- OTF_MALLOC (sub4, 1, " (EncodingSubtable4)");
- cmap->EncodingRecord[i].subtable.f.f4 = sub4;
- READ_USHORT (stream, sub4->segCountX2);
- segCount = sub4->segCountX2 / 2;
- READ_USHORT (stream, sub4->searchRange);
- READ_USHORT (stream, sub4->entrySelector);
- READ_USHORT (stream, sub4->rangeShift);
- OTF_MALLOC (sub4->segments, segCount, " (segCount)");
- for (j = 0; j < segCount; j++)
- READ_USHORT (stream, sub4->segments[j].endCount);
- READ_USHORT (stream, dummy);
- for (j = 0; j < segCount; j++)
- READ_USHORT (stream, sub4->segments[j].startCount);
- for (j = 0; j < segCount; j++)
- READ_SHORT (stream, sub4->segments[j].idDelta);
- for (j = 0; j < segCount; j++)
- {
- unsigned off;
- unsigned rest = 2 * (segCount - j);
-
- READ_USHORT (stream, off);
- if (off == 0)
- sub4->segments[j].idRangeOffset = 0xFFFF;
- else
- sub4->segments[j].idRangeOffset = (off - rest) / 2;
- }
- j = (cmap->EncodingRecord[i].subtable.length
- - (14 + 2 * (segCount * 4 + 1)));
- sub4->GlyphCount = j / 2;
- OTF_MALLOC (sub4->glyphIdArray, sub4->GlyphCount, " (GlyphCount)");
- for (j = 0; j < sub4->GlyphCount; j++)
- READ_USHORT (stream, sub4->glyphIdArray[j]);
- }
+ SEEK_STREAM (stream, offset + 2);
+ read_coverage (otf, stream, offset, &subtable->Coverage);
+ READ_UINT16 (stream, subtable->u.pair2.ValueFormat1);
+ READ_UINT16 (stream, subtable->u.pair2.ValueFormat2);
+ read_class_def (otf, stream, offset,
+ &subtable->u.pair2.ClassDef1);
+ read_class_def (otf, stream, offset,
+ &subtable->u.pair2.ClassDef2);
+ READ_UINT16 (stream, subtable->u.pair2.Class1Count);
+ READ_UINT16 (stream, subtable->u.pair2.Class2Count);
+ subtable->u.pair2.Class1Record
+ = read_class1_record_list (otf, stream, offset,
+ subtable->u.pair2.Class1Count,
+ subtable->u.pair2.ValueFormat1,
+ subtable->u.pair2.Class2Count,
+ subtable->u.pair2.ValueFormat2);
}
- }
- return cmap;
-}
-
-\f
+ else
+ OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
+ break;
+
+ case 3:
+ OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
+ break;
-/* TABLE: name */
+ case 4:
+ if (subtable->Format == 1)
+ {
+ read_coverage (otf, stream, offset, &subtable->Coverage);
+ read_coverage (otf, stream, offset,
+ &subtable->u.mark_base1.BaseCoverage);
+ READ_UINT16 (stream, subtable->u.mark_base1.ClassCount);
+ read_mark_array (otf, stream, offset,
+ &subtable->u.mark_base1.MarkArray);
+ read_anchor_array (otf, stream, offset,
+ subtable->u.mark_base1.ClassCount,
+ &subtable->u.mark_base1.BaseArray);
+ }
+ else
+ OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
+ break;
-static char *
-read_name (OTF *otf, OTF_Stream *stream, OTF_NameRecord *rec, int bytes)
-{
- char *errfmt = "nameID (%d)";
- void *errret = NULL;
- OTF_StreamState state;
- char *str;
- int i;
- int c;
+ case 5:
+ OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
+ break;
- SAVE_STREAM (stream, state);
- SEEK_STREAM (stream, stream->pos + rec->offset);
+ case 6:
+ if (subtable->Format == 1)
+ {
+ read_coverage (otf, stream, offset, &subtable->Coverage);
+ read_coverage (otf, stream, offset,
+ &subtable->u.mark_mark1.Mark2Coverage);
+ READ_UINT16 (stream, subtable->u.mark_base1.ClassCount);
+ read_mark_array (otf, stream, offset,
+ &subtable->u.mark_mark1.Mark1Array);
+ read_anchor_array (otf, stream, offset,
+ subtable->u.mark_mark1.ClassCount,
+ &subtable->u.mark_mark1.Mark2Array);
+ }
+ else
+ OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
+ break;
- if (bytes == 1)
- {
- OTF_MALLOC (str, rec->length + 1, (void *) rec->nameID);
- READ_BYTES (stream, str, rec->length);
- for (i = 0; i < rec->length; i++)
- if (str[i] < 0)
- str[i] = '?';
- }
- else if (bytes == 2)
- {
- OTF_MALLOC (str, rec->length / 2 + 1, (void *) rec->nameID);
- for (i = 0; i < rec->length / 2; i++)
+ case 7:
+ if (subtable->Format == 1)
+ {
+ if (read_context1 (otf, stream, offset, &subtable->Coverage,
+ &subtable->u.context1) < 0)
+ return errret;
+ }
+ else if (subtable->Format == 2)
{
- READ_USHORT (stream, c);
- if (c >= 128)
- c = '?';
- str[i] = c;
+ if (read_context2 (otf, stream, offset, &subtable->Coverage,
+ &subtable->u.context2) < 0)
+ return errret;
}
- }
- else if (bytes == 4)
- {
- OTF_MALLOC (str, rec->length / 4 + 1, (void *) rec->nameID);
- for (i = 0; i < rec->length / 4; i++)
+ else if (subtable->Format == 3)
{
- READ_ULONG (stream, c);
- if (c >= 128)
- c = '?';
- str[i] = c;
+ if (read_context3 (otf, stream, offset, &subtable->Coverage,
+ &subtable->u.context3) < 0)
+ return errret;
+ }
+ else
+ OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
+ break;
+
+ case 8:
+ if (subtable->Format == 1)
+ {
+ if (read_chain_context1 (otf, stream, offset, &subtable->Coverage,
+ &subtable->u.chain_context1) < 0)
+ return errret;
+ }
+ else if (subtable->Format == 2)
+ {
+ if (read_chain_context2 (otf, stream, offset, &subtable->Coverage,
+ &subtable->u.chain_context2) < 0)
+ return errret;
+ }
+ else if (subtable->Format == 3)
+ {
+ if (read_chain_context3 (otf, stream, offset, &subtable->Coverage,
+ &subtable->u.chain_context3) < 0)
+ return errret;
}
+ else
+ OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
+ break;
+
+ case 9:
+ OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
+ break;
+
+ default:
+ OTF_ERROR (OTF_ERROR_TABLE, " (Invalid LookupType)");
}
- str[i] = '\0';
- RESTORE_STREAM (stream, state);
- return str;
+ return 0;
}
static void *
-read_name_table (OTF *otf, OTF_Stream *stream)
+read_gpos_table (OTF *otf, OTF_Stream *stream)
{
- char *errfmt = "name%s";
- void *errret = NULL;
- OTF_name *name;
- int i;
+ return read_gsub_gpos_table (otf, stream, 0);
+}
- OTF_CALLOC (name, 1, "");
- READ_USHORT (stream, name->format);
- READ_USHORT (stream, name->count);
- READ_USHORT (stream, name->stringOffset);
- OTF_MALLOC (name->nameRecord, name->count, "");
- for (i = 0; i < name->count; i++)
- {
- OTF_NameRecord *rec = name->nameRecord + i;
+\f
+#if 0
+/* BASE */
- READ_USHORT (stream, rec->platformID);
- READ_USHORT (stream, rec->encodingID);
- READ_USHORT (stream, rec->languageID);
- READ_USHORT (stream, rec->nameID);
- READ_USHORT (stream, rec->length);
- READ_USHORT (stream, rec->offset);
- }
- for (i = 0; i < name->count; i++)
- {
- OTF_NameRecord *rec = name->nameRecord + i;
- int nameID = rec->nameID;
+static OTF_BASE *
+read_base_table (OTF_Stream *stream, long offset)
+{
+ OTF_BASE *base;
- if (nameID <= OTF_max_nameID
- && ! name->name[nameID])
- {
- if (rec->platformID == 0)
- name->name[nameID] = read_name (otf, stream, rec,
- rec->encodingID <= 3 ? 2 : 4);
- else if (rec->platformID == 1
- && rec->encodingID == 0)
- name->name[nameID] = read_name (otf, stream, rec, 1);
- else if (rec->platformID == 3
- && (rec->encodingID == 1 || rec->encodingID == 10))
- name->name[nameID] = read_name (otf, stream,
- rec, rec->encodingID == 1 ? 2 : 4);
- }
- }
+ OTF_MALLOC (base, 1);
- return name;
+ return base;
}
\f
+/* JSTF */
-/* APIs */
+static OTF_JSTF *
+read_jstf_table (OTF_Stream *stream, long offset)
+{
+ OTF_JSTF *jstf;
-OTF_Tag
-OTF_tag (char *name)
+ OTF_MALLOC (jstf, 1);
+
+ return jstf;
+}
+#endif /* 0 */
+\f
+/*** (1-11) Structure for OTF */
+
+int
+read_offset_table (OTF *otf, OTF_Stream *stream, OTF_OffsetTable *table)
+{
+ int errret = -1;
+
+ READ_FIXED (stream, table->sfnt_version);
+ READ_USHORT (stream, table->numTables);
+ READ_USHORT (stream, table->searchRange);
+ READ_USHORT (stream, table->enterSelector);
+ READ_USHORT (stream, table->rangeShift);
+ return 0;
+}
+
+static OTF_Tag
+read_table_directory (OTF_Stream *stream, OTF_TableDirectory *table)
{
- unsigned char *p = (unsigned char *) name;
+ int errret = 0;
+ OTF_Tag tag;
- if (! name)
- return (OTF_Tag) 0;
- return (OTF_Tag) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+ READ_TAG (stream, tag);
+ table->tag = tag;
+ table->name[0] = tag >> 24;
+ table->name[1] = (tag >> 16) & 0xFF;
+ table->name[0] = (tag >> 8) & 0xFF;
+ table->name[0] = tag >> 8;
+ table->name[0] = '\0';
+ READ_ULONG (stream, table->checkSum);
+ READ_ULONG (stream, table->offset);
+ READ_ULONG (stream, table->length);
+ return tag;
}
-void
-OTF_tag_name (OTF_Tag tag, char *name)
+static int
+read_header_part (OTF *otf, FILE *fp)
{
- name[0] = (char) (tag >> 24);
- name[1] = (char) ((tag >> 16) & 0xFF);
- name[2] = (char) ((tag >> 8) & 0xFF);
- name[3] = (char) (tag & 0xFF);
- name[4] = '\0';
+ char *errfmt = "otf header%s";
+ int errret = -1;
+ OTF_Tag head_tag, name_tag, cmap_tag, gdef_tag, gsub_tag, gpos_tag;
+ OTF_Stream *stream;
+ int i;
+ OTF_InternalData *internal_data = (OTF_InternalData *) otf->internal_data;
+
+ internal_data->table_info[OTF_TABLE_TYPE_HEAD].address = (void *) &otf->head;
+ internal_data->table_info[OTF_TABLE_TYPE_HEAD].reader = read_head_table;
+ internal_data->table_info[OTF_TABLE_TYPE_NAME].address = (void *) &otf->name;
+ internal_data->table_info[OTF_TABLE_TYPE_NAME].reader = read_name_table;
+ internal_data->table_info[OTF_TABLE_TYPE_CMAP].address = (void *) &otf->cmap;
+ internal_data->table_info[OTF_TABLE_TYPE_CMAP].reader = read_cmap_table;
+ internal_data->table_info[OTF_TABLE_TYPE_GDEF].address = (void *) &otf->gdef;
+ internal_data->table_info[OTF_TABLE_TYPE_GDEF].reader = read_gdef_table;
+ internal_data->table_info[OTF_TABLE_TYPE_GSUB].address = (void *) &otf->gsub;
+ internal_data->table_info[OTF_TABLE_TYPE_GSUB].reader = read_gsub_table;
+ internal_data->table_info[OTF_TABLE_TYPE_GPOS].address = (void *) &otf->gpos;
+ internal_data->table_info[OTF_TABLE_TYPE_GPOS].reader = read_gpos_table;
+
+ head_tag = OTF_tag ("head");
+ name_tag = OTF_tag ("name");
+ cmap_tag = OTF_tag ("cmap");
+ gdef_tag = OTF_tag ("GDEF");
+ gsub_tag = OTF_tag ("GSUB");
+ gpos_tag = OTF_tag ("GPOS");
+
+ stream = make_stream ();
+ if (! stream)
+ return -1;
+
+ internal_data->header_stream = stream;
+
+ /* Size of Offset Table is 12 bytes. */
+ if (setup_stream (stream, fp, 0, 12, "Offset Table") < 0)
+ return -1;
+ if (read_offset_table (otf, stream, &otf->offset_table) < 0)
+ return -1;
+
+ /* Size of each Table Directory is 16 bytes. */
+ if (setup_stream (stream, fp, 12, 16 * otf->offset_table.numTables,
+ "Table Directory") < 0)
+ return -1;
+
+ OTF_CALLOC (otf->table_dirs, otf->offset_table.numTables, " (OffsetTable)");
+ for (i = 0; i < otf->offset_table.numTables; i++)
+ {
+ OTF_Tag tag = read_table_directory (stream, otf->table_dirs + i);
+ OTF_TableInfo *table_info = NULL;
+
+ if (! tag)
+ return -1;
+ if (tag == head_tag)
+ table_info = internal_data->table_info + OTF_TABLE_TYPE_HEAD;
+ else if (tag == name_tag)
+ table_info = internal_data->table_info + OTF_TABLE_TYPE_NAME;
+ else if (tag == cmap_tag)
+ table_info = internal_data->table_info + OTF_TABLE_TYPE_CMAP;
+ else if (tag == gdef_tag)
+ table_info = internal_data->table_info + OTF_TABLE_TYPE_GDEF;
+ else if (tag == gsub_tag)
+ table_info = internal_data->table_info + OTF_TABLE_TYPE_GSUB;
+ else if (tag == gpos_tag)
+ table_info = internal_data->table_info + OTF_TABLE_TYPE_GPOS;
+
+ if (table_info)
+ {
+ table_info->stream = make_stream ();
+ if (setup_stream (table_info->stream, fp,
+ otf->table_dirs[i].offset,
+ otf->table_dirs[i].length,
+ otf->table_dirs[i].name) < 0)
+ return -1;
+ }
+ }
+
+ internal_data->header_stream = NULL;
+ free_stream (stream);
+ return 0;
}
+\f
+/*** (2) APIs for reading OTF */
+
+/*** (2-1) OTF_open() */
-/* We can't use memory allocation macros in the following functions
- because those macros returns from the functions before freeing
- memory previously allocated. */
+/* Note: We can't use memory allocation macros in the following
+ functions because those macros return from the functions before
+ freeing memory previously allocated. */
OTF *
OTF_open (char *otf_name)
return otf;
}
+/*** (2-2) OTF_close() */
void
OTF_close (OTF *otf)
free (otf);
}
+/*** (2-3) OTF_get_table() */
int
OTF_get_table (OTF *otf, char *name)
return 0;
}
+
+\f
+/*** (5) APIs miscellaneous ***/
+
+OTF_Tag
+OTF_tag (char *name)
+{
+ unsigned char *p = (unsigned char *) name;
+
+ if (! name)
+ return (OTF_Tag) 0;
+ return (OTF_Tag) ((p[0] << 24) | (p[1] << 16) | (p[2] << 8) | p[3]);
+}
+
+void
+OTF_tag_name (OTF_Tag tag, char *name)
+{
+ name[0] = (char) (tag >> 24);
+ name[1] = (char) ((tag >> 16) & 0xFF);
+ name[2] = (char) ((tag >> 8) & 0xFF);
+ name[3] = (char) (tag & 0xFF);
+ name[4] = '\0';
+}