$OpenBSD: patch-libs_icu-xetex_layout_KernTable_cpp,v 1.1.1.1 2007/07/17 21:53:34 jasper Exp $
--- libs/icu-xetex/layout/KernTable.cpp.orig	Wed Jun 27 09:59:39 2007
+++ libs/icu-xetex/layout/KernTable.cpp	Wed Jun 27 10:00:16 2007
@@ -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
       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
 
 	  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);
