1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/textandloc/fontservices/textshaperplugin/IcuSource/layout/KernTable.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,195 @@
1.4 +/*
1.5 + * @(#)KernTable.cpp 1.1 04/10/13
1.6 + *
1.7 + * (C) Copyright IBM Corp. 2004-2005 - All Rights Reserved
1.8 + *
1.9 + */
1.10 +
1.11 +#include "KernTable.h"
1.12 +
1.13 +#include "LESwaps.h"
1.14 +
1.15 +#include <stdio.h>
1.16 +
1.17 +#define DEBUG 0
1.18 +
1.19 +U_NAMESPACE_BEGIN
1.20 +
1.21 +struct PairInfo {
1.22 + le_uint32 key; // sigh, MSVC compiler gags on union here
1.23 + le_int16 value; // fword, kern value in funits
1.24 +};
1.25 +#define KERN_PAIRINFO_SIZE 6
1.26 +
1.27 +struct Subtable_0 {
1.28 + le_uint16 nPairs;
1.29 + le_uint16 searchRange;
1.30 + le_uint16 entrySelector;
1.31 + le_uint16 rangeShift;
1.32 +};
1.33 +#define KERN_SUBTABLE_0_HEADER_SIZE 8
1.34 +
1.35 +// Kern table version 0 only
1.36 +struct SubtableHeader {
1.37 + le_uint16 version;
1.38 + le_uint16 length;
1.39 + le_uint16 coverage;
1.40 +};
1.41 +#define KERN_SUBTABLE_HEADER_SIZE 6
1.42 +
1.43 +// Version 0 only, version 1 has different layout
1.44 +struct KernTableHeader {
1.45 + le_uint16 version;
1.46 + le_uint16 nTables;
1.47 +};
1.48 +#define KERN_TABLE_HEADER_SIZE 4
1.49 +
1.50 +#define COVERAGE_HORIZONTAL 0x1
1.51 +#define COVERAGE_MINIMUM 0x2
1.52 +#define COVERAGE_CROSS 0x4
1.53 +#define COVERAGE_OVERRIDE 0x8
1.54 +
1.55 +KernTable::KernTable(const LEFontInstance* font, const void* tableData)
1.56 + : pairs(0), font(font)
1.57 +{
1.58 + const KernTableHeader* header = (const KernTableHeader*)tableData;
1.59 + if (header == 0) {
1.60 +#if DEBUG
1.61 + fprintf(stderr, "no kern data\n");
1.62 + fflush(stderr);
1.63 +#endif
1.64 + return;
1.65 + }
1.66 +
1.67 +#if DEBUG
1.68 + // dump first 32 bytes of header
1.69 + for (int i = 0; i < 64; ++i) {
1.70 + fprintf(stderr, "%0.2x ", ((const char*)tableData)[i]&0xff);
1.71 + if (((i+1)&0xf) == 0) {
1.72 + fprintf(stderr, "\n");
1.73 + } else if (((i+1)&0x7) == 0) {
1.74 + fprintf(stderr, " ");
1.75 + }
1.76 + }
1.77 + fflush(stderr);
1.78 +#endif
1.79 +
1.80 + if (header->version == 0 && SWAPW(header->nTables) > 0) {
1.81 + const SubtableHeader* subhead = (const SubtableHeader*)((char*)tableData + KERN_TABLE_HEADER_SIZE);
1.82 + if (subhead->version == 0) {
1.83 + coverage = SWAPW(subhead->coverage);
1.84 + if (coverage & COVERAGE_HORIZONTAL) { // only handle horizontal kerning
1.85 + const Subtable_0* table = (const Subtable_0*)((char*)subhead + KERN_SUBTABLE_HEADER_SIZE);
1.86 + nPairs = SWAPW(table->nPairs);
1.87 + searchRange = SWAPW(table->searchRange);
1.88 + entrySelector = SWAPW(table->entrySelector);
1.89 + rangeShift = SWAPW(table->rangeShift);
1.90 + pairs = (const PairInfo*)((char*)table + KERN_SUBTABLE_0_HEADER_SIZE);
1.91 +
1.92 +#if DEBUG
1.93 + fprintf(stderr, "coverage: %0.4x nPairs: %d pairs 0x%x\n", coverage, nPairs, pairs);
1.94 + fprintf(stderr, " searchRange: %d entrySelector: %d rangeShift: %d\n", searchRange, entrySelector, rangeShift);
1.95 + fflush(stderr);
1.96 +
1.97 + {
1.98 + // dump part of the pair list
1.99 + char ids[256];
1.100 + for (int i = 256; --i >= 0;) {
1.101 + LEGlyphID id = font->mapCharToGlyph(i);
1.102 + if (id < 256) {
1.103 + ids[id] = (char)i;
1.104 + }
1.105 + }
1.106 +
1.107 + const PairInfo* p = pairs;
1.108 + for (i = 0; i < nPairs; ++i, p = (const PairInfo*)((char*)p+KERN_PAIRINFO_SIZE)) {
1.109 + le_uint32 k = SWAPL(p->key);
1.110 + le_uint16 left = (k >> 16) & 0xffff;
1.111 + le_uint16 right = k & 0xffff;
1.112 + if (left < 256 && right < 256) {
1.113 + char c = ids[left];
1.114 + if (c > 0x20 && c < 0x7f) {
1.115 + fprintf(stderr, "%c/", c & 0xff);
1.116 + } else {
1.117 + fprintf(stderr, "%0.2x/", c & 0xff);
1.118 + }
1.119 + c = ids[right];
1.120 + if (c > 0x20 && c < 0x7f) {
1.121 + fprintf(stderr, "%c ", c & 0xff);
1.122 + } else {
1.123 + fprintf(stderr, "%0.2x ", c & 0xff);
1.124 + }
1.125 + }
1.126 + }
1.127 + fflush(stderr);
1.128 + }
1.129 +#endif
1.130 + }
1.131 + }
1.132 + }
1.133 +}
1.134 +
1.135 +
1.136 +/*
1.137 + * Process the glyph positions. The positions array has two floats for each
1.138 + * glyph, plus a trailing pair to mark the end of the last glyph.
1.139 + */
1.140 +//void KernTable::process(const LEGlyphID glyphs[], float* positions, le_int32 glyphCount)
1.141 +void KernTable::process(LEGlyphStorage& storage)
1.142 +{
1.143 + if (pairs) {
1.144 + LEErrorCode success = LE_NO_ERROR;
1.145 +
1.146 + le_uint32 key = storage[0]; // no need to mask off high bits
1.147 + float adjust = 0;
1.148 + for (int i = 1, e = storage.getGlyphCount(); i < e; ++i) {
1.149 + key = key << 16 | (storage[i] & 0xffff);
1.150 +
1.151 + // argh, to do a binary search, we need to have the pair list in sorted order
1.152 + // but it is not in sorted order on win32 platforms because of the endianness difference
1.153 + // so either I have to swap the element each time I examine it, or I have to swap
1.154 + // all the elements ahead of time and store them in the font
1.155 +
1.156 + const PairInfo* p = pairs;
1.157 + const PairInfo* tp = (const PairInfo*)((char*)p + rangeShift);
1.158 + if (key > SWAPL(tp->key)) {
1.159 + p = tp;
1.160 + }
1.161 +
1.162 +#if DEBUG
1.163 + fprintf(stderr, "binary search for %0.8x\n", key);
1.164 + fflush(stderr);
1.165 +#endif
1.166 +
1.167 + le_uint32 probe = searchRange;
1.168 + while (probe > KERN_PAIRINFO_SIZE) {
1.169 + probe >>= 1;
1.170 + tp = (const PairInfo*)((char*)p + probe);
1.171 + le_uint32 tkey = SWAPL(tp->key);
1.172 +#if DEBUG
1.173 + fprintf(stdout, " %.3d (%0.8x)\n", ((char*)tp - (char*)pairs)/KERN_PAIRINFO_SIZE, tkey);
1.174 + fflush(stdout);
1.175 +#endif
1.176 + if (tkey <= key) {
1.177 + if (tkey == key) {
1.178 + le_int16 value = SWAPW(tp->value);
1.179 +#if DEBUG
1.180 + fprintf(stdout, "binary found kerning pair %x:%x at %d, value: 0x%x (%g)\n",
1.181 + storage[i-1], storage[i], i, value & 0xffff, font->xUnitsToPoints(value));
1.182 + fflush(stdout);
1.183 +#endif
1.184 + adjust += font->xUnitsToPoints(value);
1.185 + break;
1.186 + }
1.187 + p = tp;
1.188 + }
1.189 + }
1.190 +
1.191 + storage.adjustPosition(i, adjust, 0, success);
1.192 + }
1.193 + storage.adjustPosition(storage.getGlyphCount(), adjust, 0, success);
1.194 + }
1.195 +}
1.196 +
1.197 +U_NAMESPACE_END
1.198 +