X-Git-Url: https://git.saurik.com/apple/icu.git/blobdiff_plain/46f4442e9a5a4f3b98b7c1083586332f6a8a99a4..ef6cf650f4a75c3f97de06b51fa104f2069b9ea2:/icuSources/layout/KernTable.cpp diff --git a/icuSources/layout/KernTable.cpp b/icuSources/layout/KernTable.cpp index 45ce091d..70005324 100644 --- a/icuSources/layout/KernTable.cpp +++ b/icuSources/layout/KernTable.cpp @@ -1,7 +1,7 @@ /* * @(#)KernTable.cpp 1.1 04/10/13 * - * (C) Copyright IBM Corp. 2004-2007 - All Rights Reserved + * (C) Copyright IBM Corp. 2004-2014 - All Rights Reserved * */ @@ -14,7 +14,7 @@ #include -#define DEBUG 0 +#define KERNTABLE_DEBUG 0 U_NAMESPACE_BEGIN @@ -24,6 +24,7 @@ struct PairInfo { le_int16 value; // fword, kern value in funits }; #define KERN_PAIRINFO_SIZE 6 +LE_CORRECT_SIZE(PairInfo, KERN_PAIRINFO_SIZE) #define SWAP_KEY(p) (((le_uint32) SWAPW((p)->left) << 16) | SWAPW((p)->right)) @@ -34,6 +35,7 @@ struct Subtable_0 { le_uint16 rangeShift; }; #define KERN_SUBTABLE_0_HEADER_SIZE 8 +LE_CORRECT_SIZE(Subtable_0, KERN_SUBTABLE_0_HEADER_SIZE) // Kern table version 0 only struct SubtableHeader { @@ -42,6 +44,7 @@ struct SubtableHeader { le_uint16 coverage; }; #define KERN_SUBTABLE_HEADER_SIZE 6 +LE_CORRECT_SIZE(SubtableHeader, KERN_SUBTABLE_HEADER_SIZE) // Version 0 only, version 1 has different layout struct KernTableHeader { @@ -49,6 +52,7 @@ struct KernTableHeader { le_uint16 nTables; }; #define KERN_TABLE_HEADER_SIZE 4 +LE_CORRECT_SIZE(KernTableHeader, KERN_TABLE_HEADER_SIZE) #define COVERAGE_HORIZONTAL 0x1 #define COVERAGE_MINIMUM 0x2 @@ -70,21 +74,21 @@ struct KernTableHeader { * TODO: support multiple subtables * TODO: respect header flags */ -KernTable::KernTable(const LEFontInstance* font, const void* tableData) - : pairs(0), font(font) +KernTable::KernTable(const LETableReference& base, LEErrorCode &success) + : pairs(), fTable(base) { - const KernTableHeader* header = (const KernTableHeader*)tableData; - if (header == 0) { -#if DEBUG + if(LE_FAILURE(success) || fTable.isEmpty()) { +#if KERNTABLE_DEBUG fprintf(stderr, "no kern data\n"); #endif return; } + LEReferenceTo header(fTable, success); -#if DEBUG +#if KERNTABLE_DEBUG // dump first 32 bytes of header for (int i = 0; i < 64; ++i) { - fprintf(stderr, "%0.2x ", ((const char*)tableData)[i]&0xff); + fprintf(stderr, "%0.2x ", ((const char*)header.getAlias())[i]&0xff); if (((i+1)&0xf) == 0) { fprintf(stderr, "\n"); } else if (((i+1)&0x7) == 0) { @@ -93,14 +97,18 @@ KernTable::KernTable(const LEFontInstance* font, const void* tableData) } #endif - if (header->version == 0 && SWAPW(header->nTables) > 0) { - const SubtableHeader* subhead = (const SubtableHeader*)((char*)tableData + KERN_TABLE_HEADER_SIZE); + if(LE_FAILURE(success)) return; - if (subhead->version == 0) { + if (!header.isEmpty() && header->version == 0 && SWAPW(header->nTables) > 0) { + LEReferenceTo subhead(header, success, KERN_TABLE_HEADER_SIZE); + + if (LE_SUCCESS(success) && !subhead.isEmpty() && subhead->version == 0) { coverage = SWAPW(subhead->coverage); if (coverage & COVERAGE_HORIZONTAL) { // only handle horizontal kerning - const Subtable_0* table = (const Subtable_0*)((char*)subhead + KERN_SUBTABLE_HEADER_SIZE); + LEReferenceTo table(subhead, success, KERN_SUBTABLE_HEADER_SIZE); + + if(table.isEmpty() || LE_FAILURE(success)) return; nPairs = SWAPW(table->nPairs); @@ -114,13 +122,27 @@ KernTable::KernTable(const LEFontInstance* font, const void* tableData) rangeShift = (nPairs * KERN_PAIRINFO_SIZE) - searchRange; #endif - pairs = (const PairInfo*)((char*)table + KERN_SUBTABLE_0_HEADER_SIZE); + if(LE_SUCCESS(success) && nPairs>0) { + // pairs is an instance member, and table is on the stack. + // set 'pairs' based on table.getAlias(). This will range check it. -#if DEBUG + pairs = LEReferenceToArrayOf(fTable, // based on overall table + success, + (const PairInfo*)table.getAlias(), // subtable 0 + .. + KERN_SUBTABLE_0_HEADER_SIZE, // .. offset of header size + nPairs); // count + } + +#if 0 + fprintf(stderr, "coverage: %0.4x nPairs: %d pairs %p\n", coverage, nPairs, pairs.getAlias()); + fprintf(stderr, " searchRange: %d entrySelector: %d rangeShift: %d\n", searchRange, entrySelector, rangeShift); + fprintf(stderr, "[[ ignored font table entries: range %d selector %d shift %d ]]\n", SWAPW(table->searchRange), SWAPW(table->entrySelector), SWAPW(table->rangeShift)); +#endif +#if KERNTABLE_DEBUG fprintf(stderr, "coverage: %0.4x nPairs: %d pairs 0x%x\n", coverage, nPairs, pairs); fprintf(stderr, " searchRange: %d entrySelector: %d rangeShift: %d\n", searchRange, entrySelector, rangeShift); - { + if(LE_SUCCESS(success) { // dump part of the pair list char ids[256]; @@ -132,12 +154,13 @@ KernTable::KernTable(const LEFontInstance* font, const void* tableData) } } - const PairInfo* p = pairs; + for (i = 0; i < nPairs; ++i) { + const PairInfo& p = pairs[i, success]; - for (i = 0; i < nPairs; ++i, p = (const PairInfo*)((char*)p+KERN_PAIRINFO_SIZE)) { le_uint16 left = p->left; le_uint16 right = p->right; + if (left < 256 && right < 256) { char c = ids[left]; @@ -161,21 +184,20 @@ KernTable::KernTable(const LEFontInstance* font, const void* tableData) } } } - + /* * Process the glyph positions. The positions array has two floats for each - * glyph, plus a trailing pair to mark the end of the last glyph. +g * glyph, plus a trailing pair to mark the end of the last glyph. */ -void KernTable::process(LEGlyphStorage& storage) +void KernTable::process(LEGlyphStorage& storage, LEErrorCode &success) { - if (pairs) { - LEErrorCode success = LE_NO_ERROR; + if (LE_SUCCESS(success) && !pairs.isEmpty()) { le_uint32 key = storage[0]; // no need to mask off high bits float adjust = 0; - for (int i = 1, e = storage.getGlyphCount(); i < e; ++i) { + for (int i = 1, e = storage.getGlyphCount(); LE_SUCCESS(success)&& i < e; ++i) { key = key << 16 | (storage[i] & 0xffff); // argh, to do a binary search, we need to have the pair list in sorted order @@ -183,36 +205,40 @@ void KernTable::process(LEGlyphStorage& storage) // so either I have to swap the element each time I examine it, or I have to swap // all the elements ahead of time and store them in the font - const PairInfo* p = pairs; - const PairInfo* tp = (const PairInfo*)((char*)p + rangeShift); + const PairInfo *p = pairs.getAlias(0, success); + + LEReferenceTo tpRef(pairs, success, rangeShift); // ((char*)pairs) + rangeShift + const PairInfo *tp = tpRef.getAlias(); + if(LE_FAILURE(success)) return; // get out. if (key > SWAP_KEY(tp)) { p = tp; } -#if DEBUG +#if KERNTABLE_DEBUG fprintf(stderr, "binary search for %0.8x\n", key); #endif le_uint32 probe = searchRange; - while (probe > KERN_PAIRINFO_SIZE) { + while (probe > KERN_PAIRINFO_SIZE && LE_SUCCESS(success)) { probe >>= 1; - tp = (const PairInfo*)((char*)p + probe); - + tpRef = LEReferenceTo(pairs, success, p, probe); // (char*)p + probe + tp = tpRef.getAlias(); le_uint32 tkey = SWAP_KEY(tp); -#if DEBUG + if(LE_FAILURE(success)) break; +#if KERNTABLE_DEBUG fprintf(stdout, " %.3d (%0.8x)\n", ((char*)tp - (char*)pairs)/KERN_PAIRINFO_SIZE, tkey); #endif - if (tkey <= key) { + if (tkey <= key && LE_SUCCESS(success)) { if (tkey == key) { le_int16 value = SWAPW(tp->value); -#if DEBUG - fprintf(stdout, "binary found kerning pair %x:%x at %d, value: 0x%x (%g)\n", +#if KERNTABLE_DEBUG + fprintf(stdout, "binary found kerning pair %x:%x at %d, value: 0x%x (%g)\n", storage[i-1], storage[i], i, value & 0xffff, font->xUnitsToPoints(value)); fflush(stdout); #endif - adjust += font->xUnitsToPoints(value); + adjust += fTable.getFont()->xUnitsToPoints(value); break; }