X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fotfopen.c;h=c49eb1d33e6d462c14ae129b19143a3721102dc8;hb=1e0fa2bf25fc79591bf064ba67744da2398eac0e;hp=ea0445b91598c5b7bdf28d0f6f86bd268267509b;hpb=7404f27e585163a341b474fe28cd3d0df5f7e152;p=m17n%2Flibotf.git diff --git a/src/otfopen.c b/src/otfopen.c index ea0445b..c49eb1d 100644 --- a/src/otfopen.c +++ b/src/otfopen.c @@ -1,6 +1,6 @@ /* otfopen.c -- OpenType font reader. -Copyright (C) 2003, 2004, 2005, 2006 +Copyright (C) 2003, 2004, 2005, 2006, 2008, 2009 National Institute of Advanced Industrial Science and Technology (AIST) Registration Number H15PRO167 @@ -57,6 +57,15 @@ write to the Free Software Foundation, Inc., 59 Temple Place, Suite (5) API miscellaneous */ + +int debug_flag = -1; + +static void +set_debug_flag () +{ + debug_flag = getenv ("LIBOTF_DEBUG") != NULL; +} + /* (0) Stream handler @@ -91,7 +100,7 @@ typedef struct typedef long OTF_StreamState; -OTF_Stream * +static OTF_Stream * make_stream (const char *name) { OTF_Stream *stream; @@ -105,7 +114,7 @@ make_stream (const char *name) return stream; } -int +static int setup_stream (OTF_Stream *stream, FILE *fp, long offset, int nbytes) { char *errfmt = "stream setup for %s"; @@ -131,7 +140,7 @@ setup_stream (OTF_Stream *stream, FILE *fp, long offset, int nbytes) return 0; } -OTF_Stream * +static OTF_Stream * make_stream_from_ft_face (FT_Face face, const char *name) { char *errfmt = "FT_Face stream creation for %s"; @@ -161,10 +170,11 @@ make_stream_from_ft_face (FT_Face face, const char *name) return stream; } -void +static void free_stream (OTF_Stream *stream) { - free (stream->buf); + if (stream->buf) + free (stream->buf); free (stream); } @@ -199,6 +209,15 @@ free_stream (OTF_Stream *stream) (stream)->pos += 2; \ } while (0) +#define READ_UINT24(stream, var) \ + do { \ + STREAM_CHECK_SIZE ((stream), 3); \ + (var) = (((stream)->buf[(stream)->pos ] << 16) \ + | ((stream)->buf[(stream)->pos + 1] << 8) \ + | (stream)->buf[(stream)->pos + 2]); \ + (stream)->pos += 3; \ + } while (0) + #define READ_ULONG(stream, var) \ do { \ STREAM_CHECK_SIZE ((stream), 4); \ @@ -289,6 +308,16 @@ struct _OTF_TableInfo 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. */ @@ -299,6 +328,9 @@ struct OTF_InternalData /* Records of allocated memories. */ OTF_MemoryRecord *memory_record; + + /* Root of application data chain. */ + OTF_ApplicationData *app_data; }; @@ -382,13 +414,14 @@ read_head_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag) 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) @@ -398,7 +431,7 @@ read_name (OTF *otf, OTF_Stream *stream, OTF_NameRecord *rec) : 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); @@ -495,6 +528,85 @@ read_name_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag) /*** (1-4) "cmap" table */ +static OTF_EncodingSubtable14 * +read_cmap_uvs_table (OTF *otf, OTF_Stream *stream, OTF_Offset offset) +{ + OTF_EncodingSubtable14 *sub14; + char *errfmt = "cmap-uvs%s"; + void *errret = NULL; + unsigned nRecords; + unsigned i,j; + + OTF_MALLOC (sub14, 1, " (EncodingSubtable14)"); + READ_ULONG (stream, nRecords); + sub14->nRecords = nRecords; + OTF_MALLOC (sub14->Records, nRecords, "(EncodingSubtable14-Records)"); + for (i = 0; i < sub14->nRecords; i++) + { + unsigned varSelector=0, defaultUVSOffset, nonDefaultUVSOffset; + + READ_UINT24 (stream, varSelector); + sub14->Records[i].varSelector = varSelector; + READ_ULONG (stream, defaultUVSOffset); + sub14->Records[i].defaultUVSOffset = defaultUVSOffset; + READ_ULONG (stream, nonDefaultUVSOffset); + sub14->Records[i].nonDefaultUVSOffset = nonDefaultUVSOffset; + } + for (i = 0; i < sub14->nRecords; i++) + { + OTF_VariationSelectorRecord *record = &sub14->Records[i]; + unsigned defaultUVSOffset = record->defaultUVSOffset; + unsigned nonDefaultUVSOffset = record->nonDefaultUVSOffset; + + if (defaultUVSOffset) + { + unsigned numUnicodeValueRanges; + + SEEK_STREAM (stream, offset+defaultUVSOffset); + READ_ULONG (stream, numUnicodeValueRanges); + record->numUnicodeValueRanges = numUnicodeValueRanges; + OTF_MALLOC (record->unicodeValueRanges, + numUnicodeValueRanges, + "(EncodingSubtable14-Records-unicodeValueRanges)"); + for (j = 0; j < numUnicodeValueRanges; j++) + { + OTF_UnicodeValueRange *unicodeValueRange + = &record->unicodeValueRanges[j]; + unsigned startUnicodeValue; + char additionalCount; + + READ_UINT24 (stream, startUnicodeValue); + unicodeValueRange->startUnicodeValue=startUnicodeValue; + READ_BYTES (stream, &additionalCount, 1); + unicodeValueRange->additionalCount + = (unsigned short) additionalCount; + } + } + if (nonDefaultUVSOffset) + { + unsigned numUVSMappings; + + SEEK_STREAM (stream, offset+nonDefaultUVSOffset); + READ_ULONG (stream, numUVSMappings); + record->numUVSMappings = numUVSMappings; + OTF_MALLOC (record->uvsMappings, numUVSMappings, + "(EncodingSubtable14-Records-uvsMappings)"); + for (j = 0; j < numUVSMappings; j++) + { + OTF_UVSMapping *uvsMapping = &record->uvsMappings[j]; + unsigned unicodeValue; + unsigned short glyphID; + + READ_UINT24 (stream, unicodeValue); + uvsMapping->unicodeValue = unicodeValue; + READ_USHORT (stream, glyphID); + uvsMapping->glyphID = glyphID; + } + } + } + return sub14; +} + static void * read_cmap_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag) { @@ -533,6 +645,8 @@ read_cmap_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag) unicode_full_index = i; } } + cmap->table_index = unicode_full_index; + for (i = 0; i < cmap->numTables; i++) { unsigned format; @@ -540,15 +654,23 @@ read_cmap_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag) 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) + if (format == 14) { - READ_ULONG (stream, cmap->EncodingRecord[i].subtable.length); - READ_ULONG (stream, cmap->EncodingRecord[i].subtable.language); + READ_ULONG (stream, cmap->EncodingRecord[i].subtable.length); + cmap->EncodingRecord[i].subtable.language = 0; } else { - READ_USHORT (stream, cmap->EncodingRecord[i].subtable.language); + 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 + { + READ_USHORT (stream, cmap->EncodingRecord[i].subtable.language); + } } switch (format) { @@ -705,6 +827,14 @@ read_cmap_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag) } break; + case 14: + { + cmap->EncodingRecord[i].subtable.f.f14 + = read_cmap_uvs_table (otf, stream, + cmap->EncodingRecord[i].offset); + break; + } + default: OTF_ERROR (OTF_ERROR_TABLE, " (invalid Subtable format)"); } @@ -725,13 +855,13 @@ read_cmap_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag) for (i = 0; i < segCount; i++) { - OTF_cmapSegument *seg = sub4->segments + i; + OTF_cmapSegment *seg = sub4->segments + i; int c; 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; @@ -951,41 +1081,48 @@ read_device_table (OTF *otf, OTF_Stream *stream, long offset, READ_UINT16 (stream, table->EndSize); READ_UINT16 (stream, table->DeltaFormat); num = table->EndSize - table->StartSize + 1; - OTF_MALLOC (table->DeltaValue, num, ""); + if (num > 0 && table->DeltaFormat >= 1 && table->DeltaFormat <= 3) + { + OTF_MALLOC (table->DeltaValue, num, ""); - if (table->DeltaFormat == 1) - for (i = 0; i < num; i++) - { - if ((i % 8) == 0) - READ_UINT16 (stream, val); - intval.int2 = (val >> (14 - (i % 8) * 2)) & 0x03; - table->DeltaValue[i] = intval.int2; - } - else if (table->DeltaFormat == 2) - for (i = 0; i < num; i++) - { - if ((i % 4) == 0) - READ_UINT16 (stream, val); - intval.int4 = (val >> (12 - (i % 4) * 4)) & 0x0F; - table->DeltaValue[i] = intval.int4; - } - else if (table->DeltaFormat == 3) - for (i = 0; i < num; i++) - { - if ((i % 2) == 0) + if (table->DeltaFormat == 1) + for (i = 0; i < num; i++) { - READ_UINT16 (stream, val); - intval.int8 = val >> 8; - table->DeltaValue[i] = intval.int8; + if ((i % 8) == 0) + READ_UINT16 (stream, val); + intval.int2 = (val >> (14 - (i % 8) * 2)) & 0x03; + table->DeltaValue[i] = intval.int2; } - else + else if (table->DeltaFormat == 2) + for (i = 0; i < num; i++) { - intval.int8 = val >> 8; - table->DeltaValue[i] = intval.int8; + if ((i % 4) == 0) + READ_UINT16 (stream, val); + intval.int4 = (val >> (12 - (i % 4) * 4)) & 0x0F; + table->DeltaValue[i] = intval.int4; } - } + else /* (table->DeltaFormat == 3) */ + for (i = 0; i < num; i++) + { + if ((i % 2) == 0) + { + READ_UINT16 (stream, val); + intval.int8 = val >> 8; + table->DeltaValue[i] = intval.int8; + } + else + { + intval.int8 = val >> 8; + table->DeltaValue[i] = intval.int8; + } + } + } else - OTF_ERROR (OTF_ERROR_TABLE, " (Invalid format)"); + { + /* Invalid DeltaFormat but several fonts has such values (bug of + fontforge?). So accept it with NULL delta values. */ + table->DeltaValue = NULL; + } return 0; } @@ -1099,22 +1236,27 @@ read_gdef_table (OTF *otf, OTF_TableInfo *table, enum OTF_ReaderFlag flag) OTF_GDEF *gdef; OTF_CALLOC (gdef, 1, ""); - read_gdef_header (stream, (OTF_GDEFHeader *) &gdef->header); - if (gdef->header.GlyphClassDef) + if (stream->buf) { - 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); + 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); + } } *table->address = gdef; @@ -2604,7 +2746,7 @@ read_jstf_table (OTF_Stream *stream, long offset) /*** (1-11) Structure for OTF */ -int +static int read_offset_table (OTF *otf, OTF_Stream *stream, OTF_OffsetTable *table) { int errret = -1; @@ -2735,6 +2877,10 @@ read_header_part (OTF *otf, FILE *fp, FT_Face face) internal_data->table_info[OTF_TABLE_TYPE_GPOS].stream = stream; } + if (! internal_data->table_info[OTF_TABLE_TYPE_GDEF].stream) + /* We can simulate the GDEF table. */ + internal_data->table_info[OTF_TABLE_TYPE_GDEF].stream + = make_stream ("GDEF"); return 0; } @@ -2796,6 +2942,9 @@ OTF_open (const char *otf_name) 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') @@ -2846,6 +2995,9 @@ OTF_open_ft_face (FT_Face face) 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)); @@ -2880,6 +3032,7 @@ OTF_close (OTF *otf) 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); @@ -2888,6 +3041,10 @@ OTF_close (OTF *otf) 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; @@ -2897,6 +3054,7 @@ OTF_close (OTF *otf) free (memrec); memrec = next; } + free (internal_data); } if (otf->filename) @@ -3092,3 +3250,44 @@ OTF_tag_name (OTF_Tag tag, char *name) 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; +}