os/textandloc/fontservices/textshaperplugin/IcuSource/layout/KernTable.cpp
changeset 0 bde4ae8d615e
     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 +