X-Git-Url: http://git.chise.org/gitweb/?a=blobdiff_plain;f=src%2Fotfopen.c;h=7b6288b794394ef12b57a03c6d59ecc36fb085bd;hb=5a0f79517a9a4d354651407f080a0a17d0c869e7;hp=c50b32c8e217814c3882be59629e37cfa41fe2c2;hpb=179cf424f0663b4760e94ed2c5bb5e5653fd587c;p=m17n%2Flibotf.git diff --git a/src/otfopen.c b/src/otfopen.c index c50b32c..7b6288b 100644 --- a/src/otfopen.c +++ b/src/otfopen.c @@ -1,29 +1,30 @@ /* 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 #include #include +#include #include "otf.h" #include "otferror.h" @@ -336,52 +337,74 @@ read_head_table (OTF *otf, OTF_Stream *stream) /*** (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 * @@ -413,20 +436,13 @@ read_name_table (OTF *otf, OTF_Stream *stream) 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; @@ -441,6 +457,7 @@ read_cmap_table (OTF *otf, OTF_Stream *stream) 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, ""); @@ -449,12 +466,27 @@ read_cmap_table (OTF *otf, OTF_Stream *stream) 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++) { @@ -486,6 +518,7 @@ read_cmap_table (OTF *otf, OTF_Stream *stream) break; case 2: + OTF_ERROR (OTF_ERROR_TABLE, " (not yet supported)"); break; case 4: @@ -543,8 +576,113 @@ read_cmap_table (OTF *otf, OTF_Stream *stream) 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; } @@ -1213,7 +1351,7 @@ read_class_set_list (OTF *otf, OTF_Stream *stream, long offset, 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); @@ -1595,7 +1733,7 @@ read_alternate_set_list (OTF *otf, OTF_Stream *stream, long offset, OTF_AlternateSet **altset) { char *errfmt = "AlternateSet%s"; - int errret = -1; + int errret = 0; unsigned count; int i; @@ -1820,6 +1958,7 @@ read_value_record (OTF *otf, OTF_Stream *stream, long offset, 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++) @@ -1964,6 +2103,37 @@ read_anchor_array (OTF *otf, OTF_Stream *stream, long 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, @@ -1991,6 +2161,87 @@ read_class1_record_list (OTF *otf, OTF_Stream *stream, long offset, return rec; } +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 (read_anchor (otf, stream, offset + attach->offset, + &attach->ComponentRecord[i].LigatureAnchor[j]) < 0) + return -1; + 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, @@ -2007,6 +2258,8 @@ read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, 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, @@ -2017,6 +2270,8 @@ read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, 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)"); @@ -2031,18 +2286,30 @@ read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, 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 @@ -2051,13 +2318,26 @@ read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, 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: @@ -2078,7 +2358,18 @@ read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, 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: @@ -2145,7 +2436,24 @@ read_lookup_subtable_gpos (OTF *otf, OTF_Stream *stream, 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: @@ -2331,7 +2639,7 @@ get_table_info (OTF *otf, char *name) 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_ERROR (OTF_ERROR_TABLE, " (unsupported table name)"); if (*table_info->address) /* Already read. */ @@ -2361,7 +2669,15 @@ OTF_open (char *otf_name) 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); @@ -2428,6 +2744,8 @@ OTF_close (OTF *otf) } free (internal_data); } + if (otf->filename) + free (otf->filename); free (otf); }