*/
-typedef struct
-{
- FILE *fp;
- char *name;
- long pos;
- long bufsize;
- long allocated;
- unsigned char *buf;
-} OTF_Stream;
-
typedef long OTF_StreamState;
OTF_Stream *
-stream_open (char *filename)
+make_stream ()
{
- FILE *fp;
OTF_Stream *stream;
- char *errfmt = "stream open for %s";
+ char *errfmt = "stream creation%s";
void *errret = NULL;
- fp = fopen (filename, "r");
- if (! fp)
- OTF_ERROR (OTF_ERROR_FILE, filename);
- OTF_CALLOC (stream, 1, filename);
- stream->fp = fp;
+ OTF_CALLOC (stream, 1, "");
return stream;
}
int
-stream_setup (OTF_Stream *stream, long offset, int nbytes, char *name)
+setup_stream (OTF_Stream *stream, FILE *fp, long offset, int nbytes,
+ char *name)
{
char *errfmt = "stream setup for %s";
int errret = -1;
stream->allocated = nbytes;
}
stream->bufsize = nbytes;
- if (fseek (stream->fp, offset, SEEK_SET) < 0)
+ if (fseek (fp, offset, SEEK_SET) < 0)
OTF_ERROR (OTF_ERROR_FILE, stream->name);
- if (fread (stream->buf, 1, nbytes, stream->fp) != nbytes)
+ if (fread (stream->buf, 1, nbytes, fp) != nbytes)
OTF_ERROR (OTF_ERROR_FILE, stream->name);
return 0;
}
void
-stream_close (OTF_Stream *stream)
+free_stream (OTF_Stream *stream)
{
- fclose (stream->fp);
+ free (stream->buf);
free (stream);
}
-#define STREAM_SAVE_STATE(stream, state) ((state) = (stream)->pos)
-#define STREAM_RESTORE_STATE(stream, state) ((stream)->pos = (state))
-#define STREAM_SEEK(stream, offset) ((stream)->pos = (offset))
-
-int
-stream_overrun (OTF_Stream *stream)
-{
- char *errfmt = "buffer overrun in %s";
- int errret = -1;
-
- OTF_ERROR (OTF_ERROR_TABLE, (stream)->name);
-}
+#define SAVE_STREAM(stream, state) ((state) = (stream)->pos)
+#define RESTORE_STREAM(stream, state) ((stream)->pos = (state))
+#define SEEK_STREAM(stream, offset) ((stream)->pos = (offset))
#define STREAM_CHECK_SIZE(stream, size) \
if ((stream)->pos + (size) > (stream)->bufsize) \
{ \
- stream_overrun (stream); \
+ char *errfmt = "buffer overrun in %s"; \
+ \
+ OTF_ERROR (OTF_ERROR_TABLE, (stream)->name); \
return errret; \
} \
else
return 0;
}
-static int
+static OTF_Tag
read_table_directory (OTF_Stream *stream, OTF_TableDirectory *table)
{
- int errret = -1;
-
- READ_TAG (stream, table->tag);
+ 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 0;
+ return tag;
}
\f
-OTF_head *
+static void *
read_head_table (OTF_Stream *stream)
{
char *errfmt = "head%s";
return head;
}
+static void
+free_head_table (OTF_head *head)
+{
+ free (head);
+}
+
\f
static int
int errret = -1;
int i, j, k;
- STREAM_SEEK (stream, offset);
+ SEEK_STREAM (stream, offset);
READ_USHORT (stream, list->ScriptCount);
- OTF_MALLOC (list->ScriptRecord, list->ScriptCount, "");
OTF_CALLOC (list->Script, list->ScriptCount, "");
for (i = 0; i < list->ScriptCount; i++)
{
- READ_TAG (stream, list->ScriptRecord[i].ScriptTag);
- READ_OFFSET (stream, list->ScriptRecord[i].Script);
+ 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 + list->ScriptRecord[i].Script;
+ long script_offset = offset + script->offset;
- STREAM_SEEK (stream, 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_LangSys *langsys = &script->DefaultLangSys;
- STREAM_SEEK (stream, script_offset + script->DefaultLangSysOffset);
+ SEEK_STREAM (stream, script_offset + script->DefaultLangSysOffset);
READ_OFFSET (stream, langsys->LookupOrder);
READ_USHORT (stream, langsys->ReqFeatureIndex);
READ_USHORT (stream, langsys->FeatureCount);
{
OTF_LangSys *langsys = script->LangSys + j;
- STREAM_SEEK (stream,
+ SEEK_STREAM (stream,
script_offset + script->LangSysRecord[j].LangSys);
READ_OFFSET (stream, langsys->LookupOrder);
READ_USHORT (stream, langsys->ReqFeatureIndex);
int i, j;
READ_UINT16 (stream, list->FeatureCount);
- OTF_MALLOC (list->FeatureRecord, list->FeatureCount, "");
OTF_CALLOC (list->Feature, list->FeatureCount, "");
for (i = 0; i < list->FeatureCount; i++)
{
- READ_TAG (stream, list->FeatureRecord[i].FeatureTag);
- READ_OFFSET (stream, list->FeatureRecord[i].Feature);
+ 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;
- STREAM_SEEK (stream, offset + list->FeatureRecord[i].Feature);
+ SEEK_STREAM (stream, offset + feature->offset);
READ_OFFSET (stream, feature->FeatureParams);
READ_UINT16 (stream, feature->LookupCount);
OTF_MALLOC (feature->LookupListIndex, feature->LookupCount,
int errret = -1;
int i, j;
- STREAM_SEEK (stream, offset);
+ SEEK_STREAM (stream, offset);
READ_UINT16 (stream, list->LookupCount);
- OTF_MALLOC (list->LookupOffset, list->LookupCount, "");
OTF_CALLOC (list->Lookup, list->LookupCount, "");
for (i = 0; i < list->LookupCount; i++)
- READ_OFFSET (stream, list->LookupOffset[i]);
+ READ_OFFSET (stream, list->Lookup[i].offset);
for (i = 0; i < list->LookupCount; i++)
{
OTF_Lookup *lookup = list->Lookup + i;
- STREAM_SEEK (stream, offset + list->LookupOffset[i]);
+ SEEK_STREAM (stream, offset + lookup->offset);
READ_UINT16 (stream, lookup->LookupType);
READ_UINT16 (stream, lookup->LookupFlag);
READ_UINT16 (stream, lookup->SubTableCount);
for (j = 0; j < lookup->SubTableCount; j++)
{
long this_offset
- = offset + list->LookupOffset[i] + lookup->SubTableOffset[j];
+ = offset + lookup->offset + lookup->SubTableOffset[j];
if (read_lookup_subtable_gsub (stream, this_offset,
lookup->LookupType,
for (j = 0; j < lookup->SubTableCount; j++)
{
long this_offset
- = offset + list->LookupOffset[i] + lookup->SubTableOffset[j];
+ = offset + lookup->offset + lookup->SubTableOffset[j];
if (read_lookup_subtable_gpos (stream, this_offset,
lookup->LookupType,
int count;
READ_OFFSET (stream, coverage->offset);
- STREAM_SAVE_STATE (stream, state);
- STREAM_SEEK (stream, offset + coverage->offset);
+ SAVE_STREAM (stream, state);
+ SEEK_STREAM (stream, offset + coverage->offset);
READ_UINT16 (stream, coverage->CoverageFormat);
if (coverage->CoverageFormat == 1)
count = read_glyph_ids (stream, &coverage->table.GlyphArray, 0);
if (count < 0)
return -1;
coverage->Count = (unsigned) count;
- STREAM_RESTORE_STATE (stream, state);
+ RESTORE_STREAM (stream, state);
return 0;
}
char *errfmt = "ClassDef%s";
int errret = -1;
- STREAM_SEEK (stream, class->offset);
+ SEEK_STREAM (stream, class->offset);
READ_UINT16 (stream, class->ClassFormat);
if (class->ClassFormat == 1)
{
OTF_StreamState state;
READ_OFFSET (stream, class->offset);
- STREAM_SAVE_STATE (stream, state);
- STREAM_SEEK (stream, offset + class->offset);
+ SAVE_STREAM (stream, state);
+ SEEK_STREAM (stream, offset + class->offset);
READ_UINT16 (stream, class->ClassFormat);
if (class->ClassFormat == 1)
{
else
OTF_ERROR (OTF_ERROR_TABLE, " (Invalid format)");
- STREAM_RESTORE_STATE (stream, state);
+ RESTORE_STREAM (stream, state);
return 0;
}
+static void
+free_class_def (OTF_ClassDef *class)
+{
+ if (class->ClassFormat == 1)
+ {
+ if (class->f.f1.GlyphCount)
+ free (class->f.f1.ClassValueArray);
+ }
+ else if (class->ClassFormat == 2)
+ {
+
+ }
+}
+
+
static int
read_device_table (OTF_Stream *stream, long offset, OTF_DeviceTable *table)
{
int int8 : 8;
} intval;
- STREAM_SEEK (stream, offset + table->offset);
+ SEEK_STREAM (stream, offset + table->offset);
READ_UINT16 (stream, table->StartSize);
READ_UINT16 (stream, table->EndSize);
READ_UINT16 (stream, table->DeltaFormat);
\f
/* GSUB */
-static int
-read_gsub_header (OTF_Stream *stream, OTF_GSUBHeader *header)
-{
- int errret = -1;
-
- READ_FIXED (stream, header->Version);
- READ_OFFSET (stream, header->ScriptList);
- READ_OFFSET (stream, header->FeatureList);
- READ_OFFSET (stream, header->LookupList);
- return 0;
-}
-
-static OTF_GSUB *
+static void *
read_gsub_table (OTF_Stream *stream)
{
char *errfmt = "GSUB%s";
OTF_GSUB *gsub;
OTF_CALLOC (gsub, 1, "");
- if (read_gsub_header (stream, &gsub->header) < 0
- || read_script_list (stream, gsub->header.ScriptList,
- &gsub->script_list) < 0
- || read_feature_list (stream, gsub->header.FeatureList,
- &gsub->feature_list) < 0
- || read_lookup_list (stream, gsub->header.LookupList,
- &gsub->lookup_list, 1) < 0)
+ 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 (stream, gsub->ScriptList.offset,
+ &gsub->ScriptList) < 0
+ || read_feature_list (stream, gsub->FeatureList.offset,
+ &gsub->FeatureList) < 0
+ || read_lookup_list (stream, gsub->LookupList.offset,
+ &gsub->LookupList, 1) < 0)
return NULL;
return gsub;
}
READ_OFFSET (stream, (*seq)[i].offset);
for (i = 0; i < count; i++)
{
- STREAM_SEEK (stream, offset + (*seq)[i].offset);
+ SEEK_STREAM (stream, offset + (*seq)[i].offset);
(*seq)[i].GlyphCount = read_glyph_ids (stream, &(*seq)[i].Substitute, 0);
if (! (*seq)[i].GlyphCount)
return 0;
READ_OFFSET (stream, (*ligature)[i].offset);
for (i = 0; i < count; i++)
{
- STREAM_SEEK (stream, offset + (*ligature)[i].offset);
+ SEEK_STREAM (stream, offset + (*ligature)[i].offset);
READ_GLYPHID (stream, (*ligature)[i].LigGlyph);
(*ligature)[i].CompCount
= read_glyph_ids (stream, &(*ligature)[i].Component, -1);
{
int lig_count;
- STREAM_SEEK (stream, offset + (*ligset)[i].offset);
+ SEEK_STREAM (stream, offset + (*ligset)[i].offset);
lig_count = read_ligature (stream, offset + (*ligset)[i].offset,
&(*ligset)[i].Ligature);
if (lig_count < 0)
READ_OFFSET (stream, (*rule)[i].offset);
for (i = 0; i < count; i++)
{
- STREAM_SEEK (stream, offset + (*rule)[i].offset);
+ SEEK_STREAM (stream, offset + (*rule)[i].offset);
(*rule)[i].BacktrackGlyphCount
= read_glyph_ids (stream, &(*rule)[i].Backtrack, 0);
if (! (*rule)[i].BacktrackGlyphCount)
READ_OFFSET (stream, (*set)[i].offset);
for (i = 0; i < count; i++)
{
- STREAM_SEEK (stream, offset + (*set)[i].offset);
+ SEEK_STREAM (stream, offset + (*set)[i].offset);
(*set)[i].ChainSubRuleCount
= read_chain_subrule (stream, offset + (*set)[i].offset,
&(*set)[i].ChainSubRule);
READ_OFFSET (stream, (*rule)[i].offset);
for (i = 0; i < count; i++)
{
- STREAM_SEEK (stream, offset + (*rule)[i].offset);
+ SEEK_STREAM (stream, offset + (*rule)[i].offset);
(*rule)[i].BacktrackGlyphCount
= read_glyph_ids (stream, (OTF_GlyphID **) &(*rule)[i].Backtrack, 0);
if (! (*rule)[i].BacktrackGlyphCount)
READ_OFFSET (stream, (*set)[i].offset);
for (i = 0; i < count; i++)
{
- STREAM_SEEK (stream, offset + (*set)[i].offset);
+ SEEK_STREAM (stream, offset + (*set)[i].offset);
(*set)[i].ChainSubClassRuleCnt
= read_chain_subclass_rule (stream, offset + (*set)[i].offset,
&(*set)[i].ChainSubClassRule);
int errret = -1;
int count;
- STREAM_SEEK (stream, offset);
+ SEEK_STREAM (stream, offset);
READ_UINT16 (stream, subtable->Format);
switch (type)
{
READ_OFFSET (stream, value_record->XAdvDevice.offset);
if (bit & OTF_YAdvDevice)
READ_OFFSET (stream, value_record->YAdvDevice.offset);
- STREAM_SAVE_STATE (stream, state);
+ SAVE_STREAM (stream, state);
if (value_record->XPlaDevice.offset)
{
if (read_device_table (stream, offset, &value_record->XPlaDevice) < 0)
if (read_device_table (stream, offset, &value_record->YAdvDevice) < 0)
return -1;
}
- STREAM_RESTORE_STATE (stream, state);
+ RESTORE_STREAM (stream, state);
return 0;
}
char *errfmt = "Anchor%s";
int errret = -1;
- STREAM_SEEK (stream, offset + anchor->offset);
+ SEEK_STREAM (stream, offset + anchor->offset);
READ_UINT16 (stream, anchor->AnchorFormat);
READ_INT16 (stream, anchor->XCoordinate);
READ_INT16 (stream, anchor->YCoordinate);
int i;
READ_OFFSET (stream, array->offset);
- STREAM_SAVE_STATE (stream, state);
- STREAM_SEEK (stream, offset + 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++)
if (read_anchor (stream, offset + array->offset,
&array->MarkRecord[i].MarkAnchor) < 0)
return -1;;
- STREAM_RESTORE_STATE (stream, state);
+ RESTORE_STREAM (stream, state);
return 0;
}
int i, j;
READ_OFFSET (stream, array->offset);
- STREAM_SAVE_STATE (stream, state);
- STREAM_SEEK (stream, offset + array->offset);
+ SAVE_STREAM (stream, state);
+ SEEK_STREAM (stream, offset + array->offset);
READ_UINT16 (stream, array->BaseCount);
OTF_MALLOC (array->BaseRecord, array->BaseCount, "");
for (i = 0; i < array->BaseCount; i++)
if (read_anchor (stream, offset + array->offset,
&array->BaseRecord[i].BaseAnchor[j]) < 0)
return -1;
- STREAM_RESTORE_STATE (stream, state);
+ RESTORE_STREAM (stream, state);
return 0;
}
char *errfmt = "GPOS LookupSubTable%s";
int errret = -1;
- STREAM_SEEK (stream, offset);
+ SEEK_STREAM (stream, offset);
READ_UINT16 (stream, subtable->Format);
switch (type)
{
}
else if (subtable->Format == 2)
{
- STREAM_SEEK (stream, offset + 2);
+ SEEK_STREAM (stream, offset + 2);
read_coverage (stream, offset, &subtable->Coverage);
READ_UINT16 (stream, subtable->sub.gpos.pair2.ValueFormat1);
READ_UINT16 (stream, subtable->sub.gpos.pair2.ValueFormat2);
}
-static OTF_GPOS *
+static void *
read_gpos_table (OTF_Stream *stream)
{
char *errfmt = "GPOS%s";
void *errret = NULL;
OTF_GPOS *gpos;
- OTF_MALLOC (gpos, 1, "");
- if (read_gsub_header (stream, (OTF_GPOSHeader *) &gpos->header) < 0
- || read_script_list (stream, gpos->header.ScriptList,
- &gpos->script_list) < 0
- || read_feature_list (stream, gpos->header.FeatureList,
- &gpos->feature_list) < 0
- || read_lookup_list (stream, gpos->header.LookupList,
- &gpos->lookup_list, 0) < 0)
+ 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 (stream, gpos->ScriptList.offset,
+ &gpos->ScriptList) < 0
+ || read_feature_list (stream, gpos->FeatureList.offset,
+ &gpos->FeatureList) < 0
+ || read_lookup_list (stream, gpos->LookupList.offset,
+ &gpos->LookupList, 0) < 0)
return NULL;
return gpos;
}
{
int count;
- STREAM_SEEK (stream, offset + list->AttachPoint[i].offset);
+ 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)");
return 0;
}
+static void
+free_attach_list (OTF_AttachList *list)
+{
+}
+
static int
read_caret_value (OTF_Stream *stream, long offset, OTF_CaretValue *caret)
{
char *errfmt = "CaretValue%s";
int errret = -1;
- STREAM_SEEK (stream, offset + caret->offset);
+ SEEK_STREAM (stream, offset + caret->offset);
READ_UINT16 (stream, caret->CaretValueFormat);
if (caret->CaretValueFormat == 1)
READ_INT16 (stream, caret->f.f1.Coordinate);
{
int count;
- STREAM_SEEK (stream, offset + list->LigGlyph[i].offset);
+ 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)");
return 0;
}
+static void
+free_lig_caret_list (OTF_LigCaretList *list)
+{
+}
static int
read_gdef_header (OTF_Stream *stream, OTF_GDEFHeader *header)
return 0;
}
-static OTF_GDEF *
+static void *
read_gdef_table (OTF_Stream *stream)
{
char *errfmt = "GDEF%s";
return gdef;
}
+static void
+free_gdef_table (OTF_GDEF *gdef)
+{
+ if (gdef->header.GlyphClassDef)
+ free_class_def (&gdef->glyph_class_def);
+ if (gdef->header.AttachList)
+ free_attach_list (&gdef->attach_list);
+ if (gdef->header.LigCaretList)
+ free_lig_caret_list (&gdef->lig_caret_list);
+ if (gdef->header.MarkAttachClassDef)
+ free_class_def (&gdef->mark_attach_class_def);
+ free (gdef);
+}
+
+
\f
/* cmap */
-static OTF_cmap *
+static void *
read_cmap_table (OTF_Stream *stream)
{
char *errfmt = "cmap%s";
{
unsigned format;
- STREAM_SEEK (stream, cmap->EncodingRecord[i].offset);
+ 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);
return cmap;
}
+static void
+free_cmap_table (OTF_cmap *cmap)
+{
+ int i;
+
+ for (i = 0; i < cmap->numTables; i++)
+ {
+ unsigned format = cmap->EncodingRecord[i].subtable.format;
+
+ switch (format)
+ {
+ case 0:
+ free (cmap->EncodingRecord[i].subtable.f.f0);
+ break;
+
+ case 4:
+ {
+ OTF_EncodingSubtable4 *sub4
+ = cmap->EncodingRecord[i].subtable.f.f4;
+
+ free (sub4->glyphIdArray);
+ free (sub4->segments);
+ free (sub4);
+ }
+ break;
+ }
+ }
+ free (cmap);
+}
+
\f
-/* name */
+/* TABLE: name */
static char *
read_name (OTF_Stream *stream, OTF_NameRecord *rec, int bytes)
int i;
int c;
- STREAM_SAVE_STATE (stream, state);
- STREAM_SEEK (stream, stream->pos + rec->offset);
+ SAVE_STREAM (stream, state);
+ SEEK_STREAM (stream, stream->pos + rec->offset);
if (bytes == 1)
{
}
}
str[i] = '\0';
- STREAM_RESTORE_STATE (stream, state);
+ RESTORE_STREAM (stream, state);
return str;
}
-static OTF_name *
+static void *
read_name_table (OTF_Stream *stream)
{
char *errfmt = "name%s";
return name;
}
+static void
+free_name_table (OTF_name *name)
+{
+ int i;
+
+ for (i = 0; i < name->count; i++)
+ if (name->name[i])
+ free (name->name[i]);
+
+ free (name->nameRecord);
+ free (name);
+}
\f
+/* APIs */
+
OTF *
otf_open (char *otf_name)
{
+ FILE *fp;
char *errfmt = "OTF%s";
void *errret = NULL;
OTF_Stream *stream;
OTF *otf;
- OTF_Tag head_tag, cmap_tag, name_tag, gdef_tag, gsub_tag, gpos_tag;
+ OTF_Tag head_tag, name_tag, cmap_tag, gdef_tag, gsub_tag, gpos_tag;
int i;
- stream = stream_open (otf_name);
- if (! stream)
- return NULL;
+ fp = fopen (otf_name, "r");
+ if (! fp)
+ OTF_ERROR (OTF_ERROR_FILE, otf_name);
head_tag = otf_tag ("head");
- cmap_tag = otf_tag ("cmap");
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");
- /* Size of Offset Table in OTF is 12 bytes. */
- if (stream_setup (stream, 0, 12, "Offset Table") < 0)
+ stream = make_stream ();
+ if (! stream)
return NULL;
OTF_CALLOC_GOTO (otf, 1, " (body)", err);
otf_error = OTF_ERROR_MEMORY;
goto err;
}
+ /* Size of Offset Table is 12 bytes. */
+ if (setup_stream (stream, fp, 0, 12, "Offset Table") < 0)
+ goto err;
if (read_offset_table (stream, &otf->offset_table) < 0)
goto err;
- /* Size of each Table Directory in OTF is 16 bytes. */
- if (stream_setup (stream, 12, 16 * otf->offset_table.numTables,
+ /* Size of each Table Directory is 16 bytes. */
+ if (setup_stream (stream, fp, 12, 16 * otf->offset_table.numTables,
"Table Directory") < 0)
goto err;
OTF_CALLOC_GOTO (otf->table_dirs, otf->offset_table.numTables,
" (OffsetTable)", err);
for (i = 0; i < otf->offset_table.numTables; i++)
- if (read_table_directory (stream, otf->table_dirs + i) < 0)
- goto err;
-
- for (i = 0; i < otf->offset_table.numTables; i++)
{
- if (otf->table_dirs[i].tag == head_tag)
- {
- stream_setup (stream, otf->table_dirs[i].offset,
- otf->table_dirs[i].length, "head");
- otf->head = read_head_table (stream);
- }
- else if (otf->table_dirs[i].tag == cmap_tag)
- {
- stream_setup (stream, otf->table_dirs[i].offset,
- otf->table_dirs[i].length, "cmap");
- otf->cmap = read_cmap_table (stream);
- }
- else if (otf->table_dirs[i].tag == name_tag)
- {
- stream_setup (stream, otf->table_dirs[i].offset,
- otf->table_dirs[i].length, "name");
- otf->name = read_name_table (stream);
- }
- else if (otf->table_dirs[i].tag == gdef_tag)
- {
- stream_setup (stream, otf->table_dirs[i].offset,
- otf->table_dirs[i].length, "GDEF");
- otf->gdef = read_gdef_table (stream);
- }
- else if (otf->table_dirs[i].tag == gsub_tag)
- {
- stream_setup (stream, otf->table_dirs[i].offset,
- otf->table_dirs[i].length, "GSUB");
- otf->gsub = read_gsub_table (stream);
- }
- else if (otf->table_dirs[i].tag == gpos_tag)
+ OTF_Tag tag = read_table_directory (stream, otf->table_dirs + i);
+
+ if (! tag)
+ goto err;
+ if (tag == head_tag)
+ otf->head = otf->table_dirs + i;
+ else if (tag == name_tag)
+ otf->name = otf->table_dirs + i;
+ else if (tag == cmap_tag)
+ otf->cmap = otf->table_dirs + i;
+ else if (tag == gdef_tag)
+ otf->gdef = otf->table_dirs + i;
+ else if (tag == gsub_tag)
+ otf->gsub = otf->table_dirs + i;
+ else if (tag == gpos_tag)
+ otf->gpos = otf->table_dirs + i;
+ else
+ tag = 0;
+
+ if (tag)
{
- stream_setup (stream, otf->table_dirs[i].offset,
- otf->table_dirs[i].length, "GPOS");
- otf->gpos = read_gpos_table (stream);
+ otf->table_dirs[i].stream = make_stream ();
+ if (setup_stream (otf->table_dirs[i].stream, fp,
+ otf->table_dirs[i].offset,
+ otf->table_dirs[i].length,
+ otf->table_dirs[i].name) < 0)
+ goto err;
}
}
- stream_close (stream);
+ free_stream (stream);
+ fclose (fp);
return otf;
err:
- stream_close (stream);
+ free_stream (stream);
+ fclose (fp);
otf_close (otf);
return NULL;
}
+
void
otf_close (OTF *otf)
{
free (otf->filename);
if (otf->table_dirs)
free (otf->table_dirs);
+ if (otf->head)
+ free_head_table ((OTF_head *) otf->head->table);
+ if (otf->name)
+ free_name_table ((OTF_name *) otf->name->table);
+ if (otf->cmap)
+ free_cmap_table ((OTF_cmap *) otf->cmap->table);
+ if (otf->gdef)
+ free_gdef_table ((OTF_GDEF *) otf->gdef->table);
+}
+
+
+void *
+otf_get_table (OTF *otf, OTF_Tag tag)
+{
+ char *errfmt = "OTF Table Read";
+ void *errret = NULL;
+ OTF_TableDirectory *tabledir = NULL;
+ void *(*reader) (OTF_Stream *stream);
+
+ if (tag == otf_tag ("head"))
+ tabledir = otf->head, reader = read_head_table;
+ else if (tag == otf_tag ("name"))
+ tabledir = otf->name, reader = read_name_table;
+ else if (tag == otf_tag ("cmap"))
+ tabledir = otf->cmap, reader = read_cmap_table;
+ else if (tag == otf_tag ("GDEF"))
+ tabledir = otf->gdef, reader = read_gdef_table;
+ else if (tag == otf_tag ("GSUB"))
+ tabledir = otf->gsub, reader = read_gsub_table;
+ else if (tag == otf_tag ("GPOS"))
+ tabledir = otf->gpos, reader = read_gpos_table;
+ else
+ OTF_ERROR (OTF_ERROR_TABLE, " (unsupported)");
+
+ if (! tabledir)
+ OTF_ERROR (OTF_ERROR_TABLE, " (not found)");
+ if (! tabledir->stream)
+ OTF_ERROR (OTF_ERROR_TABLE, " (invalid contents)");
+ if (! tabledir->table)
+ {
+ tabledir->table = (*reader) (tabledir->stream);
+ if (! tabledir->table)
+ {
+ free_stream (tabledir->stream);
+ tabledir->stream = NULL;
+ OTF_ERROR (OTF_ERROR_TABLE, " (invalid contents)");
+ }
+ }
+ return tabledir->table;
}
-/* BASIC */
+/***
+ @file otf.h
+
+ @brief This file defines APIs for the OTF library.
+
+ The @e OTF @e library is for reading and processing OpenType font
+ tables. It can handle the tables of the following names.a
+
+ @li @e head:
+
+ @li @e name:
+
+ @li @e cmap:
+
+ @li @e GDEF:
+
+ @li @e GSUB:
+
+ @li @e GPOS:
+
+*/
+
+#ifndef _OTF_H_
+#define _OTF_H_
+
+////
+
+/***
+ @defgroup Error handling
+ @brief Handling errors that occur in the OTF library.
+ */
+
+/*** @{ */
+
+/***
+ @brief Global variable holding an error code.
+
+ The variable otf_error is set to one of OTF_ERROR_XXX when an
+ error is detected in OTF library. */
+extern int otf_error;
+
+/***
+ @brief Print error message.
+
+ The function otf_perror () prints $PREFIX and an error message to
+ the standard output according to the value of otf_error. If this
+ variable is zero, do nothing. */
+
+extern void otf_perror (char *prefix);
+
+
+/*** Macros for error codes. */
+
+/***
+ @brief Memory allocation error.
+
+ When the OTF library fails to allocate memory, the variable
+ otf_error is set to this value. */
#define OTF_ERROR_MEMORY -1
+
+/***
+ @brief File read error.
+
+ When the OTF library fails to read a file, the variable otf_error
+ is set to this value. */
#define OTF_ERROR_FILE -2
+
+/***
+ @brief OTF table read error.
+
+ When the OTF library detects an invalid data in an OTF table, the
+ variable otf_error is set to this value. */
#define OTF_ERROR_TABLE -3
+
+/***
+ @brief CMAP processing error.
+
+ When the OTF library an invalid data in an OTF table, the variable
+ otf_error is set to this value. */
#define OTF_ERROR_CMAP_PROC -4
#define OTF_ERROR_GDEF_PROC -5
#define OTF_ERROR_GSUB_PROC -6
#define OTF_ERROR_GPOS_PROC -7
-extern int otf_error;
+/*** @} */
+
+////
+
+/*** */
+
+/* BASIC */
typedef unsigned OTF_Tag;
typedef unsigned OTF_GlyphID;
*/
-typedef struct OTF_ScriptRecord OTF_ScriptRecord;
-typedef struct OTF_Script OTF_Script;
-
-typedef struct
-{
- unsigned ScriptCount;
- OTF_ScriptRecord *ScriptRecord;
- OTF_Script *Script;
-} OTF_ScriptList;
-
-struct OTF_ScriptRecord
-{
- OTF_Tag ScriptTag;
- OTF_Offset Script;
-};
-
typedef struct
{
OTF_Offset LookupOrder;
OTF_Offset LangSys;
} OTF_LangSysRecord;
-struct OTF_Script
+typedef struct
{
+ OTF_Tag ScriptTag;
+ OTF_Offset offset;
OTF_Offset DefaultLangSysOffset;
OTF_LangSys DefaultLangSys;
unsigned LangSysCount;
OTF_LangSysRecord *LangSysRecord;
OTF_LangSys *LangSys;
-};
-
-typedef struct OTF_FeatureRecord OTF_FeatureRecord;
-typedef struct OTF_Feature OTF_Feature;
+} OTF_Script;
typedef struct
{
- unsigned FeatureCount;
- OTF_FeatureRecord *FeatureRecord;
- OTF_Feature *Feature;
-} OTF_FeatureList;
+ OTF_Offset offset;
+ unsigned ScriptCount;
+ OTF_Script *Script;
+} OTF_ScriptList;
-struct OTF_FeatureRecord
+typedef struct
{
OTF_Tag FeatureTag;
- OTF_Offset Feature;
-};
-
-struct OTF_Feature
-{
+ OTF_Offset offset;
OTF_Offset FeatureParams;
unsigned LookupCount;
unsigned *LookupListIndex;
-};
-
-typedef struct OTF_Lookup OTF_Lookup;
+} OTF_Feature;
typedef struct
{
- unsigned LookupCount;
- OTF_Offset *LookupOffset;
- OTF_Lookup *Lookup;
-} OTF_LookupList;
+ OTF_Offset offset;
+ unsigned FeatureCount;
+ OTF_Feature *Feature;
+} OTF_FeatureList;
typedef struct OTF_LookupSubTable OTF_LookupSubTable;
-struct OTF_Lookup
+typedef struct
{
+ OTF_Offset offset;
unsigned LookupType;
unsigned LookupFlag;
unsigned SubTableCount;
OTF_Offset *SubTableOffset;
OTF_LookupSubTable *SubTable;
-};
+} OTF_Lookup;
+
+typedef struct
+{
+ OTF_Offset offset;
+ unsigned LookupCount;
+ OTF_Lookup *Lookup;
+} OTF_LookupList;
enum OTF_LookupFlagBit
{
OTF_MarkAttachmentType = 0xFF00
};
-typedef struct OTF_RangeRecord OTF_RangeRecord;
+typedef struct
+{
+ OTF_GlyphID Start;
+ OTF_GlyphID End;
+ unsigned StartCoverageIndex;
+} OTF_RangeRecord;
typedef struct
{
} table;
} OTF_Coverage;
-struct OTF_RangeRecord
+typedef struct
{
OTF_GlyphID Start;
OTF_GlyphID End;
- unsigned StartCoverageIndex;
-};
-
-typedef struct OTF_ClassRangeRecord OTF_ClassRangeRecord;
+ unsigned Class;
+} OTF_ClassRangeRecord;
typedef struct
{
} f;
} OTF_ClassDef;
-struct OTF_ClassRangeRecord
-{
- OTF_GlyphID Start;
- OTF_GlyphID End;
- unsigned Class;
-};
-
typedef struct
{
OTF_Offset offset;
typedef struct
{
OTF_Fixed Version;
- OTF_Offset ScriptList;
- OTF_Offset FeatureList;
- OTF_Offset LookupList;
-} OTF_GSUBHeader;
-
-typedef struct
-{
- OTF_GSUBHeader header;
- OTF_ScriptList script_list;
- OTF_FeatureList feature_list;
- OTF_LookupList lookup_list;
+ OTF_ScriptList ScriptList;
+ OTF_FeatureList FeatureList;
+ OTF_LookupList LookupList;
} OTF_GSUB;
\f
-typedef OTF_GSUBHeader OTF_GPOSHeader;
/* GPOS */
typedef struct
{
- OTF_GPOSHeader header;
- OTF_ScriptList script_list;
- OTF_FeatureList feature_list;
- OTF_LookupList lookup_list;
+ OTF_Fixed Version;
+ OTF_ScriptList ScriptList;
+ OTF_FeatureList FeatureList;
+ OTF_LookupList LookupList;
} OTF_GPOS;
\f
typedef struct
{
OTF_Offset offset;
- unsigned CaretValueFormat; /* 1, 2, 3 */
+ unsigned CaretValueFormat; /* 1, 2, or 3 */
union {
union {
int Coordinate;
int offset;
} OTF_NameRecord;
-#define OTF_max_nameID 20
+#define OTF_max_nameID 23
typedef struct
{
typedef struct
{
+ FILE *fp;
+ char *name;
+ long pos;
+ long bufsize;
+ long allocated;
+ unsigned char *buf;
+} OTF_Stream;
+
+typedef struct
+{
OTF_Tag tag;
+ char name[5];
unsigned checkSum;
unsigned offset;
unsigned length;
+ void *table;
+ OTF_Stream *stream;
} OTF_TableDirectory;
typedef struct
char *filename;
OTF_OffsetTable offset_table;
OTF_TableDirectory *table_dirs;
- OTF_head *head;
- OTF_name *name;
- OTF_cmap *cmap;
- OTF_GDEF *gdef;
- OTF_GSUB *gsub;
- OTF_GPOS *gpos;
+ OTF_TableDirectory *head;
+ OTF_TableDirectory *name;
+ OTF_TableDirectory *cmap;
+ OTF_TableDirectory *gdef;
+ OTF_TableDirectory *gsub;
+ OTF_TableDirectory *gpos;
/* The following tables are not yet supported. */
- // OTF_BASE *base;
- // OTF_JSTF *jstf;
+ // OTF_TableDirectory *base;
+ // OTF_TableDirectory *jstf;
} OTF;
typedef struct
} OTF_GlyphString;
+/***
+ @brief Convert a string to OTF tag.
+
+ The function otf_tag () converts the string $STR to OTF tag, and
+ return that tag. If $STR is NULL, return 0.
+
+ If $STR is not NULL, the length should be at least 4, and the
+ first 4 characters are took into an account. */
+
extern OTF_Tag otf_tag (char *str);
+/***
+ @brief Open an OpenType font file.
+
+ The function otf_open () reads the OpenType font file whose name
+ is $NAME, and return a pointer to the structure of type OTF. */
+
extern OTF *otf_open (char *name);
extern void otf_close (OTF *otf);
+extern void *otf_get_table (OTF *otf, OTF_Tag tag);
+
+extern int otf_drive_cmap (OTF *otf, OTF_GlyphString *gstring);
+extern int otf_drive_gdef (OTF *otf, OTF_GlyphString *gstring);
+extern int otf_drive_gsub (OTF *otf, OTF_Tag script_tag, OTF_Tag langsys_tag,
+ OTF_GlyphString *gstring);
+extern int otf_drive_gpos (OTF *otf, OTF_Tag script_tag, OTF_Tag langsys_tag,
+ OTF_GlyphString *gstring);
+extern int otf_drive_table (OTF *otf, OTF_Tag script_tag, OTF_Tag langsys_tag,
+ OTF_GlyphString *gstring);
-extern int otf_cmap (OTF *otf, OTF_GlyphString *gstring);
-extern int otf_gdef (OTF *otf, OTF_GlyphString *gstring);
-extern int otf_gsub (OTF *otf, OTF_Tag script_tag, OTF_Tag langsys_tag,
- OTF_GlyphString *gstring);
-extern int otf_gpos (OTF *otf, OTF_Tag script_tag, OTF_Tag langsys_tag,
- OTF_GlyphString *gstring);
-extern int otf_lookup_cmap (OTF *otf, int c);
+#endif /* not _OTF_H_ */