/* otfopen.c -- OpenType font reader.
-Copyright (C) 2003
- by AIST (National Institute of Advanced Industrial Science and Technology)
- Registration Number H15PRO???
+Copyright (C) 2003, 2004
+ National Institute of Advanced Industrial Science and Technology (AIST)
+ Registration Number H15PRO167
-This file is part of the OTF library.
+This file is part of libotf.
-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.
+Libotf is free software; you can redistribute it and/or modify it
+under the terms of the GNU Lesser General Public License as published
+by the Free Software Foundation; either version 2.1 of the License, 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.
+Libotf 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 Lesser 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. */
+You should have received a copy of the GNU Lesser General Public
+License along with this library, in a file named 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 <config.h>
#include "otf.h"
#include "otferror.h"
(2-1) OTF_open()
(2-2) OTF_close()
(2-3) OTF_get_table()
+ (2-4) OTF_check_table()
(5) API miscellaneous
*/
\f
/*** (1-3) "name" table */
-static char *
-read_name (OTF *otf, OTF_Stream *stream, OTF_NameRecord *rec, int bytes)
+static int
+read_name (OTF *otf, OTF_Stream *stream, OTF_NameRecord *rec)
{
char *errfmt = "nameID (%d)";
- void *errret = NULL;
+ int errret = -1;
OTF_StreamState state;
- char *str;
+ int ucs = 0;
+ int ascii = 0;
int i;
- int c;
+ if (rec->platformID == 0)
+ ucs = (rec->encodingID <= 3) ? 2 : 4;
+ else if (rec->platformID == 1 && rec->encodingID == 0)
+ ascii = 1;
+ else if (rec->platformID == 3)
+ ucs = (rec->encodingID == 1 ? 2
+ : rec->encodingID == 10 ? 4
+ : 0);
+
+ OTF_MALLOC (rec->name, rec->length + 1, (void *) rec->nameID);
SAVE_STREAM (stream, state);
SEEK_STREAM (stream, stream->pos + rec->offset);
+ READ_BYTES (stream, rec->name, rec->length);
+ RESTORE_STREAM (stream, state);
+ rec->name[rec->length] = 0;
- if (bytes == 1)
+ if (ascii)
{
- 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] = '?';
+ rec->ascii = 1;
}
- else if (bytes == 2)
+ else if (ucs == 2)
{
- OTF_MALLOC (str, rec->length / 2 + 1, (void *) rec->nameID);
+ rec->ascii = 1;
for (i = 0; i < rec->length / 2; i++)
{
- READ_USHORT (stream, c);
- if (c >= 128)
- c = '?';
- str[i] = c;
+ if (rec->name[i * 2] > 0
+ || rec->name[i * 2 + 1] >= 128)
+ {
+ rec->ascii = 0;
+ break;
+ }
}
+ if (rec->ascii)
+ for (i = 0; i < rec->length / 2; i++)
+ rec->name[i] = rec->name[i * 2 + 1];
+ rec->name[i] = 0;
}
- else if (bytes == 4)
+ else if (ucs == 4)
{
- OTF_MALLOC (str, rec->length / 4 + 1, (void *) rec->nameID);
+ rec->ascii = 1;
for (i = 0; i < rec->length / 4; i++)
{
- READ_ULONG (stream, c);
- if (c >= 128)
- c = '?';
- str[i] = c;
+ if (rec->name[i * 4] > 0
+ || rec->name[i * 4 + 1] > 0
+ || rec->name[i * 4 + 2] > 0
+ || rec->name[i * 2 + 3] >= 128)
+ {
+ rec->ascii = 0;
+ break;
+ }
}
+ if (rec->ascii)
+ for (i = 0; i < rec->length / 4; i++)
+ rec->name[i] = rec->name[i * 4 + 3];
+ rec->name[i] = 0;
}
- str[i] = '\0';
- RESTORE_STREAM (stream, state);
- return str;
+
+ return 0;
}
static void *
OTF_NameRecord *rec = name->nameRecord + i;
int nameID = rec->nameID;
- 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);
- }
+ read_name (otf, stream, rec);
+
+ if (nameID >= OTF_max_nameID)
+ continue;
+ if (! name->name[nameID]
+ && rec->ascii)
+ name->name[nameID] = (char *) rec->name;
}
return name;
char *errfmt = "cmap%s";
void *errret = NULL;
OTF_cmap *cmap;
+ int unicode_bmp_index = -1, unicode_full_index = -1;
int i;
OTF_CALLOC (cmap, 1, "");
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);
+ unsigned platformID, encodingID;
+
+ READ_USHORT (stream, platformID);
+ cmap->EncodingRecord[i].platformID = platformID;
+ READ_USHORT (stream, encodingID);
+ cmap->EncodingRecord[i].encodingID = encodingID;
READ_ULONG (stream, cmap->EncodingRecord[i].offset);
- if (cmap->EncodingRecord[i].platformID == 3
- && cmap->EncodingRecord[i].encodingID == 1)
- cmap->Unicode = cmap->EncodingRecord + i;
+ if (platformID == 0)
+ {
+ if (encodingID <= 3)
+ unicode_bmp_index = i;
+ else
+ unicode_full_index = i;
+ }
+ else if (platformID == 3)
+ {
+ if (encodingID == 1)
+ unicode_bmp_index = i;
+ else if (encodingID == 10)
+ unicode_full_index = i;
+ }
}
for (i = 0; i < cmap->numTables; i++)
{
break;
case 2:
+ {
+ OTF_EncodingSubtable2 *sub2;
+ int j, max_key, remaining_bytes;
+
+ OTF_MALLOC (sub2, 1, " (EncodingSubtable2)");
+ cmap->EncodingRecord[i].subtable.f.f2 = sub2;
+ for (j = 0, max_key = 0; j < 256; j++)
+ {
+ READ_USHORT (stream, sub2->subHeaderKeys[j]);
+ if (max_key < sub2->subHeaderKeys[j])
+ max_key = sub2->subHeaderKeys[j];
+ }
+ max_key += 8;
+ sub2->subHeaderCount = max_key / 8;
+ OTF_MALLOC (sub2->subHeaders, max_key / 8, " (subHeaders)");
+ for (j = 0; j < sub2->subHeaderCount; j++)
+ {
+ READ_USHORT (stream, sub2->subHeaders[j].firstCode);
+ READ_USHORT (stream, sub2->subHeaders[j].entryCount);
+ READ_SHORT (stream, sub2->subHeaders[j].idDelta);
+ READ_USHORT (stream, sub2->subHeaders[j].idRangeOffset);
+ /* Make it offset from sub2->glyphIndexArray. */
+ sub2->subHeaders[j].idRangeOffset -= max_key - (j * 8 + 6);
+ }
+ sub2->glyphIndexCount = (cmap->EncodingRecord[i].subtable.length
+ - 262 - max_key);
+ OTF_MALLOC (sub2->glyphIndexArray, sub2->glyphIndexCount,
+ " (glyphIndexArray)");
+ READ_BYTES (stream, sub2->glyphIndexArray, sub2->glyphIndexCount);
+ }
break;
case 4:
for (j = 0; j < sub4->GlyphCount; j++)
READ_USHORT (stream, sub4->glyphIdArray[j]);
}
+ break;
+
+ case 6:
+ {
+ OTF_EncodingSubtable6 *sub6;
+ int j;
+
+ OTF_MALLOC (sub6, 1, " (EncodingSubtable6)");
+ cmap->EncodingRecord[i].subtable.f.f6 = sub6;
+ READ_USHORT (stream, sub6->firstCode);
+ READ_USHORT (stream, sub6->entryCount);
+ OTF_MALLOC (sub6->glyphIdArray, sub6->entryCount, " (GlyphCount)");
+ for (j = 0; j < sub6->entryCount; j++)
+ READ_USHORT (stream, sub6->glyphIdArray[j]);
+ }
+ break;
+
+ case 8:
+ {
+ OTF_EncodingSubtable8 *sub8;
+ int j;
+
+ OTF_MALLOC (sub8, 1, " (EncodingSubtable8)");
+ cmap->EncodingRecord[i].subtable.f.f8 = sub8;
+ for (j = 0; j < 8192; j++)
+ READ_BYTES (stream, sub8->is32, 8192);
+ READ_ULONG (stream, sub8->nGroups);
+ OTF_MALLOC (sub8->Groups, sub8->nGroups, " (Groups)");
+ for (j = 0; j < sub8->nGroups; j++)
+ {
+ READ_ULONG (stream, sub8->Groups[i].startCharCode);
+ READ_ULONG (stream, sub8->Groups[i].endCharCode);
+ READ_ULONG (stream, sub8->Groups[i].startGlyphID);
+ }
+ }
+ break;
+
+ case 10:
+ {
+ OTF_EncodingSubtable10 *sub10;
+ int j;
+
+ OTF_MALLOC (sub10, 1, " (EncodingSubtable10)");
+ cmap->EncodingRecord[i].subtable.f.f10 = sub10;
+ READ_ULONG (stream, sub10->startCharCode);
+ READ_ULONG (stream, sub10->numChars);
+ OTF_MALLOC (sub10->glyphs, sub10->numChars, " (GlyphCount)");
+ for (j = 0; j < sub10->numChars; j++)
+ READ_USHORT (stream, sub10->glyphs[j]);
+ }
+ break;
+
+ case 12:
+ {
+ OTF_EncodingSubtable12 *sub12;
+ int j;
+
+ OTF_MALLOC (sub12, 1, " (EncodingSubtable12)");
+ cmap->EncodingRecord[i].subtable.f.f12 = sub12;
+ READ_ULONG (stream, sub12->nGroups);
+ OTF_MALLOC (sub12->Groups, sub12->nGroups, " (Groups)");
+ for (j = 0; j < sub12->nGroups; j++)
+ {
+ READ_ULONG (stream, sub12->Groups[i].startCharCode);
+ READ_ULONG (stream, sub12->Groups[i].endCharCode);
+ READ_ULONG (stream, sub12->Groups[i].startGlyphID);
+ }
+ }
+ break;
+
+ default:
+ OTF_ERROR (OTF_ERROR_TABLE, " (invalid Subtable format)");
+ }
+ }
+
+ if (unicode_bmp_index >= 0)
+ {
+ OTF_EncodingRecord *rec = cmap->EncodingRecord + unicode_bmp_index;
+ OTF_GlyphID glyph_id, max_glyph_id = 0;
+
+ OTF_CALLOC (cmap->unicode_table, 0x10000, "");
+ switch (rec->subtable.format)
+ {
+ case 4:
+ {
+ OTF_EncodingSubtable4 *sub4 = rec->subtable.f.f4;
+ int segCount = sub4->segCountX2 / 2;
+
+ for (i = 0; i < segCount; i++)
+ {
+ OTF_cmapSegument *seg = sub4->segments + i;
+ int c;
+
+ if (seg->idRangeOffset == 0xFFFF)
+ for (c = seg->startCount; c <= seg->endCount; c++)
+ {
+ glyph_id = c + seg->idDelta;
+ cmap->unicode_table[c] = glyph_id;
+ if (glyph_id > max_glyph_id)
+ max_glyph_id = glyph_id;
+ }
+ else
+ for (c = seg->startCount; c <= seg->endCount && c != 0xFFFF;
+ c++)
+ {
+ glyph_id = sub4->glyphIdArray[seg->idRangeOffset
+ + (c - seg->startCount)];
+ cmap->unicode_table[c] = glyph_id;
+ if (glyph_id > max_glyph_id)
+ max_glyph_id = glyph_id;
+ }
+ }
+ }
}
+
+ OTF_CALLOC (cmap->decode_table, max_glyph_id + 1, "");
+ for (i = 0; i < 0x10000; i++)
+ if (cmap->unicode_table[i])
+ cmap->decode_table[cmap->unicode_table[i]] = i;
+ cmap->max_glyph_id = max_glyph_id;
}
+
return cmap;
}
READ_GLYPHID (stream, (*ids)[i]);
return count;
}
-
+
static unsigned
read_range_records (OTF *otf, OTF_Stream *stream, OTF_RangeRecord **record)
{
int errret = -1;
OTF_StreamState state;
int count;
-
+
READ_OFFSET (stream, coverage->offset);
SAVE_STREAM (stream, state);
SEEK_STREAM (stream, offset + coverage->offset);
char *errfmt = "ClassDef%s";
int errret = -1;
OTF_StreamState state;
-
+
READ_OFFSET (stream, class->offset);
if (! class->offset)
return 0;
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;
READ_UINT16 (stream, count);
if (! count)
OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
- OTF_MALLOC (*set, count, "");
+ OTF_CALLOC (*set, count, "");
for (i = 0; i < count; i++)
/* Offset can be zero. */
READ_OFFSET (stream, (*set)[i].offset);
= read_glyph_ids (otf, stream,
(OTF_GlyphID **) &(*rule)[i].LookAhead, 0, -1);
(*rule)[i].LookupCount
- = read_lookup_record_list (otf, stream,
+ = read_lookup_record_list (otf, stream,
&(*rule)[i].LookupRecord, -1);
if (! (*rule)[i].LookupCount)
return errret;
OTF_AlternateSet **altset)
{
char *errfmt = "AlternateSet%s";
- int errret = -1;
+ int errret = 0;
unsigned count;
int i;
return count;
}
-static int
+static int
+read_reverse_chain1 (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_Coverage *coverage,
+ OTF_GSUB_ReverseChain1 *reverse_chain)
+{
+ int count;
+
+ if (read_coverage (otf, stream, offset, coverage) < 0)
+ return -1;
+ count = read_coverage_list (otf, stream, offset,
+ &reverse_chain->Backtrack, -1);
+ if (count < 0)
+ return -1;
+ reverse_chain->BacktrackGlyphCount = (unsigned) count;
+ count = read_coverage_list (otf, stream, offset,
+ &reverse_chain->LookAhead, -1);
+ if (count <= 0)
+ return -1;
+ reverse_chain->LookaheadGlyphCount = (unsigned) count;
+ count = read_glyph_ids (otf, stream, &reverse_chain->Substitute, 0, -1);
+ if (count <= 0)
+ return -1;
+ reverse_chain->GlyphCount = count;
+ return 0;
+}
+
+static int
read_lookup_subtable_gsub (OTF *otf, OTF_Stream *stream, long offset,
unsigned type, OTF_LookupSubTableGSUB *subtable)
{
int errret = -1;
SEEK_STREAM (stream, offset);
- READ_UINT16 (stream, subtable->Format);
+ READ_USHORT (stream, subtable->Format);
sprintf (errfmt, "GSUB Lookup %d-%d%%s", type, subtable->Format);
switch (type)
{
else
OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
break;
-
+
case 3:
if (subtable->Format == 1)
{
else
OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
break;
-
+
case 6:
if (subtable->Format == 1)
{
else
OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
break;
-
+
case 7:
+ if (subtable->Format == 1)
+ {
+ unsigned ex_type;
+ long ex_offset;
+ OTF_LookupSubTableGSUB *ex_subtable;
+
+ READ_USHORT (stream, ex_type);
+ READ_ULONG (stream, ex_offset);
+ OTF_CALLOC (ex_subtable, 1, " (SubTable)");
+ if (read_lookup_subtable_gsub (otf, stream, offset + ex_offset,
+ ex_type, ex_subtable) < 0)
+ return errret;
+ subtable->u.extension1.ExtensionLookupType = ex_type;
+ subtable->u.extension1.ExtensionOffset = ex_offset;
+ subtable->u.extension1.ExtensionSubtable = ex_subtable;
+ }
+ else
+ OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
+ break;
+
case 8:
- OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
+ if (subtable->Format == 1)
+ {
+ if (read_reverse_chain1 (otf, stream, offset, &subtable->Coverage,
+ &subtable->u.reverse_chain1) < 0)
+ return errret;
+ }
+ else
+ OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
break;
default:
OTF_StreamState state;
int size, i;
+ memset (value_record, 0, sizeof (OTF_ValueRecord));
if (! bit)
return 0;
for (i = 0, size = 0; i < 8; i++)
if (bit & OTF_XPlacement)
READ_INT16 (stream, value_record->XPlacement);
- if (bit & OTF_XPlacement)
+ if (bit & OTF_YPlacement)
READ_INT16 (stream, value_record->YPlacement);
if (bit & OTF_XAdvance)
READ_INT16 (stream, value_record->XAdvance);
int errret = -1;
OTF_StreamState state;
int i;
-
+
READ_OFFSET (stream, array->offset);
SAVE_STREAM (stream, state);
SEEK_STREAM (stream, offset + array->offset);
int errret = -1;
OTF_StreamState state;
int i, j;
-
+
READ_OFFSET (stream, array->offset);
SAVE_STREAM (stream, state);
SEEK_STREAM (stream, offset + array->offset);
return 0;
}
+static OTF_PairSet *
+read_pair_set_list (OTF *otf, OTF_Stream *stream, long offset, unsigned num,
+ enum OTF_ValueFormat bit1, enum OTF_ValueFormat bit2)
+{
+ char *errfmt = "PairSet%s";
+ void *errret = NULL;
+ OTF_StreamState state;
+ OTF_PairSet *set;
+ int i, j;
+
+ OTF_MALLOC (set, num, "");
+ for (i = 0; i < num; i++)
+ READ_OFFSET (stream, set[i].offset);
+ SAVE_STREAM (stream, state);
+ for (i = 0; i < num; i++)
+ {
+ SEEK_STREAM (stream, offset + set[i].offset);
+ READ_UINT16 (stream, set[i].PairValueCount);
+ OTF_MALLOC (set[i].PairValueRecord, set[i].PairValueCount, "");
+ for (j = 0; j < set[i].PairValueCount; j++)
+ {
+ OTF_PairValueRecord *rec = set[i].PairValueRecord + j;
+
+ READ_UINT16 (stream, rec->SecondGlyph);
+ read_value_record (otf, stream, offset, bit1, &rec->Value1);
+ read_value_record (otf, stream, offset, bit2, &rec->Value2);
+ }
+ }
+ RESTORE_STREAM (stream, state);
+ return set;
+}
static OTF_Class1Record *
read_class1_record_list (OTF *otf, OTF_Stream *stream, long offset,
return rec;
}
-static int
+static unsigned
+read_entry_exit_list (OTF *otf, OTF_Stream *stream, long offset,
+ OTF_EntryExitRecord **rec)
+{
+ char *errfmt = "EntryExitSet%s";
+ int errret = 0;
+ unsigned count;
+ int i;
+ OTF_StreamState state;
+
+ READ_UINT16 (stream, count);
+ if (! count)
+ OTF_ERROR (OTF_ERROR_TABLE, " (zero count)");
+ OTF_MALLOC (*rec, count, "");
+ for (i = 0; i < count; i++)
+ {
+ READ_OFFSET (stream, (*rec)[i].EntryAnchor.offset);
+ READ_OFFSET (stream, (*rec)[i].ExitAnchor.offset);
+ }
+ SAVE_STREAM (stream, state);
+ for (i = 0; i < count; i++)
+ {
+ if (read_anchor (otf, stream, offset, &(*rec)[i].EntryAnchor) < 0)
+ return -1;
+ if (read_anchor (otf, stream, offset, &(*rec)[i].ExitAnchor) < 0)
+ return -1;
+ }
+ RESTORE_STREAM (stream, state);
+ return count;
+}
+
+static int
+read_ligature_attach (OTF *otf, OTF_Stream *stream, long offset,
+ unsigned ClassCount, OTF_LigatureAttach *attach)
+{
+ char *errfmt = "LigatureAttach%s";
+ int errret = 1;
+ int i, j;
+
+ SEEK_STREAM (stream, offset + attach->offset);
+ READ_UINT16 (stream, attach->ComponentCount);
+ OTF_MALLOC (attach->ComponentRecord, attach->ComponentCount, "");
+ for (i = 0; i < attach->ComponentCount; i++)
+ {
+ OTF_MALLOC (attach->ComponentRecord[i].LigatureAnchor, ClassCount,
+ " (ComponentRecord)");
+ for (j = 0; j < ClassCount; j++)
+ READ_OFFSET (stream,
+ attach->ComponentRecord[i].LigatureAnchor[j].offset);
+ }
+ for (i = 0; i < attach->ComponentCount; i++)
+ for (j = 0; j < ClassCount; j++)
+ {
+ if (attach->ComponentRecord[i].LigatureAnchor[j].offset)
+ {
+ if (read_anchor (otf, stream, offset + attach->offset,
+ &attach->ComponentRecord[i].LigatureAnchor[j]) < 0)
+ return -1;
+ }
+ else
+ attach->ComponentRecord[i].LigatureAnchor[j].AnchorFormat = 0;
+ }
+ return 0;
+}
+
+static int
+read_ligature_array (OTF *otf, OTF_Stream *stream, long offset,
+ unsigned class_count, OTF_LigatureArray *array)
+{
+ char *errfmt = "LigatureArray%s";
+ int errret = -1;
+ OTF_StreamState state;
+ int i;
+
+ READ_OFFSET (stream, array->offset);
+ SAVE_STREAM (stream, state);
+ SEEK_STREAM (stream, offset + array->offset);
+ READ_UINT16 (stream, array->LigatureCount);
+ OTF_MALLOC (array->LigatureAttach, array->LigatureCount, "");
+ for (i = 0; i < array->LigatureCount; i++)
+ READ_OFFSET (stream, array->LigatureAttach[i].offset);
+ for (i = 0; i < array->LigatureCount; i++)
+ read_ligature_attach (otf, stream, offset + array->offset,
+ class_count, array->LigatureAttach + i);
+ RESTORE_STREAM (stream, state);
+ return 0;
+}
+
+static int
read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream,
long offset, unsigned type,
OTF_LookupSubTableGPOS *subtable)
case 1:
if (subtable->Format == 1)
{
+ if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0)
+ return -1;
READ_UINT16 (stream, subtable->u.single1.ValueFormat);
read_value_record (otf, stream, offset,
subtable->u.single1.ValueFormat,
OTF_GPOS_Single2 *single2 = &subtable->u.single2;
int i;
+ if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0)
+ return -1;
READ_UINT16 (stream, single2->ValueFormat);
READ_UINT16 (stream, single2->ValueCount);
OTF_CALLOC (single2->Value, single2->ValueCount," (ValueRecord)");
case 2:
if (subtable->Format == 1)
{
- OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
+ if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0)
+ return -1;
+ READ_UINT16 (stream, subtable->u.pair1.ValueFormat1);
+ READ_UINT16 (stream, subtable->u.pair1.ValueFormat2);
+ READ_UINT16 (stream, subtable->u.pair1.PairSetCount);
+ subtable->u.pair1.PairSet
+ = read_pair_set_list (otf, stream, offset,
+ subtable->u.pair1.PairSetCount,
+ subtable->u.pair1.ValueFormat1,
+ subtable->u.pair1.ValueFormat2);
+ if (! subtable->u.pair1.PairSet)
+ return -1;
}
else if (subtable->Format == 2)
{
- SEEK_STREAM (stream, offset + 2);
- read_coverage (otf, stream, offset, &subtable->Coverage);
+ if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0)
+ return -1;
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);
+ if (read_class_def (otf, stream, offset,
+ &subtable->u.pair2.ClassDef1) < 0
+ || read_class_def (otf, stream, offset,
+ &subtable->u.pair2.ClassDef2) < 0)
+ return -1;
READ_UINT16 (stream, subtable->u.pair2.Class1Count);
READ_UINT16 (stream, subtable->u.pair2.Class2Count);
subtable->u.pair2.Class1Record
subtable->u.pair2.ValueFormat1,
subtable->u.pair2.Class2Count,
subtable->u.pair2.ValueFormat2);
+ if (! subtable->u.pair2.Class1Record)
+ return -1;
}
else
OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
break;
-
+
case 3:
- OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
+ if (subtable->Format == 1)
+ {
+ if (read_coverage (otf, stream, offset, &subtable->Coverage) < 0)
+ return -1;
+ subtable->u.cursive1.EntryExitCount
+ = read_entry_exit_list (otf, stream, offset,
+ &subtable->u.cursive1.EntryExitRecord);
+ if (! subtable->u.cursive1.EntryExitCount)
+ return -1;
+ }
+ else
+ OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
break;
case 4:
break;
case 5:
- OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
+ if (subtable->Format == 1)
+ {
+ read_coverage (otf, stream, offset, &subtable->Coverage);
+ read_coverage (otf, stream, offset,
+ &subtable->u.mark_lig1.LigatureCoverage);
+ READ_UINT16 (stream, subtable->u.mark_lig1.ClassCount);
+ read_mark_array (otf, stream, offset,
+ &subtable->u.mark_lig1.MarkArray);
+ read_ligature_array (otf, stream, offset,
+ subtable->u.mark_lig1.ClassCount,
+ &subtable->u.mark_lig1.LigatureArray);
+ }
break;
case 6:
break;
case 9:
- OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)");
+ if (subtable->Format == 1)
+ {
+ unsigned ex_type;
+ long ex_offset;
+ OTF_LookupSubTableGPOS *ex_subtable;
+
+ READ_USHORT (stream, ex_type);
+ READ_ULONG (stream, ex_offset);
+ OTF_CALLOC (ex_subtable, 1, " (SubTable)");
+ if (read_lookup_subtable_gpos (otf, stream, offset + ex_offset,
+ ex_type, ex_subtable) < 0)
+ return errret;
+ subtable->u.extension1.ExtensionLookupType = ex_type;
+ subtable->u.extension1.ExtensionOffset = ex_offset;
+ subtable->u.extension1.ExtensionSubtable = ex_subtable;
+ }
+ else
+ OTF_ERROR (OTF_ERROR_TABLE, " (Invalid SubFormat)");
break;
default:
int
read_offset_table (OTF *otf, OTF_Stream *stream, OTF_OffsetTable *table)
-{
+{
int errret = -1;
READ_FIXED (stream, table->sfnt_version);
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;
return 0;
}
+static OTF_TableInfo *
+get_table_info (OTF *otf, char *name)
+{
+ char *errfmt = "OTF Table Read%s";
+ OTF_TableInfo *errret = NULL;
+ OTF_InternalData *internal_data = otf->internal_data;
+ OTF_TableInfo *table_info;
+ OTF_Tag tag = OTF_tag (name);
+
+ if (! tag)
+ OTF_ERROR (OTF_ERROR_TABLE, " (invalid table name)");
+
+ if (tag == OTF_tag ("head"))
+ table_info = internal_data->table_info + OTF_TABLE_TYPE_HEAD;
+ else if (tag == OTF_tag ("name"))
+ table_info = internal_data->table_info + OTF_TABLE_TYPE_NAME;
+ else if (tag == OTF_tag ("cmap"))
+ table_info = internal_data->table_info + OTF_TABLE_TYPE_CMAP;
+ else if (tag == OTF_tag ("GDEF"))
+ table_info = internal_data->table_info + OTF_TABLE_TYPE_GDEF;
+ else if (tag == OTF_tag ("GSUB"))
+ table_info = internal_data->table_info + OTF_TABLE_TYPE_GSUB;
+ else if (tag == OTF_tag ("GPOS"))
+ table_info = internal_data->table_info + OTF_TABLE_TYPE_GPOS;
+ else
+ OTF_ERROR (OTF_ERROR_TABLE, " (unsupported table name)");
+
+ if (*table_info->address)
+ /* Already read. */
+ return table_info;
+ if (! table_info->stream)
+ OTF_ERROR (OTF_ERROR_TABLE, " (table not found)");
+ if (! table_info->reader)
+ OTF_ERROR (OTF_ERROR_TABLE, " (invalid contents)");
+ return table_info;
+}
+
+
\f
/*** (2) API for reading OTF */
void *errret = NULL;
OTF *otf;
OTF_InternalData *internal_data;
-
+ int len = strlen (otf_name);
+ const char *ext = otf_name + (len - 4);
+
+ if (len < 4
+ || ext[0] != '.'
+ || (ext[1] != 'O' && ext[1] != 'T' && ext[1] != 'o' && ext[1] != 't')
+ || (ext[2] != 'T' && ext[2] != 't')
+ || (ext[3] != 'F' && ext[3] != 'f'))
+ OTF_ERROR (OTF_ERROR_FILE, otf_name);
fp = fopen (otf_name, "r");
if (! fp)
OTF_ERROR (OTF_ERROR_FILE, otf_name);
}
free (internal_data);
}
+ if (otf->filename)
+ free (otf->filename);
free (otf);
}
int
OTF_get_table (OTF *otf, char *name)
{
- char *errfmt = "OTF Table Read%s";
- int errret = -1;
- OTF_InternalData *internal_data = otf->internal_data;
- OTF_TableInfo *table_info;
- OTF_Tag tag = OTF_tag (name);
-
- if (! tag)
- OTF_ERROR (OTF_ERROR_TABLE, " (invalid table name)");
-
- if (tag == OTF_tag ("head"))
- table_info = internal_data->table_info + OTF_TABLE_TYPE_HEAD;
- else if (tag == OTF_tag ("name"))
- table_info = internal_data->table_info + OTF_TABLE_TYPE_NAME;
- else if (tag == OTF_tag ("cmap"))
- table_info = internal_data->table_info + OTF_TABLE_TYPE_CMAP;
- else if (tag == OTF_tag ("GDEF"))
- table_info = internal_data->table_info + OTF_TABLE_TYPE_GDEF;
- else if (tag == OTF_tag ("GSUB"))
- table_info = internal_data->table_info + OTF_TABLE_TYPE_GSUB;
- else if (tag == OTF_tag ("GPOS"))
- table_info = internal_data->table_info + OTF_TABLE_TYPE_GPOS;
- else
- OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported table name)");
+ OTF_TableInfo *table_info = get_table_info (otf, name);
- if (*table_info->address)
- /* Already read. */
- return 0;
- if (! table_info->stream)
- OTF_ERROR (OTF_ERROR_TABLE, " (table not found)");
- if (! table_info->reader)
- OTF_ERROR (OTF_ERROR_TABLE, " (invalid contents)");
+ if (! table_info)
+ return -1;
*table_info->address = (*table_info->reader) (otf, table_info->stream);
free_stream (table_info->stream);
if (! *table_info->address)
{
table_info->reader = NULL;
- return errret;
+ return -1;
}
-
return 0;
}
+/*** (2-4) OTF_check_table() */
+
+int
+OTF_check_table (OTF *otf, char *name)
+{
+ return (get_table_info (otf, name) ? 0 : -1);
+}
+
+
+
\f
/*** (5) API miscellaneous ***/