diff -r 000000000000 -r bde4ae8d615e os/textandloc/fontservices/textshaperplugin/IcuSource/layout/KernTable.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/os/textandloc/fontservices/textshaperplugin/IcuSource/layout/KernTable.cpp Fri Jun 15 03:10:57 2012 +0200 @@ -0,0 +1,195 @@ +/* + * @(#)KernTable.cpp 1.1 04/10/13 + * + * (C) Copyright IBM Corp. 2004-2005 - All Rights Reserved + * + */ + +#include "KernTable.h" + +#include "LESwaps.h" + +#include + +#define DEBUG 0 + +U_NAMESPACE_BEGIN + +struct PairInfo { + le_uint32 key; // sigh, MSVC compiler gags on union here + le_int16 value; // fword, kern value in funits +}; +#define KERN_PAIRINFO_SIZE 6 + +struct Subtable_0 { + le_uint16 nPairs; + le_uint16 searchRange; + le_uint16 entrySelector; + le_uint16 rangeShift; +}; +#define KERN_SUBTABLE_0_HEADER_SIZE 8 + +// Kern table version 0 only +struct SubtableHeader { + le_uint16 version; + le_uint16 length; + le_uint16 coverage; +}; +#define KERN_SUBTABLE_HEADER_SIZE 6 + +// Version 0 only, version 1 has different layout +struct KernTableHeader { + le_uint16 version; + le_uint16 nTables; +}; +#define KERN_TABLE_HEADER_SIZE 4 + +#define COVERAGE_HORIZONTAL 0x1 +#define COVERAGE_MINIMUM 0x2 +#define COVERAGE_CROSS 0x4 +#define COVERAGE_OVERRIDE 0x8 + +KernTable::KernTable(const LEFontInstance* font, const void* tableData) + : pairs(0), font(font) +{ + const KernTableHeader* header = (const KernTableHeader*)tableData; + if (header == 0) { +#if DEBUG + fprintf(stderr, "no kern data\n"); + fflush(stderr); +#endif + return; + } + +#if DEBUG + // dump first 32 bytes of header + for (int i = 0; i < 64; ++i) { + fprintf(stderr, "%0.2x ", ((const char*)tableData)[i]&0xff); + if (((i+1)&0xf) == 0) { + fprintf(stderr, "\n"); + } else if (((i+1)&0x7) == 0) { + fprintf(stderr, " "); + } + } + fflush(stderr); +#endif + + if (header->version == 0 && SWAPW(header->nTables) > 0) { + const SubtableHeader* subhead = (const SubtableHeader*)((char*)tableData + KERN_TABLE_HEADER_SIZE); + if (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); + nPairs = SWAPW(table->nPairs); + searchRange = SWAPW(table->searchRange); + entrySelector = SWAPW(table->entrySelector); + rangeShift = SWAPW(table->rangeShift); + pairs = (const PairInfo*)((char*)table + KERN_SUBTABLE_0_HEADER_SIZE); + +#if 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); + fflush(stderr); + + { + // dump part of the pair list + char ids[256]; + for (int i = 256; --i >= 0;) { + LEGlyphID id = font->mapCharToGlyph(i); + if (id < 256) { + ids[id] = (char)i; + } + } + + 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; + if (left < 256 && right < 256) { + char c = ids[left]; + if (c > 0x20 && c < 0x7f) { + fprintf(stderr, "%c/", c & 0xff); + } else { + fprintf(stderr, "%0.2x/", c & 0xff); + } + c = ids[right]; + if (c > 0x20 && c < 0x7f) { + fprintf(stderr, "%c ", c & 0xff); + } else { + fprintf(stderr, "%0.2x ", c & 0xff); + } + } + } + fflush(stderr); + } +#endif + } + } + } +} + + +/* + * 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. + */ +//void KernTable::process(const LEGlyphID glyphs[], float* positions, le_int32 glyphCount) +void KernTable::process(LEGlyphStorage& storage) +{ + if (pairs) { + LEErrorCode success = LE_NO_ERROR; + + 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) { + key = key << 16 | (storage[i] & 0xffff); + + // argh, to do a binary search, we need to have the pair list in sorted order + // 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 + + const PairInfo* p = pairs; + const PairInfo* tp = (const PairInfo*)((char*)p + rangeShift); + if (key > SWAPL(tp->key)) { + p = tp; + } + +#if DEBUG + fprintf(stderr, "binary search for %0.8x\n", key); + fflush(stderr); +#endif + + le_uint32 probe = searchRange; + while (probe > KERN_PAIRINFO_SIZE) { + probe >>= 1; + tp = (const PairInfo*)((char*)p + probe); + le_uint32 tkey = SWAPL(tp->key); +#if DEBUG + fprintf(stdout, " %.3d (%0.8x)\n", ((char*)tp - (char*)pairs)/KERN_PAIRINFO_SIZE, tkey); + fflush(stdout); +#endif + if (tkey <= key) { + 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", + storage[i-1], storage[i], i, value & 0xffff, font->xUnitsToPoints(value)); + fflush(stdout); +#endif + adjust += font->xUnitsToPoints(value); + break; + } + p = tp; + } + } + + storage.adjustPosition(i, adjust, 0, success); + } + storage.adjustPosition(storage.getGlyphCount(), adjust, 0, success); + } +} + +U_NAMESPACE_END +