/* otfopen.c -- OpenType font reader.
-Copyright (C) 2003, 2004, 2005, 2006, 2008
+Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009, 2010
National Institute of Advanced Industrial Science and Technology (AIST)
Registration Number H15PRO167
#include <config.h>
#include "otf.h"
-#include "otferror.h"
+#include "internal.h"
#include FT_TRUETYPE_TABLES_H
(5) API miscellaneous
*/
+
+int debug_flag = -1;
+
+static void
+set_debug_flag ()
+{
+ debug_flag = getenv ("LIBOTF_DEBUG") != NULL;
+}
+
\f
/* (0) Stream handler
OTF_Stream *stream;
};
+struct _OTF_ApplicationData
+{
+ char *id;
+ void *data;
+ void (*freer) (void *data);
+ struct _OTF_ApplicationData *next;
+};
+
+typedef struct _OTF_ApplicationData OTF_ApplicationData;
+
struct OTF_InternalData
{
/* Information about each OTF table. */
/* Records of allocated memories. */
OTF_MemoryRecord *memory_record;
-};
+ /* Root of application data chain. */
+ OTF_ApplicationData *app_data;
+};
static OTF_MemoryRecord *
allocate_memory_record (OTF *otf)
static int
read_name (OTF *otf, OTF_Stream *stream, OTF_NameRecord *rec)
{
- char *errfmt = "nameID (%d)";
+ char errfmt[256];
int errret = -1;
OTF_StreamState state;
int ucs = 0;
int ascii = 0;
int i;
+ sprintf (errfmt, "nameID (%d)%%s", rec->nameID);
if (rec->platformID == 0)
ucs = (rec->encodingID <= 3) ? 2 : 4;
else if (rec->platformID == 1 && rec->encodingID == 0)
: rec->encodingID == 10 ? 4
: 0);
- OTF_MALLOC (rec->name, rec->length + 1, (void *) rec->nameID);
+ OTF_MALLOC (rec->name, rec->length + 1, "");
SAVE_STREAM (stream, state);
SEEK_STREAM (stream, stream->pos + rec->offset);
READ_BYTES (stream, rec->name, rec->length);
READ_ULONG (stream, nRecords);
sub14->nRecords = nRecords;
OTF_MALLOC (sub14->Records, nRecords, "(EncodingSubtable14-Records)");
- for (i = 0; i < sub14->nRecords; i++)
+ for (i = 0; i < sub14->nRecords; i++)
{
unsigned varSelector=0, defaultUVSOffset, nonDefaultUVSOffset;
READ_ULONG (stream, nonDefaultUVSOffset);
sub14->Records[i].nonDefaultUVSOffset = nonDefaultUVSOffset;
}
- for (i = 0; i < sub14->nRecords; i++)
+ for (i = 0; i < sub14->nRecords; i++)
{
OTF_VariationSelectorRecord *record = &sub14->Records[i];
unsigned defaultUVSOffset = record->defaultUVSOffset;
unsigned nonDefaultUVSOffset = record->nonDefaultUVSOffset;
- if (defaultUVSOffset)
+ if (defaultUVSOffset)
{
unsigned numUnicodeValueRanges;
SEEK_STREAM (stream, offset+defaultUVSOffset);
READ_ULONG (stream, numUnicodeValueRanges);
record->numUnicodeValueRanges = numUnicodeValueRanges;
- OTF_MALLOC (record->unicodeValueRanges,
+ OTF_MALLOC (record->unicodeValueRanges,
numUnicodeValueRanges,
"(EncodingSubtable14-Records-unicodeValueRanges)");
for (j = 0; j < numUnicodeValueRanges; j++)
{
- OTF_UnicodeValueRange *unicodeValueRange
+ OTF_UnicodeValueRange *unicodeValueRange
= &record->unicodeValueRanges[j];
unsigned startUnicodeValue;
char additionalCount;
= (unsigned short) additionalCount;
}
}
- if (nonDefaultUVSOffset)
+ if (nonDefaultUVSOffset)
{
unsigned numUVSMappings;
unicode_full_index = i;
}
}
+ cmap->table_index = unicode_full_index;
+
for (i = 0; i < cmap->numTables; i++)
{
unsigned format;
cmap->EncodingRecord[i].subtable.format = format;
if (format == 14)
{
- READ_ULONG (stream, cmap->EncodingRecord[i].subtable.length);
+ READ_ULONG (stream, cmap->EncodingRecord[i].subtable.length);
cmap->EncodingRecord[i].subtable.language = 0;
}
else
{
unsigned off;
unsigned rest = 2 * (segCount - j);
-
+
READ_USHORT (stream, off);
if (off == 0)
sub4->segments[j].idRangeOffset = 0xFFFF;
if (seg->idRangeOffset == 0xFFFF)
for (c = seg->startCount; c <= seg->endCount; c++)
{
- glyph_id = c + seg->idDelta;
+ glyph_id = (c + seg->idDelta) % 0x10000;
cmap->unicode_table[c] = glyph_id;
if (glyph_id > max_glyph_id)
max_glyph_id = glyph_id;
count = read_glyph_ids (otf, stream, &reverse_chain->Substitute, 0, -1);
if (count <= 0)
return -1;
- reverse_chain->GlyphCount = count;
+ reverse_chain->GlyphCount = count;
return 0;
}
OTF_Tag gsub_tag = OTF_tag ("GSUB");
OTF_Tag gpos_tag = OTF_tag ("GPOS");
OTF_Stream *stream = make_stream ("Offset Table");
+ unsigned char ttctag[4];
if (! stream)
return -1;
internal_data->header_stream = stream;
- /* Size of Offset Table is 12 bytes. */
- if (setup_stream (stream, fp, 0, 12) < 0)
+ /* Size of Offset Table is 12 bytes. Size of TTC header
+ (including only the an offset of the first font) is 16. */
+ if (setup_stream (stream, fp, 0, 16) < 0)
return -1;
+ READ_BYTES (stream, ttctag, 4);
+ if (memcmp (ttctag, "ttcf", 4) == 0)
+ {
+ /* This is a TrueType Collection file. We extract the first font. */
+ unsigned version, numfonts, offset;
+ READ_ULONG (stream, version);
+ READ_ULONG (stream, numfonts);
+ READ_ULONG (stream, offset); /* Offset of the first font. */
+ if (setup_stream (stream, fp, offset, 12) < 0)
+ return -1;
+ }
+ else
+ SEEK_STREAM (stream, 0L);
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) < 0)
+ if (setup_stream (stream, fp, stream->pos,
+ 16 * otf->offset_table.numTables) < 0)
return -1;
OTF_CALLOC (otf->table_dirs, otf->offset_table.numTables,
int len = strlen (otf_name);
const char *ext = otf_name + (len - 4);
+ if (debug_flag < 0)
+ set_debug_flag ();
+
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'))
+ || (strncasecmp (ext + 1, "otf", 3)
+ && strncasecmp (ext + 1, "ttf", 3)
+ && strncasecmp (ext + 1, "ttc", 3)))
OTF_ERROR (OTF_ERROR_FILE, otf_name);
fp = fopen (otf_name, "r");
if (! fp)
OTF *otf;
OTF_InternalData *internal_data;
+ if (debug_flag < 0)
+ set_debug_flag ();
+
if (! FT_IS_SFNT (face))
OTF_ERROR (OTF_ERROR_FILE, (char *) face->family_name);
otf = calloc (1, sizeof (OTF));
if (! otf)
OTF_ERROR (OTF_ERROR_MEMORY, "body allocation");
otf->filename = NULL;
-
+
internal_data = calloc (1, sizeof (OTF_InternalData));
if (! internal_data)
OTF_ERROR (OTF_ERROR_MEMORY, " (InternalData");
if (internal_data)
{
OTF_MemoryRecord *memrec = internal_data->memory_record;
+ OTF_ApplicationData *app_data = internal_data->app_data;
if (internal_data->header_stream)
free_stream (internal_data->header_stream);
if (internal_data->table_info[i].stream)
free_stream (internal_data->table_info[i].stream);
+ for (; app_data; app_data = app_data->next)
+ if (app_data->data && app_data->freer)
+ app_data->freer (app_data->data);
+
while (memrec)
{
OTF_MemoryRecord *next = memrec->next;
free (memrec);
memrec = next;
}
+
free (internal_data);
}
if (otf->filename)
if (OTF_get_features (otf, gsubp) < 0)
{
+ if (gsubp ? ! otf->gsub : ! otf->gpos)
+ return 0;
for (i = 0; i < n_features; i++)
{
OTF_Tag feature = features[i];
if ((((unsigned) feature) & 0x80000000) == 0)
return -1;
}
- return 1;
}
if (gsubp)
{
name[3] = (char) (tag & 0xFF);
name[4] = '\0';
}
+
+int
+OTF_put_data (OTF *otf, char *id, void *data, void (*freer) (void *data))
+{
+ char *errfmt = "appdata %s";
+ int errret = -1;
+ OTF_InternalData *internal_data = (OTF_InternalData *) otf->internal_data;
+ OTF_ApplicationData *app_data = internal_data->app_data;
+ int len = strlen (id) + 1;
+
+ for (; app_data; app_data = app_data->next)
+ if (memcmp (app_data->id, id, len) == 0)
+ {
+ if (app_data->data && app_data->freer)
+ app_data->freer (app_data->data);
+ break;
+ }
+ if (! app_data)
+ {
+ OTF_MALLOC (app_data, sizeof (OTF_ApplicationData), id);
+ app_data->next = internal_data->app_data;
+ internal_data->app_data = app_data;
+ OTF_MALLOC (app_data->id, len, id);
+ memcpy (app_data->id, id, len);
+ }
+ app_data->data = data;
+ app_data->freer = freer;
+ return 0;
+}
+
+void *
+OTF_get_data (OTF *otf, char *id)
+{
+ OTF_InternalData *internal_data = (OTF_InternalData *) otf->internal_data;
+ OTF_ApplicationData *app_data = internal_data->app_data;
+
+ for (; app_data; app_data = app_data->next)
+ if (strcmp (app_data->id, id) == 0)
+ return app_data->data;
+ return NULL;
+}