summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Kew <jfkthame@googlemail.com>2007-06-27 12:15:56 +0000
committerJonathan Kew <jfkthame@googlemail.com>2007-06-27 12:15:56 +0000
commit83775b3c9a877e38288b5c82b26f09624e469a29 (patch)
tree0e6e857ac86300b4fa2f38e041dc10530d8e62d1
parentf72c425a11a1d4c03760f4a510b317c7d787c258 (diff)
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
-rw-r--r--Build/source/libs/icu-xetex/layout/KernTable.cpp29
1 files 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);