1ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 2ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * @(#)KernTable.cpp 1.1 04/10/13 3ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 459d709d503bab6e2b61931737e662dd293b40578ccornelius * (C) Copyright IBM Corp. 2004-2013 - All Rights Reserved 5ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 6ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 7ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 8ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "KernTable.h" 9ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LEFontInstance.h" 10ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LEGlyphStorage.h" 11ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 12ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "LESwaps.h" 13ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include "OpenTypeUtilities.h" 14ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 15ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#include <stdio.h> 16ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 17ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define DEBUG 0 18ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 19ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_BEGIN 20ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 21ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustruct PairInfo { 22ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 left; // left glyph of kern pair 23ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 right; // right glyph of kern pair 24ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int16 value; // fword, kern value in funits 25ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 26ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define KERN_PAIRINFO_SIZE 6 2759d709d503bab6e2b61931737e662dd293b40578ccorneliusLE_CORRECT_SIZE(PairInfo, KERN_PAIRINFO_SIZE) 28ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 29ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define SWAP_KEY(p) (((le_uint32) SWAPW((p)->left) << 16) | SWAPW((p)->right)) 30ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 31ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustruct Subtable_0 { 32ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 nPairs; 33ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 searchRange; 34ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 entrySelector; 35ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 rangeShift; 36ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 37ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define KERN_SUBTABLE_0_HEADER_SIZE 8 3859d709d503bab6e2b61931737e662dd293b40578ccorneliusLE_CORRECT_SIZE(Subtable_0, KERN_SUBTABLE_0_HEADER_SIZE) 39ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 40ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Kern table version 0 only 41ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustruct SubtableHeader { 42ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 version; 43ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 length; 44ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 coverage; 45ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 46ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define KERN_SUBTABLE_HEADER_SIZE 6 4759d709d503bab6e2b61931737e662dd293b40578ccorneliusLE_CORRECT_SIZE(SubtableHeader, KERN_SUBTABLE_HEADER_SIZE) 48ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 49ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru// Version 0 only, version 1 has different layout 50ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Querustruct KernTableHeader { 51ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 version; 52ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 nTables; 53ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru}; 54ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define KERN_TABLE_HEADER_SIZE 4 5559d709d503bab6e2b61931737e662dd293b40578ccorneliusLE_CORRECT_SIZE(KernTableHeader, KERN_TABLE_HEADER_SIZE) 56ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 57ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define COVERAGE_HORIZONTAL 0x1 58ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define COVERAGE_MINIMUM 0x2 59ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define COVERAGE_CROSS 0x4 60ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#define COVERAGE_OVERRIDE 0x8 61ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 62ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 63ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This implementation has support for only one subtable, so if the font has 64ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * multiple subtables, only the first will be used. If this turns out to 65ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * be a problem in practice we should add it. 66ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 67ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This also supports only version 0 of the kern table header, only 68ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Apple supports the latter. 69ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 70ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * This implementation isn't careful about the kern table flags, and 71ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * might invoke kerning when it is not supposed to. That too I'm 72ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * leaving for a bug fix. 73ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * 74ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * TODO: support multiple subtables 75ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * TODO: respect header flags 76ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 7759d709d503bab6e2b61931737e662dd293b40578ccorneliusKernTable::KernTable(const LETableReference& base, LEErrorCode &success) 7859d709d503bab6e2b61931737e662dd293b40578ccornelius : pairs(), fTable(base) 79ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 8059d709d503bab6e2b61931737e662dd293b40578ccornelius if(LE_FAILURE(success) || fTable.isEmpty()) { 81ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if DEBUG 82ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fprintf(stderr, "no kern data\n"); 83ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif 84ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru return; 85ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 8659d709d503bab6e2b61931737e662dd293b40578ccornelius LEReferenceTo<KernTableHeader> header(fTable, success); 87ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 88ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if DEBUG 89ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // dump first 32 bytes of header 90ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (int i = 0; i < 64; ++i) { 9159d709d503bab6e2b61931737e662dd293b40578ccornelius fprintf(stderr, "%0.2x ", ((const char*)header.getAlias())[i]&0xff); 92ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (((i+1)&0xf) == 0) { 93ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fprintf(stderr, "\n"); 94ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else if (((i+1)&0x7) == 0) { 95ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fprintf(stderr, " "); 96ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 97ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 98ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif 99ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 10059d709d503bab6e2b61931737e662dd293b40578ccornelius if(LE_FAILURE(success)) return; 101ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 10259d709d503bab6e2b61931737e662dd293b40578ccornelius if (!header.isEmpty() && header->version == 0 && SWAPW(header->nTables) > 0) { 10359d709d503bab6e2b61931737e662dd293b40578ccornelius LEReferenceTo<SubtableHeader> subhead(header, success, KERN_TABLE_HEADER_SIZE); 10459d709d503bab6e2b61931737e662dd293b40578ccornelius 10559d709d503bab6e2b61931737e662dd293b40578ccornelius if (LE_SUCCESS(success) && !subhead.isEmpty() && subhead->version == 0) { 106ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru coverage = SWAPW(subhead->coverage); 107ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 108ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (coverage & COVERAGE_HORIZONTAL) { // only handle horizontal kerning 10959d709d503bab6e2b61931737e662dd293b40578ccornelius LEReferenceTo<Subtable_0> table(subhead, success, KERN_SUBTABLE_HEADER_SIZE); 11059d709d503bab6e2b61931737e662dd293b40578ccornelius 11159d709d503bab6e2b61931737e662dd293b40578ccornelius if(table.isEmpty() || LE_FAILURE(success)) return; 112ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 113ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru nPairs = SWAPW(table->nPairs); 114ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 115ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if 0 // some old fonts have bad values here... 116ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru searchRange = SWAPW(table->searchRange); 117ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru entrySelector = SWAPW(table->entrySelector); 118ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rangeShift = SWAPW(table->rangeShift); 119ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#else 120ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru entrySelector = OpenTypeUtilities::highBit(nPairs); 121ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru searchRange = (1 << entrySelector) * KERN_PAIRINFO_SIZE; 122ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru rangeShift = (nPairs * KERN_PAIRINFO_SIZE) - searchRange; 123ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif 124ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 12559d709d503bab6e2b61931737e662dd293b40578ccornelius if(LE_SUCCESS(success) && nPairs>0) { 12659d709d503bab6e2b61931737e662dd293b40578ccornelius // pairs is an instance member, and table is on the stack. 12759d709d503bab6e2b61931737e662dd293b40578ccornelius // set 'pairs' based on table.getAlias(). This will range check it. 128ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 12959d709d503bab6e2b61931737e662dd293b40578ccornelius pairs = LEReferenceToArrayOf<PairInfo>(fTable, // based on overall table 13059d709d503bab6e2b61931737e662dd293b40578ccornelius success, 13159d709d503bab6e2b61931737e662dd293b40578ccornelius (const PairInfo*)table.getAlias(), // subtable 0 + .. 13259d709d503bab6e2b61931737e662dd293b40578ccornelius KERN_SUBTABLE_0_HEADER_SIZE, // .. offset of header size 13359d709d503bab6e2b61931737e662dd293b40578ccornelius nPairs); // count 13459d709d503bab6e2b61931737e662dd293b40578ccornelius } 13559d709d503bab6e2b61931737e662dd293b40578ccornelius 13659d709d503bab6e2b61931737e662dd293b40578ccornelius#if 0 13759d709d503bab6e2b61931737e662dd293b40578ccornelius fprintf(stderr, "coverage: %0.4x nPairs: %d pairs %p\n", coverage, nPairs, pairs.getAlias()); 13859d709d503bab6e2b61931737e662dd293b40578ccornelius fprintf(stderr, " searchRange: %d entrySelector: %d rangeShift: %d\n", searchRange, entrySelector, rangeShift); 13959d709d503bab6e2b61931737e662dd293b40578ccornelius fprintf(stderr, "[[ ignored font table entries: range %d selector %d shift %d ]]\n", SWAPW(table->searchRange), SWAPW(table->entrySelector), SWAPW(table->rangeShift)); 14059d709d503bab6e2b61931737e662dd293b40578ccornelius#endif 141ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if DEBUG 142ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fprintf(stderr, "coverage: %0.4x nPairs: %d pairs 0x%x\n", coverage, nPairs, pairs); 143ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fprintf(stderr, " searchRange: %d entrySelector: %d rangeShift: %d\n", searchRange, entrySelector, rangeShift); 144ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 14559d709d503bab6e2b61931737e662dd293b40578ccornelius if(LE_SUCCESS(success) { 146ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // dump part of the pair list 147ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru char ids[256]; 148ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 149ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru for (int i = 256; --i >= 0;) { 150ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru LEGlyphID id = font->mapCharToGlyph(i); 151ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 152ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (id < 256) { 153ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru ids[id] = (char)i; 154ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 155ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 156ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 15759d709d503bab6e2b61931737e662dd293b40578ccornelius for (i = 0; i < nPairs; ++i) { 15859d709d503bab6e2b61931737e662dd293b40578ccornelius const PairInfo& p = pairs[i, success]; 159ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 160ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 left = p->left; 161ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint16 right = p->right; 162ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 16359d709d503bab6e2b61931737e662dd293b40578ccornelius 164ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (left < 256 && right < 256) { 165ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru char c = ids[left]; 166ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 167ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (c > 0x20 && c < 0x7f) { 168ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fprintf(stderr, "%c/", c & 0xff); 169ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 170ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru printf(stderr, "%0.2x/", c & 0xff); 171ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 172ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 173ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru c = ids[right]; 174ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (c > 0x20 && c < 0x7f) { 175ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fprintf(stderr, "%c ", c & 0xff); 176ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } else { 177ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fprintf(stderr, "%0.2x ", c & 0xff); 178ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 179ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 180ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 181ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 182ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif 183ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 184ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 185ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 186ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 18759d709d503bab6e2b61931737e662dd293b40578ccornelius 188ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 189ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru/* 190ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru * Process the glyph positions. The positions array has two floats for each 19159d709d503bab6e2b61931737e662dd293b40578ccorneliusg * glyph, plus a trailing pair to mark the end of the last glyph. 192ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru */ 19359d709d503bab6e2b61931737e662dd293b40578ccorneliusvoid KernTable::process(LEGlyphStorage& storage, LEErrorCode &success) 194ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru{ 19559d709d503bab6e2b61931737e662dd293b40578ccornelius if (LE_SUCCESS(success) && !pairs.isEmpty()) { 196ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 197ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint32 key = storage[0]; // no need to mask off high bits 198ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru float adjust = 0; 199ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 20059d709d503bab6e2b61931737e662dd293b40578ccornelius for (int i = 1, e = storage.getGlyphCount(); LE_SUCCESS(success)&& i < e; ++i) { 201ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru key = key << 16 | (storage[i] & 0xffff); 202ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 203ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // argh, to do a binary search, we need to have the pair list in sorted order 204ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // but it is not in sorted order on win32 platforms because of the endianness difference 205ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // so either I have to swap the element each time I examine it, or I have to swap 206ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru // all the elements ahead of time and store them in the font 207ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 20859d709d503bab6e2b61931737e662dd293b40578ccornelius const PairInfo *p = pairs.getAlias(0, success); 20959d709d503bab6e2b61931737e662dd293b40578ccornelius 21059d709d503bab6e2b61931737e662dd293b40578ccornelius LEReferenceTo<PairInfo> tpRef(pairs, success, rangeShift); // ((char*)pairs) + rangeShift 21159d709d503bab6e2b61931737e662dd293b40578ccornelius const PairInfo *tp = tpRef.getAlias(); 21259d709d503bab6e2b61931737e662dd293b40578ccornelius if(LE_FAILURE(success)) return; // get out. 213ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 214ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (key > SWAP_KEY(tp)) { 215ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru p = tp; 216ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 217ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 218ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if DEBUG 219ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fprintf(stderr, "binary search for %0.8x\n", key); 220ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif 221ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 222ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint32 probe = searchRange; 223ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 22459d709d503bab6e2b61931737e662dd293b40578ccornelius while (probe > KERN_PAIRINFO_SIZE && LE_SUCCESS(success)) { 225ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru probe >>= 1; 22659d709d503bab6e2b61931737e662dd293b40578ccornelius tpRef = LEReferenceTo<PairInfo>(pairs, success, p, probe); // (char*)p + probe 22759d709d503bab6e2b61931737e662dd293b40578ccornelius tp = tpRef.getAlias(); 228ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_uint32 tkey = SWAP_KEY(tp); 22959d709d503bab6e2b61931737e662dd293b40578ccornelius if(LE_FAILURE(success)) break; 230ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if DEBUG 231ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fprintf(stdout, " %.3d (%0.8x)\n", ((char*)tp - (char*)pairs)/KERN_PAIRINFO_SIZE, tkey); 232ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif 23359d709d503bab6e2b61931737e662dd293b40578ccornelius if (tkey <= key && LE_SUCCESS(success)) { 234ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru if (tkey == key) { 235ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru le_int16 value = SWAPW(tp->value); 236ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#if DEBUG 23759d709d503bab6e2b61931737e662dd293b40578ccornelius fprintf(stdout, "binary found kerning pair %x:%x at %d, value: 0x%x (%g)\n", 238ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru storage[i-1], storage[i], i, value & 0xffff, font->xUnitsToPoints(value)); 239ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru fflush(stdout); 240ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru#endif 24159d709d503bab6e2b61931737e662dd293b40578ccornelius adjust += fTable.getFont()->xUnitsToPoints(value); 242ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru break; 243ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 244ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 245ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru p = tp; 246ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 247ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 248ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 249ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru storage.adjustPosition(i, adjust, 0, success); 250ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 251ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 252ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru storage.adjustPosition(storage.getGlyphCount(), adjust, 0, success); 253ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru } 254ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru} 255ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 256ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste QueruU_NAMESPACE_END 257ac04d0bbe12b3ef54518635711412f178cb4d16Jean-Baptiste Queru 258