From 83775b3c9a877e38288b5c82b26f09624e469a29 Mon Sep 17 00:00:00 2001 From: Jonathan Kew Date: Wed, 27 Jun 2007 12:15:56 +0000 Subject: fix truetype kern table crash on sparc64, and on OpenBSD with bad fonts git-svn-id: svn://tug.org/texlive/branches/branch2007@4511 c570f23f-e606-0410-a88d-b1316a301751 --- Build/source/libs/icu-xetex/layout/KernTable.cpp | 29 +++++++++++++++++++----- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/Build/source/libs/icu-xetex/layout/KernTable.cpp b/Build/source/libs/icu-xetex/layout/KernTable.cpp index dbadaf576d9..2a0e0715853 100644 --- a/Build/source/libs/icu-xetex/layout/KernTable.cpp +++ b/Build/source/libs/icu-xetex/layout/KernTable.cpp @@ -16,8 +16,10 @@ U_NAMESPACE_BEGIN struct PairInfo { - le_uint32 key; // sigh, MSVC compiler gags on union here + le_uint16 left; + le_uint16 right; le_int16 value; // fword, kern value in funits + le_uint32 key() const { return ((le_uint32)SWAPW(left) << 16) | SWAPW(right); } }; #define KERN_PAIRINFO_SIZE 6 @@ -81,9 +83,24 @@ KernTable::KernTable(const LEFontInstance* font, const void* tableData) if (coverage & COVERAGE_HORIZONTAL) { // only handle horizontal kerning const Subtable_0* table = (const Subtable_0*)((char*)subhead + KERN_SUBTABLE_HEADER_SIZE); nPairs = SWAPW(table->nPairs); +#if 0 // don't trust these fields as some old TTF fonts have bad data here searchRange = SWAPW(table->searchRange); entrySelector = SWAPW(table->entrySelector); rangeShift = SWAPW(table->rangeShift); +#else // recompute the binary search header fields + if (nPairs == 0) { // this probably shouldn't happen + searchRange = entrySelector = 0; + } else { + searchRange = 1; + entrySelector = 0; + while (searchRange * 2 <= nPairs) { + searchRange *= 2; + entrySelector += 1; + } + } + rangeShift = (nPairs - searchRange) * KERN_PAIRINFO_SIZE; + searchRange *= KERN_PAIRINFO_SIZE; +#endif pairs = (const PairInfo*)((char*)table + KERN_SUBTABLE_0_HEADER_SIZE); #if DEBUG @@ -103,9 +120,8 @@ KernTable::KernTable(const LEFontInstance* font, const void* tableData) const PairInfo* p = pairs; for (i = 0; i < nPairs; ++i, p = (const PairInfo*)((char*)p+KERN_PAIRINFO_SIZE)) { - le_uint32 k = SWAPL(p->key); - le_uint16 left = (k >> 16) & 0xffff; - le_uint16 right = k & 0xffff; + le_uint16 left = SWAPW(p->left); + le_uint16 right = SWAPW(p->right); if (left < 256 && right < 256) { char c = ids[left]; if (c > 0x20 && c < 0x7f) { @@ -149,10 +165,11 @@ void KernTable::process(LEGlyphStorage& storage) // but it is not in sorted order on win32 platforms because of the endianness difference // 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 + // The key() accessor on PairInfo handles the swapping if needed const PairInfo* p = pairs; const PairInfo* tp = (const PairInfo*)((char*)p + rangeShift); - if (key > SWAPL(tp->key)) { + if (key > tp->key()) { p = tp; } @@ -165,7 +182,7 @@ void KernTable::process(LEGlyphStorage& storage) while (probe > KERN_PAIRINFO_SIZE) { probe >>= 1; tp = (const PairInfo*)((char*)p + probe); - le_uint32 tkey = SWAPL(tp->key); + le_uint32 tkey = tp->key(); #if DEBUG fprintf(stdout, " %.3d (%0.8x)\n", ((char*)tp - (char*)pairs)/KERN_PAIRINFO_SIZE, tkey); fflush(stdout); -- cgit v1.2.3